mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-17 22:50:51 +00:00
run gib through indent
This commit is contained in:
parent
851d203916
commit
c91137e4db
13 changed files with 974 additions and 774 deletions
354
libs/gib/exp.c
354
libs/gib/exp.c
|
@ -31,10 +31,9 @@
|
|||
#include "ops.h"
|
||||
|
||||
exp_error_t EXP_ERROR;
|
||||
char *exp_error_msg = 0;
|
||||
char *exp_error_msg = 0;
|
||||
|
||||
optable_t optable[] =
|
||||
{
|
||||
optable_t optable[] = {
|
||||
{"!", OP_Not, 1},
|
||||
{"**", OP_Exp, 2},
|
||||
{"/", OP_Div, 2},
|
||||
|
@ -55,8 +54,7 @@ optable_t optable[] =
|
|||
{"", 0, 0}
|
||||
};
|
||||
|
||||
functable_t functable[] =
|
||||
{
|
||||
functable_t functable[] = {
|
||||
{"sqrt", Func_Sqrt, 1},
|
||||
{"abs", Func_Abs, 1},
|
||||
{"sin", Func_Sin, 1},
|
||||
|
@ -69,28 +67,28 @@ functable_t functable[] =
|
|||
};
|
||||
|
||||
// Error handling
|
||||
static exp_error_t
|
||||
static exp_error_t
|
||||
EXP_Error (exp_error_t err, const char *msg)
|
||||
{
|
||||
EXP_ERROR = err;
|
||||
if (exp_error_msg)
|
||||
free (exp_error_msg);
|
||||
exp_error_msg = strdup(msg);
|
||||
return err;
|
||||
EXP_ERROR = err;
|
||||
if (exp_error_msg)
|
||||
free (exp_error_msg);
|
||||
exp_error_msg = strdup (msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
const char *
|
||||
EXP_GetErrorMsg (void)
|
||||
{
|
||||
return exp_error_msg;
|
||||
return exp_error_msg;
|
||||
}
|
||||
|
||||
static token
|
||||
*EXP_NewToken (void)
|
||||
static token *
|
||||
EXP_NewToken (void)
|
||||
{
|
||||
token *new;
|
||||
token *new;
|
||||
|
||||
new = malloc(sizeof(token));
|
||||
new = malloc (sizeof (token));
|
||||
|
||||
if (!new)
|
||||
return 0;
|
||||
|
@ -113,15 +111,16 @@ EXP_FindIndexByFunc (opfunc func)
|
|||
static optable_t *
|
||||
EXP_FindOpByStr (const char *str)
|
||||
{
|
||||
int i, len, fi;
|
||||
int i, len, fi;
|
||||
|
||||
for (i = 0, len = 0, fi = -1; optable[i].func; i++)
|
||||
if (!strncmp(str, optable[i].str, strlen(optable[i].str)) && strlen(optable[i].str) > len) {
|
||||
len = strlen(optable[i].str);
|
||||
if (!strncmp (str, optable[i].str, strlen (optable[i].str))
|
||||
&& strlen (optable[i].str) > len) {
|
||||
len = strlen (optable[i].str);
|
||||
fi = i;
|
||||
}
|
||||
if (fi >= 0)
|
||||
return optable+fi;
|
||||
return optable + fi;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -129,24 +128,26 @@ EXP_FindOpByStr (const char *str)
|
|||
static functable_t *
|
||||
EXP_FindFuncByStr (const char *str)
|
||||
{
|
||||
int i, len, fi;
|
||||
int i, len, fi;
|
||||
|
||||
for (i = 0, len = 0, fi = -1; functable[i].func; i++)
|
||||
if (!strncmp(str, functable[i].str, strlen(functable[i].str)) && strlen(functable[i].str) > len) {
|
||||
len = strlen(functable[i].str);
|
||||
if (!strncmp (str, functable[i].str, strlen (functable[i].str))
|
||||
&& strlen (functable[i].str) > len) {
|
||||
len = strlen (functable[i].str);
|
||||
fi = i;
|
||||
}
|
||||
if (fi >= 0)
|
||||
return functable+fi;
|
||||
return functable + fi;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
EXP_ContainsCommas (token *chain)
|
||||
EXP_ContainsCommas (token * chain)
|
||||
{
|
||||
token *cur;
|
||||
int paren = 0;
|
||||
token *cur;
|
||||
int paren = 0;
|
||||
|
||||
for (cur = chain; cur; cur = cur->generic.next) {
|
||||
if (cur->generic.type == TOKEN_OPAREN)
|
||||
paren++;
|
||||
|
@ -157,15 +158,15 @@ EXP_ContainsCommas (token *chain)
|
|||
if (cur->generic.type == TOKEN_COMMA)
|
||||
return 1;
|
||||
}
|
||||
return -1; // We should never get here
|
||||
return -1; // We should never get here
|
||||
}
|
||||
|
||||
static int
|
||||
EXP_DoFunction (token *chain)
|
||||
EXP_DoFunction (token * chain)
|
||||
{
|
||||
token *cur, *temp;
|
||||
double *oplist = 0;
|
||||
double value;
|
||||
token *cur, *temp;
|
||||
double *oplist = 0;
|
||||
double value;
|
||||
unsigned int numops = 0;
|
||||
|
||||
|
||||
|
@ -176,13 +177,13 @@ EXP_DoFunction (token *chain)
|
|||
temp = 0;
|
||||
if (cur->generic.type == TOKEN_NUM) {
|
||||
numops++;
|
||||
oplist = realloc(oplist, sizeof(double)*numops);
|
||||
oplist[numops-1] = cur->num.value;
|
||||
oplist = realloc (oplist, sizeof (double) * numops);
|
||||
oplist[numops - 1] = cur->num.value;
|
||||
}
|
||||
EXP_RemoveToken (cur);
|
||||
}
|
||||
if (numops == chain->func.func->operands) {
|
||||
value = chain->func.func->func(oplist, numops); // Heh
|
||||
value = chain->func.func->func (oplist, numops); // Heh
|
||||
chain->generic.type = TOKEN_NUM;
|
||||
chain->num.value = value;
|
||||
if (oplist)
|
||||
|
@ -193,17 +194,18 @@ EXP_DoFunction (token *chain)
|
|||
free (oplist);
|
||||
return -1;
|
||||
}
|
||||
return -2; // We shouldn't get here
|
||||
return -2; // We shouldn't get here
|
||||
}
|
||||
|
||||
static int
|
||||
EXP_DoUnary (token *chain)
|
||||
EXP_DoUnary (token * chain)
|
||||
{
|
||||
if (chain->generic.next->generic.type == TOKEN_OP)
|
||||
EXP_DoUnary (chain->generic.next);
|
||||
if (chain->generic.next->generic.type != TOKEN_NUM)
|
||||
return -1; // In theory, this should never happen
|
||||
chain->generic.next->num.value = chain->op.op->func(chain->generic.next->num.value, 0);
|
||||
return -1; // In theory, this should never happen
|
||||
chain->generic.next->num.value =
|
||||
chain->op.op->func (chain->generic.next->num.value, 0);
|
||||
EXP_RemoveToken (chain);
|
||||
return 0;
|
||||
}
|
||||
|
@ -211,95 +213,86 @@ EXP_DoUnary (token *chain)
|
|||
token *
|
||||
EXP_ParseString (char *str)
|
||||
{
|
||||
char buf[256];
|
||||
char buf[256];
|
||||
|
||||
token *chain, *new, *cur;
|
||||
int i,m;
|
||||
optable_t *op;
|
||||
token *chain, *new, *cur;
|
||||
int i, m;
|
||||
optable_t *op;
|
||||
functable_t *func;
|
||||
|
||||
cur = chain = EXP_NewToken();
|
||||
cur = chain = EXP_NewToken ();
|
||||
chain->generic.type = TOKEN_OPAREN;
|
||||
chain->generic.prev = 0;
|
||||
chain->generic.next = 0;
|
||||
|
||||
for (i = 0; i < strlen(str); i++)
|
||||
{
|
||||
for (i = 0; i < strlen (str); i++) {
|
||||
m = 0;
|
||||
while(isspace((byte)str[i]))
|
||||
while (isspace ((byte) str[i]))
|
||||
i++;
|
||||
if (!str[i])
|
||||
break;
|
||||
if (isdigit((byte)str[i]) || str[i] == '.')
|
||||
{
|
||||
while ((isdigit((byte)str[i]) // A number
|
||||
|| str[i] == '.' // A decimal point
|
||||
|| str[i] == 'e' // An exponent
|
||||
|| ((str[i] == '-' || str[i] == '+') && str[i-1] == 'e')) // A + or - after an exponent
|
||||
&& i < strlen(str) // We are within the string
|
||||
&& m < 256) // And there is space in the buffer
|
||||
if (isdigit ((byte) str[i]) || str[i] == '.') {
|
||||
while ((isdigit ((byte) str[i]) // A number
|
||||
|| str[i] == '.' // A decimal point
|
||||
|| str[i] == 'e' // An exponent
|
||||
|| ((str[i] == '-' || str[i] == '+')
|
||||
&& str[i - 1] == 'e')) // A + or - after an exponent
|
||||
&& i < strlen (str) // We are within the string
|
||||
&& m < 256) // And there is space in the buffer
|
||||
buf[m++] = str[i++];
|
||||
buf[m] = 0;
|
||||
new = EXP_NewToken();
|
||||
new = EXP_NewToken ();
|
||||
new->generic.type = TOKEN_NUM;
|
||||
new->num.value = atof(buf);
|
||||
new->num.value = atof (buf);
|
||||
new->generic.prev = cur;
|
||||
new->generic.next = 0;
|
||||
cur->generic.next = new;
|
||||
cur = new;
|
||||
i--;
|
||||
}
|
||||
else if (str[i] == ',')
|
||||
{
|
||||
new = EXP_NewToken();
|
||||
} else if (str[i] == ',') {
|
||||
new = EXP_NewToken ();
|
||||
new->generic.type = TOKEN_COMMA;
|
||||
new->generic.prev = cur;
|
||||
new->generic.next = 0;
|
||||
cur->generic.next = new;
|
||||
cur = new;
|
||||
}
|
||||
else if (str[i] == '(')
|
||||
{
|
||||
new = EXP_NewToken();
|
||||
} else if (str[i] == '(') {
|
||||
new = EXP_NewToken ();
|
||||
new->generic.type = TOKEN_OPAREN;
|
||||
new->generic.prev = cur;
|
||||
new->generic.next = 0;
|
||||
cur->generic.next = new;
|
||||
cur = new;
|
||||
}
|
||||
else if (str[i] == ')')
|
||||
{
|
||||
new = EXP_NewToken();
|
||||
} else if (str[i] == ')') {
|
||||
new = EXP_NewToken ();
|
||||
new->generic.type = TOKEN_CPAREN;
|
||||
new->generic.prev = cur;
|
||||
new->generic.next = 0;
|
||||
cur->generic.next = new;
|
||||
cur = new;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(!(isdigit((byte)str[i])) && !isspace((byte)str[i])
|
||||
&& str[i] != '.' && str[i] != '(' && str[i] != ')'
|
||||
&& str[i] != ',' && m < 256) {
|
||||
buf[m++] = str[i++];
|
||||
} else {
|
||||
while (!(isdigit ((byte) str[i])) && !isspace ((byte) str[i])
|
||||
&& str[i] != '.' && str[i] != '(' && str[i] != ')'
|
||||
&& str[i] != ',' && m < 256) {
|
||||
buf[m++] = str[i++];
|
||||
}
|
||||
buf[m] = 0;
|
||||
if (m)
|
||||
{
|
||||
if (m) {
|
||||
if ((op = EXP_FindOpByStr (buf))) {
|
||||
i -= (m - strlen(op->str) + 1);
|
||||
new = EXP_NewToken();
|
||||
i -= (m - strlen (op->str) + 1);
|
||||
new = EXP_NewToken ();
|
||||
new->generic.type = TOKEN_OP;
|
||||
if (*(op->str) == '-') // HACK HACK HACK
|
||||
op = optable + 6; // Always assume subtraction for - initially
|
||||
if (*(op->str) == '-') // HACK HACK HACK
|
||||
op = optable + 6; // Always assume subtraction for -
|
||||
// initially
|
||||
new->op.op = op;
|
||||
new->generic.prev = cur;
|
||||
new->generic.next = 0;
|
||||
cur->generic.next = new;
|
||||
cur = new;
|
||||
} else if ((func = EXP_FindFuncByStr(buf))) {
|
||||
i -= (m - strlen(func->str) + 1);
|
||||
new = EXP_NewToken();
|
||||
} else if ((func = EXP_FindFuncByStr (buf))) {
|
||||
i -= (m - strlen (func->str) + 1);
|
||||
new = EXP_NewToken ();
|
||||
new->generic.type = TOKEN_FUNC;
|
||||
new->func.func = func;
|
||||
new->generic.prev = cur;
|
||||
|
@ -308,13 +301,14 @@ EXP_ParseString (char *str)
|
|||
cur = new;
|
||||
} else {
|
||||
EXP_DestroyTokens (chain);
|
||||
EXP_Error (EXP_E_INVOP, va("Unknown operator or function '%s'.", buf));
|
||||
EXP_Error (EXP_E_INVOP,
|
||||
va ("Unknown operator or function '%s'.", buf));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
new = EXP_NewToken();
|
||||
new = EXP_NewToken ();
|
||||
new->generic.type = TOKEN_CPAREN;
|
||||
new->generic.prev = cur;
|
||||
new->generic.next = 0;
|
||||
|
@ -323,61 +317,73 @@ EXP_ParseString (char *str)
|
|||
}
|
||||
|
||||
exp_error_t
|
||||
EXP_SimplifyTokens (token *chain)
|
||||
EXP_SimplifyTokens (token * chain)
|
||||
{
|
||||
exp_error_t res;
|
||||
int i;
|
||||
token *cur;
|
||||
token *temp;
|
||||
int i;
|
||||
token *cur;
|
||||
token *temp;
|
||||
|
||||
/* First, get rid of parentheses */
|
||||
|
||||
for (cur = chain->generic.next; cur->generic.type != TOKEN_CPAREN; cur = cur->generic.next)
|
||||
{
|
||||
if (cur->generic.type == TOKEN_OPAREN)
|
||||
{
|
||||
res = EXP_SimplifyTokens(cur); /* Call ourself to simplify parentheses content */
|
||||
for (cur = chain->generic.next; cur->generic.type != TOKEN_CPAREN;
|
||||
cur = cur->generic.next) {
|
||||
if (cur->generic.type == TOKEN_OPAREN) {
|
||||
res = EXP_SimplifyTokens (cur); /* Call ourself to simplify
|
||||
parentheses content */
|
||||
if (res)
|
||||
return res;
|
||||
if (cur->generic.prev->generic.type == TOKEN_FUNC) { // These are arguments to a function
|
||||
if (cur->generic.prev->generic.type == TOKEN_FUNC) {
|
||||
// These are arguments to a function
|
||||
cur = cur->generic.prev;
|
||||
if (EXP_DoFunction (cur))
|
||||
return EXP_Error (EXP_E_SYNTAX, va("Invalid number of arguments to function '%s'.", cur->func.func->str));
|
||||
return EXP_Error (EXP_E_SYNTAX,
|
||||
va
|
||||
("Invalid number of arguments to function '%s'.",
|
||||
cur->func.func->str));
|
||||
} else {
|
||||
if (EXP_ContainsCommas (cur))
|
||||
return EXP_Error (EXP_E_SYNTAX, "Comma used outside of a function argument list.");
|
||||
return EXP_Error (EXP_E_SYNTAX,
|
||||
"Comma used outside of a function argument list.");
|
||||
temp = cur;
|
||||
cur = cur->generic.next;
|
||||
EXP_RemoveToken(temp); /* Remove parentheses, leaving value behind */
|
||||
EXP_RemoveToken(cur->generic.next);
|
||||
EXP_RemoveToken (temp); /* Remove parentheses, leaving value
|
||||
behind */
|
||||
EXP_RemoveToken (cur->generic.next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Next, evaluate all operators in order of operations */
|
||||
|
||||
for (i = 0; optable[i].func; i++)
|
||||
{
|
||||
for (cur = chain->generic.next; cur->generic.type != TOKEN_CPAREN; cur = cur->generic.next)
|
||||
{
|
||||
if (cur->generic.type == TOKEN_OP && cur->op.op == optable + i && cur->generic.next) {
|
||||
for (i = 0; optable[i].func; i++) {
|
||||
for (cur = chain->generic.next; cur->generic.type != TOKEN_CPAREN;
|
||||
cur = cur->generic.next) {
|
||||
if (cur->generic.type == TOKEN_OP && cur->op.op == optable + i
|
||||
&& cur->generic.next) {
|
||||
// If a unary operator is in our way, it gets evaluated early
|
||||
if (cur->generic.next->generic.type == TOKEN_OP)
|
||||
if (EXP_DoUnary (cur->generic.next))
|
||||
return EXP_Error (EXP_E_SYNTAX, va("Unary operator '%s' not followed by a unary operator or numerical value.", cur->generic.next->op.op->str));
|
||||
if (optable[i].operands == 1 && cur->generic.next->generic.type == TOKEN_NUM) {
|
||||
cur->generic.next->num.value = optable[i].func(cur->generic.next->num.value, 0);
|
||||
return EXP_Error (EXP_E_SYNTAX,
|
||||
va
|
||||
("Unary operator '%s' not followed by a unary operator or numerical value.",
|
||||
cur->generic.next->op.op->str));
|
||||
if (optable[i].operands == 1
|
||||
&& cur->generic.next->generic.type == TOKEN_NUM) {
|
||||
cur->generic.next->num.value =
|
||||
optable[i].func (cur->generic.next->num.value, 0);
|
||||
temp = cur;
|
||||
cur = cur->generic.next;
|
||||
EXP_RemoveToken(temp);
|
||||
}
|
||||
else if (cur->generic.prev->generic.type == TOKEN_NUM && cur->generic.next->generic.type == TOKEN_NUM)
|
||||
{
|
||||
cur->generic.prev->num.value = optable[i].func(cur->generic.prev->num.value, cur->generic.next->num.value);
|
||||
EXP_RemoveToken (temp);
|
||||
} else if (cur->generic.prev->generic.type == TOKEN_NUM
|
||||
&& cur->generic.next->generic.type == TOKEN_NUM) {
|
||||
cur->generic.prev->num.value =
|
||||
optable[i].func (cur->generic.prev->num.value,
|
||||
cur->generic.next->num.value);
|
||||
temp = cur;
|
||||
cur = cur->generic.prev;
|
||||
EXP_RemoveToken(temp->generic.next);
|
||||
EXP_RemoveToken(temp);
|
||||
EXP_RemoveToken (temp->generic.next);
|
||||
EXP_RemoveToken (temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -386,41 +392,39 @@ EXP_SimplifyTokens (token *chain)
|
|||
}
|
||||
|
||||
void
|
||||
EXP_RemoveToken (token *tok)
|
||||
EXP_RemoveToken (token * tok)
|
||||
{
|
||||
tok->generic.prev->generic.next = tok->generic.next;
|
||||
tok->generic.next->generic.prev = tok->generic.prev;
|
||||
free(tok);
|
||||
free (tok);
|
||||
}
|
||||
|
||||
void
|
||||
EXP_DestroyTokens (token *chain)
|
||||
EXP_DestroyTokens (token * chain)
|
||||
{
|
||||
token *temp;
|
||||
for (;chain; chain = temp)
|
||||
{
|
||||
token *temp;
|
||||
|
||||
for (; chain; chain = temp) {
|
||||
temp = chain->generic.next;
|
||||
free(chain);
|
||||
free (chain);
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
EXP_Evaluate (char *str)
|
||||
{
|
||||
token *chain;
|
||||
double res;
|
||||
token *chain;
|
||||
double res;
|
||||
|
||||
EXP_ERROR = EXP_E_NORMAL;
|
||||
|
||||
if (!(chain = EXP_ParseString (str)))
|
||||
return 0;
|
||||
if (EXP_Validate (chain))
|
||||
{
|
||||
if (EXP_Validate (chain)) {
|
||||
EXP_DestroyTokens (chain);
|
||||
return 0;
|
||||
}
|
||||
if (EXP_SimplifyTokens (chain))
|
||||
{
|
||||
if (EXP_SimplifyTokens (chain)) {
|
||||
EXP_DestroyTokens (chain);
|
||||
return 0;
|
||||
}
|
||||
|
@ -430,7 +434,7 @@ EXP_Evaluate (char *str)
|
|||
}
|
||||
|
||||
void
|
||||
EXP_InsertTokenAfter (token *spot, token *new)
|
||||
EXP_InsertTokenAfter (token * spot, token * new)
|
||||
{
|
||||
spot->generic.next->generic.prev = new;
|
||||
new->generic.next = spot->generic.next;
|
||||
|
@ -440,48 +444,63 @@ EXP_InsertTokenAfter (token *spot, token *new)
|
|||
|
||||
|
||||
exp_error_t
|
||||
EXP_Validate (token *chain)
|
||||
EXP_Validate (token * chain)
|
||||
{
|
||||
token *cur, *new;
|
||||
int paren = 0;
|
||||
token *cur, *new;
|
||||
int paren = 0;
|
||||
|
||||
for (cur = chain; cur->generic.next; cur = cur->generic.next)
|
||||
{
|
||||
for (cur = chain; cur->generic.next; cur = cur->generic.next) {
|
||||
if (cur->generic.type == TOKEN_OPAREN)
|
||||
paren++;
|
||||
if (cur->generic.type == TOKEN_CPAREN)
|
||||
paren--;
|
||||
/* Implied multiplication */
|
||||
if ((cur->generic.type == TOKEN_NUM && (
|
||||
cur->generic.next->generic.type == TOKEN_OPAREN || // 5(1+1)
|
||||
cur->generic.next->generic.type == TOKEN_FUNC || // 5 sin (1+1)
|
||||
(cur->generic.next->generic.type == TOKEN_OP && cur->generic.next->op.op->operands == 1))) || // 5!(1+1)
|
||||
(cur->generic.type == TOKEN_CPAREN && (
|
||||
cur->generic.next->generic.type == TOKEN_NUM || // (1+1)5
|
||||
cur->generic.next->generic.type == TOKEN_OPAREN))) // (1+1)(1+1)
|
||||
if ((cur->generic.type == TOKEN_NUM && (cur->generic.next->generic.type == TOKEN_OPAREN || // 5(1+1)
|
||||
cur->generic.next->generic.type == TOKEN_FUNC || // 5 sin (1+1)
|
||||
(cur->generic.next->generic.type == TOKEN_OP && cur->generic.next->op.op->operands == 1))) || // 5!(1+1)
|
||||
(cur->generic.type == TOKEN_CPAREN && (cur->generic.next->generic.type == TOKEN_NUM || // (1+1)5
|
||||
cur->generic.next->generic.type == TOKEN_OPAREN))) // (1+1)(1+1)
|
||||
{
|
||||
new = EXP_NewToken ();
|
||||
new->generic.type = TOKEN_OP;
|
||||
new->op.op = EXP_FindOpByStr ("*");
|
||||
EXP_InsertTokenAfter (cur, new);
|
||||
}
|
||||
else if ((cur->generic.type == TOKEN_OP || cur->generic.type == TOKEN_OPAREN) && cur->generic.next->generic.type == TOKEN_OP)
|
||||
{
|
||||
if (cur->generic.next->op.op->func == OP_Sub) /* Stupid hack for negation */
|
||||
} else
|
||||
if ((cur->generic.type == TOKEN_OP
|
||||
|| cur->generic.type == TOKEN_OPAREN)
|
||||
&& cur->generic.next->generic.type == TOKEN_OP) {
|
||||
if (cur->generic.next->op.op->func == OP_Sub) /* Stupid hack for
|
||||
negation */
|
||||
cur->generic.next->op.op = optable + 3;
|
||||
else if (cur->generic.next->op.op->operands == 2)
|
||||
return EXP_Error (EXP_E_SYNTAX, va ("Operator '%s' does not follow a number or numerical value.", cur->generic.next->op.op->str));
|
||||
}
|
||||
else if (cur->generic.type == TOKEN_FUNC && cur->generic.next->generic.type != TOKEN_OPAREN)
|
||||
return EXP_Error (EXP_E_SYNTAX, va("Function '%s' called without an argument list.", cur->func.func->str));
|
||||
else if (cur->generic.type == TOKEN_COMMA && ((cur->generic.prev->generic.type != TOKEN_CPAREN
|
||||
&& cur->generic.prev->generic.type != TOKEN_NUM) || paren <= 1))
|
||||
return EXP_Error (EXP_E_SYNTAX, "Comma used outside of a function or after a non-number.");
|
||||
else if (cur->generic.type == TOKEN_OP && cur->generic.next->generic.type == TOKEN_CPAREN)
|
||||
return EXP_Error (EXP_E_SYNTAX, va("Operator '%s' is missing an operand.", cur->op.op->str));
|
||||
else if (cur->generic.type == TOKEN_NUM && cur->generic.next->generic.type == TOKEN_NUM)
|
||||
return EXP_Error (EXP_E_SYNTAX, "Double number error (two numbers next two each other without an operator).");
|
||||
else if (cur->generic.type == TOKEN_OPAREN && cur->generic.next->generic.type == TOKEN_CPAREN)
|
||||
return EXP_Error (EXP_E_SYNTAX,
|
||||
va
|
||||
("Operator '%s' does not follow a number or numerical value.",
|
||||
cur->generic.next->op.op->str));
|
||||
} else if (cur->generic.type == TOKEN_FUNC
|
||||
&& cur->generic.next->generic.type != TOKEN_OPAREN)
|
||||
return EXP_Error (EXP_E_SYNTAX,
|
||||
va
|
||||
("Function '%s' called without an argument list.",
|
||||
cur->func.func->str));
|
||||
else if (cur->generic.type == TOKEN_COMMA
|
||||
&&
|
||||
((cur->generic.prev->generic.type != TOKEN_CPAREN
|
||||
&& cur->generic.prev->generic.type != TOKEN_NUM)
|
||||
|| paren <= 1))
|
||||
return EXP_Error (EXP_E_SYNTAX,
|
||||
"Comma used outside of a function or after a non-number.");
|
||||
else if (cur->generic.type == TOKEN_OP
|
||||
&& cur->generic.next->generic.type == TOKEN_CPAREN)
|
||||
return EXP_Error (EXP_E_SYNTAX,
|
||||
va ("Operator '%s' is missing an operand.",
|
||||
cur->op.op->str));
|
||||
else if (cur->generic.type == TOKEN_NUM
|
||||
&& cur->generic.next->generic.type == TOKEN_NUM)
|
||||
return EXP_Error (EXP_E_SYNTAX,
|
||||
"Double number error (two numbers next two each other without an operator).");
|
||||
else if (cur->generic.type == TOKEN_OPAREN
|
||||
&& cur->generic.next->generic.type == TOKEN_CPAREN)
|
||||
return EXP_Error (EXP_E_PAREN, "Empty parentheses found.");
|
||||
}
|
||||
|
||||
|
@ -492,31 +511,30 @@ EXP_Validate (token *chain)
|
|||
}
|
||||
|
||||
void
|
||||
EXP_PrintTokens (token *chain)
|
||||
EXP_PrintTokens (token * chain)
|
||||
{
|
||||
for (; chain; chain = chain->generic.next)
|
||||
switch (chain->generic.type)
|
||||
{
|
||||
switch (chain->generic.type) {
|
||||
case TOKEN_OPAREN:
|
||||
printf("(");
|
||||
printf ("(");
|
||||
break;
|
||||
case TOKEN_CPAREN:
|
||||
printf(")");
|
||||
printf (")");
|
||||
break;
|
||||
case TOKEN_COMMA:
|
||||
printf(",");
|
||||
printf (",");
|
||||
break;
|
||||
case TOKEN_NUM:
|
||||
printf("%f", chain->num.value);
|
||||
printf ("%f", chain->num.value);
|
||||
break;
|
||||
case TOKEN_OP:
|
||||
printf("%s", chain->op.op->str);
|
||||
printf ("%s", chain->op.op->str);
|
||||
break;
|
||||
case TOKEN_FUNC:
|
||||
printf("%s", chain->func.func->str);
|
||||
printf ("%s", chain->func.func->str);
|
||||
break;
|
||||
case TOKEN_GENERIC:
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
printf ("\n");
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] = "$Id$";
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -61,17 +61,17 @@ GIB_Buffer_Construct (struct cbuf_s *cbuf)
|
|||
void
|
||||
GIB_Buffer_Destruct (struct cbuf_s *cbuf)
|
||||
{
|
||||
gib_buffer_data_t *g = GIB_DATA(cbuf);
|
||||
gib_buffer_data_t *g = GIB_DATA (cbuf);
|
||||
unsigned int i, j;
|
||||
|
||||
|
||||
dstring_delete (g->arg_composite);
|
||||
if (g->locals)
|
||||
Hash_DelTable (g->locals);
|
||||
if (g->program)
|
||||
GIB_Tree_Unref (&g->program);
|
||||
if (g->script && !(--g->script->refs)) {
|
||||
free ((void *)g->script->text);
|
||||
free ((void *)g->script->file);
|
||||
free ((void *) g->script->text);
|
||||
free ((void *) g->script->file);
|
||||
free (g->script);
|
||||
}
|
||||
for (i = 0; i < g->stack.size; i++) {
|
||||
|
@ -88,8 +88,8 @@ GIB_Buffer_Destruct (struct cbuf_s *cbuf)
|
|||
void
|
||||
GIB_Buffer_Reset (struct cbuf_s *cbuf)
|
||||
{
|
||||
gib_buffer_data_t *g = GIB_DATA(cbuf);
|
||||
|
||||
gib_buffer_data_t *g = GIB_DATA (cbuf);
|
||||
|
||||
if (g->locals)
|
||||
Hash_FlushTable (g->locals);
|
||||
g->globals = gib_globals;
|
||||
|
@ -103,19 +103,20 @@ GIB_Buffer_Reset (struct cbuf_s *cbuf)
|
|||
g->script = 0;
|
||||
g->stack.p = 0;
|
||||
g->waitret = g->done = false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Buffer_Set_Program (cbuf_t *cbuf, gib_tree_t *program)
|
||||
GIB_Buffer_Set_Program (cbuf_t * cbuf, gib_tree_t * program)
|
||||
{
|
||||
GIB_DATA(cbuf)->program = program;
|
||||
GIB_DATA (cbuf)->program = program;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
GIB_Buffer_Get_Line_Num (const char *program, unsigned int pos)
|
||||
{
|
||||
unsigned int i, line;
|
||||
|
||||
for (i = 0, line = 1; i < pos; i++)
|
||||
if (program[i] == '\n')
|
||||
line++;
|
||||
|
@ -123,7 +124,7 @@ GIB_Buffer_Get_Line_Num (const char *program, unsigned int pos)
|
|||
}
|
||||
|
||||
void
|
||||
GIB_Buffer_Add (cbuf_t *cbuf, const char *str)
|
||||
GIB_Buffer_Add (cbuf_t * cbuf, const char *str)
|
||||
{
|
||||
gib_buffer_data_t *g = GIB_DATA (cbuf);
|
||||
gib_tree_t **save, *cur;
|
||||
|
@ -134,125 +135,126 @@ GIB_Buffer_Add (cbuf_t *cbuf, const char *str)
|
|||
} else
|
||||
save = &g->program;
|
||||
if (!(*save = GIB_Parse_Lines (str, 0, TREE_NORMAL)))
|
||||
Sys_Printf (
|
||||
"-----------------\n"
|
||||
"|GIB Parse Error|\n"
|
||||
"-----------------\n"
|
||||
"Parse error while adding text to GIB buffer.\n"
|
||||
"Line %u: %s\n", GIB_Buffer_Get_Line_Num (str, GIB_Parse_ErrorPos()), GIB_Parse_ErrorMsg()
|
||||
Sys_Printf ("-----------------\n"
|
||||
"|GIB Parse Error|\n"
|
||||
"-----------------\n"
|
||||
"Parse error while adding text to GIB buffer.\n"
|
||||
"Line %u: %s\n", GIB_Buffer_Get_Line_Num (str,
|
||||
GIB_Parse_ErrorPos
|
||||
()),
|
||||
GIB_Parse_ErrorMsg ()
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Buffer_Insert (cbuf_t *cbuf, const char *str)
|
||||
GIB_Buffer_Insert (cbuf_t * cbuf, const char *str)
|
||||
{
|
||||
gib_buffer_data_t *g = GIB_DATA (cbuf);
|
||||
gib_tree_t *lines, *cur;
|
||||
|
||||
if ((lines = GIB_Parse_Lines (str, 0, TREE_NORMAL))) {
|
||||
for (cur = lines; cur; cur = cur->next);
|
||||
//if (g->ip) { // This buffer is already running!
|
||||
|
||||
// if (g->ip) { // This buffer is already running!
|
||||
|
||||
GIB_Tree_Unref (&g->program);
|
||||
cur->next = g->program;
|
||||
g->program = lines;
|
||||
} else
|
||||
Sys_Printf (
|
||||
"-----------------\n"
|
||||
"|GIB Parse Error|\n"
|
||||
"-----------------\n"
|
||||
"Parse error while inserting text into GIB buffer.\n"
|
||||
"Line %u: %s\n", GIB_Buffer_Get_Line_Num (str, GIB_Parse_ErrorPos()), GIB_Parse_ErrorMsg()
|
||||
Sys_Printf ("-----------------\n"
|
||||
"|GIB Parse Error|\n"
|
||||
"-----------------\n"
|
||||
"Parse error while inserting text into GIB buffer.\n"
|
||||
"Line %u: %s\n", GIB_Buffer_Get_Line_Num (str,
|
||||
GIB_Parse_ErrorPos
|
||||
()),
|
||||
GIB_Parse_ErrorMsg ()
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Buffer_Push_Sstack (struct cbuf_s *cbuf)
|
||||
{
|
||||
gib_buffer_data_t *g = GIB_DATA(cbuf);
|
||||
gib_buffer_data_t *g = GIB_DATA (cbuf);
|
||||
|
||||
if (++g->stack.p > g->stack.size) {
|
||||
g->stack.values = realloc(g->stack.values, sizeof (struct gib_dsarray_s) * g->stack.p);
|
||||
g->stack.values[g->stack.p-1].dstrs = 0;
|
||||
g->stack.values[g->stack.p-1].size = g->stack.values[g->stack.p-1].realsize = 0;
|
||||
g->stack.values =
|
||||
realloc (g->stack.values,
|
||||
sizeof (struct gib_dsarray_s) * g->stack.p);
|
||||
g->stack.values[g->stack.p - 1].dstrs = 0;
|
||||
g->stack.values[g->stack.p - 1].size =
|
||||
g->stack.values[g->stack.p - 1].realsize = 0;
|
||||
g->stack.size = g->stack.p;
|
||||
}
|
||||
g->stack.values[g->stack.p-1].size = 0;
|
||||
g->stack.values[g->stack.p - 1].size = 0;
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Buffer_Pop_Sstack (struct cbuf_s *cbuf)
|
||||
{
|
||||
GIB_DATA(cbuf)->stack.p--;
|
||||
GIB_DATA (cbuf)->stack.p--;
|
||||
}
|
||||
|
||||
dstring_t *
|
||||
GIB_Buffer_Dsarray_Get (struct cbuf_s *cbuf)
|
||||
{
|
||||
struct gib_dsarray_s *vals = GIB_DATA(cbuf)->stack.values+GIB_DATA(cbuf)->stack.p-1;
|
||||
struct gib_dsarray_s *vals =
|
||||
GIB_DATA (cbuf)->stack.values + GIB_DATA (cbuf)->stack.p - 1;
|
||||
if (++vals->size > vals->realsize) {
|
||||
vals->dstrs = realloc (vals->dstrs, sizeof (dstring_t *) * vals->size);
|
||||
vals->dstrs[vals->size-1] = dstring_newstr ();
|
||||
vals->dstrs[vals->size - 1] = dstring_newstr ();
|
||||
vals->realsize = vals->size;
|
||||
} else
|
||||
dstring_clearstr (vals->dstrs[vals->size-1]);
|
||||
return vals->dstrs[vals->size-1];
|
||||
dstring_clearstr (vals->dstrs[vals->size - 1]);
|
||||
return vals->dstrs[vals->size - 1];
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
GIB_Buffer_Get_Line_Info (cbuf_t *cbuf, char **line)
|
||||
GIB_Buffer_Get_Line_Info (cbuf_t * cbuf, char **line)
|
||||
{
|
||||
const char *text;
|
||||
unsigned int ofs, i, start, linenum;
|
||||
|
||||
|
||||
// Do we have a copy of the original program this buffer comes from?
|
||||
if (GIB_DATA(cbuf)->script) {
|
||||
text = GIB_DATA(cbuf)->script->text;
|
||||
for (ofs = GIB_DATA(cbuf)->ip->start, start = 0, i = 0, linenum = 1; i <= ofs; i++)
|
||||
if (GIB_DATA (cbuf)->script) {
|
||||
text = GIB_DATA (cbuf)->script->text;
|
||||
for (ofs = GIB_DATA (cbuf)->ip->start, start = 0, i = 0, linenum = 1;
|
||||
i <= ofs; i++)
|
||||
if (text[i] == '\n') {
|
||||
start = i+1;
|
||||
start = i + 1;
|
||||
linenum++;
|
||||
}
|
||||
while (text[i] != '\n')
|
||||
i++;
|
||||
*line = malloc (i - start + 1);
|
||||
memcpy (*line, text+start, i - start);
|
||||
(*line)[i-start] = 0;
|
||||
memcpy (*line, text + start, i - start);
|
||||
(*line)[i - start] = 0;
|
||||
return linenum;
|
||||
} else {
|
||||
*line = strdup (GIB_DATA(cbuf)->ip->str);
|
||||
*line = strdup (GIB_DATA (cbuf)->ip->str);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Buffer_Error (cbuf_t *cbuf, const char *type, const char *fmt, va_list args)
|
||||
GIB_Buffer_Error (cbuf_t * cbuf, const char *type, const char *fmt,
|
||||
va_list args)
|
||||
{
|
||||
char *line;
|
||||
int linenum;
|
||||
dstring_t *message = dstring_newstr();
|
||||
char *line;
|
||||
int linenum;
|
||||
dstring_t *message = dstring_newstr ();
|
||||
|
||||
dvsprintf (message, fmt, args);
|
||||
va_end (args);
|
||||
Sys_Printf ( "---------------------\n"
|
||||
"|GIB Execution Error|\n"
|
||||
"---------------------\n"
|
||||
"Type: %s\n",
|
||||
type
|
||||
);
|
||||
Sys_Printf ("---------------------\n"
|
||||
"|GIB Execution Error|\n"
|
||||
"---------------------\n" "Type: %s\n", type);
|
||||
if ((linenum = GIB_Buffer_Get_Line_Info (cbuf, &line)) != -1)
|
||||
Sys_Printf ( "%s:%i: %s\n"
|
||||
"-->%s\n",
|
||||
GIB_DATA(cbuf)->script->file,
|
||||
linenum,
|
||||
message->str,
|
||||
line
|
||||
);
|
||||
Sys_Printf ("%s:%i: %s\n"
|
||||
"-->%s\n",
|
||||
GIB_DATA (cbuf)->script->file, linenum, message->str, line);
|
||||
else
|
||||
Sys_Printf ( "%s\n"
|
||||
"-->%s\n",
|
||||
message->str,
|
||||
line
|
||||
);
|
||||
Sys_Printf ("%s\n" "-->%s\n", message->str, line);
|
||||
cbuf->state = CBUF_STATE_ERROR;
|
||||
dstring_delete (message);
|
||||
free (line);
|
||||
|
|
|
@ -32,8 +32,9 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -63,22 +64,23 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "QF/gib_thread.h"
|
||||
#include "regex.h"
|
||||
|
||||
char gib_null_string[] = "";
|
||||
char gib_null_string[] = "";
|
||||
|
||||
hashtab_t *gib_builtins;
|
||||
hashtab_t *gib_builtins;
|
||||
|
||||
/*
|
||||
Hashtable callbacks
|
||||
*/
|
||||
static const char *
|
||||
static const char *
|
||||
GIB_Builtin_Get_Key (void *ele, void *ptr)
|
||||
{
|
||||
return ((gib_builtin_t *)ele)->name->str;
|
||||
return ((gib_builtin_t *) ele)->name->str;
|
||||
}
|
||||
static void
|
||||
GIB_Builtin_Free (void *ele, void *ptr)
|
||||
{
|
||||
gib_builtin_t *b;
|
||||
|
||||
b = (gib_builtin_t *) ele;
|
||||
dstring_delete (b->name);
|
||||
free (b);
|
||||
|
@ -93,13 +95,14 @@ 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);
|
||||
|
||||
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 = dstring_newstr();
|
||||
new->name = dstring_newstr ();
|
||||
dstring_appendstr (new->name, name);
|
||||
Hash_Add (gib_builtins, new);
|
||||
}
|
||||
|
@ -122,11 +125,12 @@ GIB_Builtin_Find (const char *name)
|
|||
dstring_t *
|
||||
GIB_Return (const char *str)
|
||||
{
|
||||
dstring_t *dstr;
|
||||
if (GIB_DATA(cbuf_active)->waitret) {
|
||||
dstring_t *dstr;
|
||||
|
||||
if (GIB_DATA (cbuf_active)->waitret) {
|
||||
dstr = GIB_Buffer_Dsarray_Get (cbuf_active);
|
||||
dstring_clearstr (dstr);
|
||||
if (!str)
|
||||
if (!str)
|
||||
return dstr;
|
||||
else
|
||||
dstring_appendstr (dstr, str);
|
||||
|
@ -137,8 +141,8 @@ GIB_Return (const char *str)
|
|||
void
|
||||
GIB_Error (const char *type, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
GIB_Buffer_Error (cbuf_active, type, fmt, args);
|
||||
va_end (args);
|
||||
|
@ -160,16 +164,19 @@ GIB_Function_f (void)
|
|||
// Is the function program already tokenized?
|
||||
if (GIB_Argm (2)->delim != '{') {
|
||||
// Parse on the fly
|
||||
if (!(program = GIB_Parse_Lines (GIB_Argv(2), 0, TREE_NORMAL))) {
|
||||
if (!(program = GIB_Parse_Lines (GIB_Argv (2), 0, TREE_NORMAL))) {
|
||||
// Error!
|
||||
GIB_Error ("parse", "Parse error while defining function '%s'.", GIB_Argv(1));
|
||||
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);
|
||||
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)
|
||||
|
@ -178,6 +185,7 @@ GIB_Function_Get_f (void)
|
|||
GIB_USAGE ("name");
|
||||
else {
|
||||
gib_function_t *f;
|
||||
|
||||
if ((f = GIB_Function_Find (GIB_Argv (1))))
|
||||
GIB_Return (f->text->str);
|
||||
else
|
||||
|
@ -188,16 +196,19 @@ GIB_Function_Get_f (void)
|
|||
static void
|
||||
GIB_Local_f (void)
|
||||
{
|
||||
gib_var_t *var;
|
||||
gib_var_t *var;
|
||||
unsigned int index;
|
||||
hashtab_t *zero = 0;
|
||||
|
||||
hashtab_t *zero = 0;
|
||||
|
||||
if (GIB_Argc () < 2)
|
||||
GIB_USAGE ("var [= value1 value2 ...]");
|
||||
else {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,71 +216,77 @@ GIB_Local_f (void)
|
|||
static void
|
||||
GIB_Global_f (void)
|
||||
{
|
||||
gib_var_t *var;
|
||||
gib_var_t *var;
|
||||
unsigned int index;
|
||||
hashtab_t *zero = 0;
|
||||
|
||||
hashtab_t *zero = 0;
|
||||
|
||||
if (GIB_Argc () < 2)
|
||||
GIB_USAGE ("var [= value1 value2 ...]");
|
||||
else {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Domain_f (void)
|
||||
{
|
||||
if (GIB_Argc() != 2)
|
||||
if (GIB_Argc () != 2)
|
||||
GIB_USAGE ("domain");
|
||||
else
|
||||
GIB_DATA(cbuf_active)->globals = GIB_Domain_Get (GIB_Argv(1));
|
||||
GIB_DATA (cbuf_active)->globals = GIB_Domain_Get (GIB_Argv (1));
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Domain_Clear_f (void)
|
||||
{
|
||||
if (GIB_Argc() != 2)
|
||||
if (GIB_Argc () != 2)
|
||||
GIB_USAGE ("domain");
|
||||
else
|
||||
Hash_FlushTable (GIB_Domain_Get (GIB_Argv(2)));
|
||||
Hash_FlushTable (GIB_Domain_Get (GIB_Argv (2)));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
GIB_Return_f (void)
|
||||
{
|
||||
cbuf_t *sp = cbuf_active->up;
|
||||
|
||||
GIB_DATA(cbuf_active)->done = true;
|
||||
|
||||
if (GIB_Argc() > 1 && sp && sp->interpreter == &gib_interp && GIB_DATA(sp)->waitret) {
|
||||
cbuf_t *sp = cbuf_active->up;
|
||||
|
||||
GIB_DATA (cbuf_active)->done = true;
|
||||
|
||||
if (GIB_Argc () > 1 && sp && sp->interpreter == &gib_interp
|
||||
&& GIB_DATA (sp)->waitret) {
|
||||
unsigned int i;
|
||||
dstring_t *dstr;
|
||||
for (i = 1; i < GIB_Argc(); 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));
|
||||
dstring_appendstr (dstr, GIB_Argv (i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
GIB_For_f (void)
|
||||
{
|
||||
dstring_t *dstr;
|
||||
dstring_t *dstr;
|
||||
unsigned int i;
|
||||
if (GIB_Argc() < 5) {
|
||||
GIB_DATA(cbuf_active)->ip = GIB_DATA(cbuf_active)->ip->jump;
|
||||
|
||||
if (GIB_Argc () < 5) {
|
||||
GIB_DATA (cbuf_active)->ip = GIB_DATA (cbuf_active)->ip->jump;
|
||||
return;
|
||||
}
|
||||
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--) {
|
||||
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));
|
||||
dstring_appendstr (dstr, GIB_Argv (i));
|
||||
}
|
||||
GIB_Execute_For_Next (cbuf_active);
|
||||
}
|
||||
|
@ -277,13 +294,14 @@ GIB_For_f (void)
|
|||
static void
|
||||
GIB_Break_f (void)
|
||||
{
|
||||
if (!GIB_DATA(cbuf_active)->ip->jump) {
|
||||
if (!GIB_DATA (cbuf_active)->ip->jump) {
|
||||
GIB_Error ("loop", "Break command attempted outside of a loop.");
|
||||
return;
|
||||
}
|
||||
if (!GIB_DATA(cbuf_active)->ip->jump->flags & TREE_COND) // In a for loop?
|
||||
GIB_Buffer_Pop_Sstack (cbuf_active); // Kill it
|
||||
GIB_DATA(cbuf_active)->ip = GIB_DATA(cbuf_active)->ip->jump->jump;
|
||||
if (!GIB_DATA (cbuf_active)->ip->jump->flags & TREE_COND) // In a for
|
||||
// loop?
|
||||
GIB_Buffer_Pop_Sstack (cbuf_active); // Kill it
|
||||
GIB_DATA (cbuf_active)->ip = GIB_DATA (cbuf_active)->ip->jump->jump;
|
||||
}
|
||||
|
||||
static gib_tree_t gib_cont = {
|
||||
|
@ -296,16 +314,16 @@ static gib_tree_t gib_cont = {
|
|||
static void
|
||||
GIB_Continue_f (void)
|
||||
{
|
||||
if (!GIB_DATA(cbuf_active)->ip->jump) {
|
||||
if (!GIB_DATA (cbuf_active)->ip->jump) {
|
||||
GIB_Error ("loop", "Continue command attempted outside of a loop.");
|
||||
return;
|
||||
}
|
||||
if (GIB_DATA(cbuf_active)->ip->jump->flags & TREE_COND) {
|
||||
gib_cont.next = GIB_DATA(cbuf_active)->ip->jump;
|
||||
GIB_DATA(cbuf_active)->ip = &gib_cont;
|
||||
if (GIB_DATA (cbuf_active)->ip->jump->flags & TREE_COND) {
|
||||
gib_cont.next = GIB_DATA (cbuf_active)->ip->jump;
|
||||
GIB_DATA (cbuf_active)->ip = &gib_cont;
|
||||
} else {
|
||||
GIB_Execute_For_Next (cbuf_active);
|
||||
GIB_DATA(cbuf_active)->ip = GIB_DATA(cbuf_active)->ip->jump;
|
||||
GIB_DATA (cbuf_active)->ip = GIB_DATA (cbuf_active)->ip->jump;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,14 +332,16 @@ static void
|
|||
GIB_Runexported_f (void)
|
||||
{
|
||||
gib_function_t *f;
|
||||
|
||||
|
||||
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));
|
||||
"The QuakeForge developers.", Cmd_Argv (0));
|
||||
else {
|
||||
cbuf_t *sub = Cbuf_New (&gib_interp);
|
||||
GIB_Function_Execute (sub, f, cbuf_active->args->argv, cbuf_active->args->argc);
|
||||
cbuf_t *sub = Cbuf_New (&gib_interp);
|
||||
|
||||
GIB_Function_Execute (sub, f, cbuf_active->args->argv,
|
||||
cbuf_active->args->argc);
|
||||
cbuf_active->down = sub;
|
||||
sub->up = cbuf_active;
|
||||
cbuf_active->state = CBUF_STATE_STACK;
|
||||
|
@ -332,19 +352,23 @@ static void
|
|||
GIB_Function_Export_f (void)
|
||||
{
|
||||
gib_function_t *f;
|
||||
int i;
|
||||
|
||||
if (GIB_Argc() < 2)
|
||||
int i;
|
||||
|
||||
if (GIB_Argc () < 2)
|
||||
GIB_USAGE ("function1 [function2 function3 ...]");
|
||||
for (i = 1; i < GIB_Argc(); i++) {
|
||||
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));
|
||||
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));
|
||||
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.");
|
||||
Cmd_AddCommand (f->name, GIB_Runexported_f,
|
||||
"Exported GIB function.");
|
||||
f->exported = true;
|
||||
}
|
||||
}
|
||||
|
@ -354,19 +378,20 @@ GIB_Function_Export_f (void)
|
|||
static void
|
||||
GIB_Length_f (void)
|
||||
{
|
||||
dstring_t *ret;
|
||||
if (GIB_Argc() != 2)
|
||||
dstring_t *ret;
|
||||
|
||||
if (GIB_Argc () != 2)
|
||||
GIB_USAGE ("string");
|
||||
else if ((ret = GIB_Return (0)))
|
||||
dsprintf (ret, "%i", (int) strlen(GIB_Argv(1)));
|
||||
dsprintf (ret, "%i", (int) strlen (GIB_Argv (1)));
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Equal_f (void)
|
||||
{
|
||||
if (GIB_Argc() != 3)
|
||||
if (GIB_Argc () != 3)
|
||||
GIB_USAGE ("string1 string2");
|
||||
else if (strcmp(GIB_Argv(1), GIB_Argv(2)))
|
||||
else if (strcmp (GIB_Argv (1), GIB_Argv (2)))
|
||||
GIB_Return ("0");
|
||||
else
|
||||
GIB_Return ("1");
|
||||
|
@ -375,14 +400,15 @@ GIB_Equal_f (void)
|
|||
static void
|
||||
GIB_Slice_f (void)
|
||||
{
|
||||
dstring_t *ret;
|
||||
int start, end, len;
|
||||
if (GIB_Argc() < 3 || GIB_Argc() > 4)
|
||||
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;
|
||||
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)
|
||||
|
@ -394,7 +420,7 @@ GIB_Slice_f (void)
|
|||
} else if (start >= len || start >= end)
|
||||
return;
|
||||
if ((ret = GIB_Return (0)))
|
||||
dstring_appendsubstr (ret, GIB_Argv(1)+start, end-start);
|
||||
dstring_appendsubstr (ret, GIB_Argv (1) + start, end - start);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,59 +428,67 @@ GIB_Slice_f (void)
|
|||
static void
|
||||
GIB_Slice_Find_f (void)
|
||||
{
|
||||
char *res;
|
||||
if (GIB_Argc() != 3) {
|
||||
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)));
|
||||
}
|
||||
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;
|
||||
char *end, *start;
|
||||
const char *ifs;
|
||||
|
||||
if (GIB_Argc() < 2 || GIB_Argc() > 3) {
|
||||
|
||||
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);
|
||||
ifs = GIB_Argc () == 3 ? GIB_Argv (2) : " \t\r\n";
|
||||
|
||||
end = GIB_Argv (1);
|
||||
while (*end) {
|
||||
for (; strchr(ifs, *end); end++)
|
||||
for (; strchr (ifs, *end); end++)
|
||||
if (!*end)
|
||||
return;
|
||||
start = end;
|
||||
while (!strchr(ifs, *end))
|
||||
while (!strchr (ifs, *end))
|
||||
end++;
|
||||
if (*end)
|
||||
*(end++) = 0;
|
||||
GIB_Return (start);
|
||||
GIB_Return (start);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Regex_Match_f (void)
|
||||
{
|
||||
regex_t *reg;
|
||||
|
||||
if (GIB_Argc() != 4) {
|
||||
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, 0))
|
||||
|
||||
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, 0))
|
||||
GIB_Return ("0");
|
||||
else
|
||||
GIB_Return ("1");
|
||||
|
@ -463,53 +497,64 @@ GIB_Regex_Match_f (void)
|
|||
static void
|
||||
GIB_Regex_Replace_f (void)
|
||||
{
|
||||
regex_t *reg;
|
||||
int ofs, len;
|
||||
regmatch_t match[10];
|
||||
|
||||
if (GIB_Argc() != 5) {
|
||||
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, 0) && match[0].rm_eo)
|
||||
GIB_Regex_Apply_Match (match, GIB_Argd(1), 0, GIB_Argv(4));
|
||||
GIB_Return (GIB_Argv(1));
|
||||
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, 0) && 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;
|
||||
regex_t *reg;
|
||||
regmatch_t *match;
|
||||
int i;
|
||||
char o;
|
||||
|
||||
if (GIB_Argc() != 4) {
|
||||
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, 0) && match[0].rm_eo) {
|
||||
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, 0) && 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -520,48 +565,57 @@ static void
|
|||
GIB_Thread_Create_f (void)
|
||||
{
|
||||
gib_function_t *f;
|
||||
if (GIB_Argc() < 2)
|
||||
|
||||
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 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 (thread->cbuf, f, cbuf_active->args->argv+1, cbuf_active->args->argc-1);
|
||||
|
||||
GIB_Function_Execute (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);
|
||||
dsprintf (GIB_Return (0), "%lu", thread->id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Thread_Kill_f (void)
|
||||
{
|
||||
if (GIB_Argc() != 2)
|
||||
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);
|
||||
cbuf_t *cur;
|
||||
unsigned long int id = strtoul (GIB_Argv (1), 0, 10);
|
||||
|
||||
thread = GIB_Thread_Find (id);
|
||||
if (!thread) {
|
||||
GIB_Error ("thread", "%s: thread %lu does not exist.", GIB_Argv(0), id);
|
||||
GIB_Error ("thread", "%s: thread %lu does not exist.", GIB_Argv (0),
|
||||
id);
|
||||
return;
|
||||
}
|
||||
thread->trash = true;
|
||||
// Set error condition on the top of the stack so the thread will exit if currently running
|
||||
for (cur = thread->cbuf; cur->down && cur->down->state != CBUF_STATE_JUNK; cur = cur->down);
|
||||
// Set error condition on the top of the stack so the thread will exit
|
||||
// if currently running
|
||||
for (cur = thread->cbuf;
|
||||
cur->down && cur->down->state != CBUF_STATE_JUNK; cur = cur->down);
|
||||
cur->state = CBUF_STATE_ERROR;
|
||||
GIB_DATA(cur)->done = true;
|
||||
GIB_DATA (cur)->done = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Thread_List_f (void)
|
||||
{
|
||||
if (GIB_Argc() != 1)
|
||||
if (GIB_Argc () != 1)
|
||||
GIB_USAGE ("");
|
||||
else if (GIB_CanReturn()) {
|
||||
else if (GIB_CanReturn ()) {
|
||||
gib_thread_t *cur;
|
||||
|
||||
for (cur = gib_threads; cur; cur = cur->next)
|
||||
dsprintf (GIB_Return (0), "%lu", cur->id);
|
||||
}
|
||||
|
@ -571,35 +625,36 @@ static void
|
|||
GIB_Event_Register_f (void)
|
||||
{
|
||||
gib_function_t *func;
|
||||
if (GIB_Argc() != 3)
|
||||
|
||||
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));
|
||||
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;
|
||||
int (*GIB_File_Transform_Path) (dstring_t * path) = NULL;
|
||||
|
||||
static int
|
||||
GIB_File_Transform_Path_Null (dstring_t *path)
|
||||
GIB_File_Transform_Path_Null (dstring_t * path)
|
||||
{
|
||||
char *s;
|
||||
|
||||
char *s;
|
||||
|
||||
// Convert backslash to forward slash
|
||||
for (s = strchr(path->str, '\\'); s; s = strchr (s, '\\'))
|
||||
for (s = strchr (path->str, '\\'); s; s = strchr (s, '\\'))
|
||||
*s = '/';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
GIB_File_Transform_Path_Secure (dstring_t *path)
|
||||
GIB_File_Transform_Path_Secure (dstring_t * path)
|
||||
{
|
||||
char *s /* , e_dir[MAX_OSPATH] */;
|
||||
|
||||
for (s = strchr(path->str, '\\'); s; s = strchr (s, '\\'))
|
||||
char *s /* , e_dir[MAX_OSPATH] */ ;
|
||||
|
||||
for (s = strchr (path->str, '\\'); s; s = strchr (s, '\\'))
|
||||
*s = '/';
|
||||
if (Sys_PathType (path->str) != PATHTYPE_RELATIVE_BELOW)
|
||||
return -1;
|
||||
|
@ -610,13 +665,13 @@ GIB_File_Transform_Path_Secure (dstring_t *path)
|
|||
dstring_insertstr (path, 0, fs_userpath->string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
GIB_File_Read_f (void)
|
||||
{
|
||||
QFile *file;
|
||||
char *path;
|
||||
int len;
|
||||
int len;
|
||||
dstring_t *ret;
|
||||
|
||||
if (GIB_Argc () != 2) {
|
||||
|
@ -624,13 +679,12 @@ GIB_File_Read_f (void)
|
|||
return;
|
||||
}
|
||||
if (!*GIB_Argv (1)) {
|
||||
GIB_Error ("file",
|
||||
"%s: null filename provided", GIB_Argv(0));
|
||||
GIB_Error ("file", "%s: null filename provided", GIB_Argv (0));
|
||||
return;
|
||||
}
|
||||
if (GIB_File_Transform_Path (GIB_Argd(1))) {
|
||||
if (GIB_File_Transform_Path (GIB_Argd (1))) {
|
||||
GIB_Error ("access",
|
||||
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(1));
|
||||
"%s: access to %s denied", GIB_Argv (0), GIB_Argv (1));
|
||||
return;
|
||||
}
|
||||
if (!(ret = GIB_Return (0)))
|
||||
|
@ -639,7 +693,7 @@ GIB_File_Read_f (void)
|
|||
file = Qopen (path, "r");
|
||||
if (file) {
|
||||
len = Qfilesize (file);
|
||||
ret->size = len+1;
|
||||
ret->size = len + 1;
|
||||
dstring_adjust (ret);
|
||||
Qread (file, ret->str, len);
|
||||
ret->str[len] = 0;
|
||||
|
@ -647,7 +701,8 @@ GIB_File_Read_f (void)
|
|||
}
|
||||
if (!file) {
|
||||
GIB_Error ("file",
|
||||
"%s: could not read %s: %s", GIB_Argv(0), path, strerror (errno));
|
||||
"%s: could not read %s: %s", GIB_Argv (0), path,
|
||||
strerror (errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -657,25 +712,25 @@ GIB_File_Write_f (void)
|
|||
{
|
||||
QFile *file;
|
||||
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));
|
||||
if (!*GIB_Argv (1)) {
|
||||
GIB_Error ("file", "%s: null filename provided", GIB_Argv (0));
|
||||
return;
|
||||
}
|
||||
if (GIB_File_Transform_Path (GIB_Argd(1))) {
|
||||
if (GIB_File_Transform_Path (GIB_Argd (1))) {
|
||||
GIB_Error ("access",
|
||||
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(1));
|
||||
"%s: access to %s denied", GIB_Argv (0), GIB_Argv (1));
|
||||
return;
|
||||
}
|
||||
path = GIB_Argv(1);
|
||||
path = GIB_Argv (1);
|
||||
if (!(file = Qopen (path, "w"))) {
|
||||
GIB_Error ("file",
|
||||
"%s: could not open %s for writing: %s", GIB_Argv(0), path, strerror (errno));
|
||||
"%s: could not open %s for writing: %s", GIB_Argv (0), path,
|
||||
strerror (errno));
|
||||
return;
|
||||
}
|
||||
Qprintf (file, "%s", GIB_Argv (2));
|
||||
|
@ -687,37 +742,39 @@ GIB_File_Find_f (void)
|
|||
{
|
||||
DIR *directory;
|
||||
struct dirent *entry;
|
||||
const char *path, *glob = 0;
|
||||
char *s;
|
||||
const char *path, *glob = 0;
|
||||
char *s;
|
||||
|
||||
if (GIB_Argc () != 2) {
|
||||
GIB_USAGE ("glob");
|
||||
return;
|
||||
}
|
||||
if (GIB_File_Transform_Path (GIB_Argd(1))) {
|
||||
if (GIB_File_Transform_Path (GIB_Argd (1))) {
|
||||
GIB_Error ("access",
|
||||
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(1));
|
||||
"%s: access to %s denied", GIB_Argv (0), GIB_Argv (1));
|
||||
return;
|
||||
}
|
||||
path = GIB_Argv(1);
|
||||
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)
|
||||
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;
|
||||
*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));
|
||||
"%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))
|
||||
if (strcmp (entry->d_name, ".") && strcmp (entry->d_name, "..")
|
||||
&& !fnmatch (glob, entry->d_name, 0))
|
||||
GIB_Return (entry->d_name);
|
||||
closedir (directory);
|
||||
}
|
||||
|
@ -725,88 +782,92 @@ GIB_File_Find_f (void)
|
|||
static void
|
||||
GIB_File_Move_f (void)
|
||||
{
|
||||
char *path1, *path2;
|
||||
char *path1, *path2;
|
||||
|
||||
if (GIB_Argc () != 3) {
|
||||
GIB_USAGE ("from_file to_file");
|
||||
return;
|
||||
}
|
||||
if (GIB_File_Transform_Path (GIB_Argd(1))) {
|
||||
if (GIB_File_Transform_Path (GIB_Argd (1))) {
|
||||
GIB_Error ("access",
|
||||
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(1));
|
||||
"%s: access to %s denied", GIB_Argv (0), GIB_Argv (1));
|
||||
return;
|
||||
}
|
||||
if (GIB_File_Transform_Path (GIB_Argd(2))) {
|
||||
if (GIB_File_Transform_Path (GIB_Argd (2))) {
|
||||
GIB_Error ("access",
|
||||
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(2));
|
||||
"%s: access to %s denied", GIB_Argv (0), GIB_Argv (2));
|
||||
return;
|
||||
}
|
||||
path1 = GIB_Argv(1);
|
||||
path2 = GIB_Argv(2);
|
||||
path1 = GIB_Argv (1);
|
||||
path2 = GIB_Argv (2);
|
||||
if (Qrename (path1, path2))
|
||||
GIB_Error ("file", "%s: could not move %s to %s: %s", GIB_Argv(0), path1, path2, strerror(errno));
|
||||
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;
|
||||
char *path;
|
||||
|
||||
if (GIB_Argc () != 2) {
|
||||
GIB_USAGE ("file");
|
||||
return;
|
||||
}
|
||||
if (GIB_File_Transform_Path (GIB_Argd(1))) {
|
||||
if (GIB_File_Transform_Path (GIB_Argd (1))) {
|
||||
GIB_Error ("access",
|
||||
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(1));
|
||||
"%s: access to %s denied", GIB_Argv (0), GIB_Argv (1));
|
||||
return;
|
||||
}
|
||||
path = GIB_Argv (1);
|
||||
if (Qremove(path))
|
||||
GIB_Error ("file", "%s: could not delete %s: %s", GIB_Argv(0), path, strerror(errno));
|
||||
if (Qremove (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;
|
||||
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));
|
||||
limit = atof (GIB_Argv (2));
|
||||
start = atof (GIB_Argv (1));
|
||||
if (GIB_Argc () == 4) {
|
||||
if ((inc = atof(GIB_Argv(3))) == 0.0)
|
||||
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)))
|
||||
for (i = atof (GIB_Argv (1)); inc < 0 ? i >= limit : i <= limit; i += inc) {
|
||||
if (!(dstr = GIB_Return (0)))
|
||||
return;
|
||||
dsprintf(dstr, "%.10g", i);
|
||||
dsprintf (dstr, "%.10g", i);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Print_f (void)
|
||||
{
|
||||
if (GIB_Argc() != 2) {
|
||||
if (GIB_Argc () != 2) {
|
||||
GIB_USAGE ("text");
|
||||
return;
|
||||
}
|
||||
Sys_Printf ("%s", GIB_Argv(1));
|
||||
Sys_Printf ("%s", GIB_Argv (1));
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Random_f (void)
|
||||
{
|
||||
dstring_t *ret;
|
||||
if (GIB_Argc() != 1)
|
||||
dstring_t *ret;
|
||||
|
||||
if (GIB_Argc () != 1)
|
||||
GIB_USAGE ("");
|
||||
else if ((ret = GIB_Return (0)))
|
||||
dsprintf (ret, "%.10g", (double) rand ()/(double) RAND_MAX);
|
||||
dsprintf (ret, "%.10g", (double) rand () / (double) RAND_MAX);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -817,7 +878,7 @@ GIB_Builtin_Init (qboolean 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);
|
||||
|
|
|
@ -32,8 +32,9 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -51,52 +52,58 @@ static void
|
|||
GIB_Execute_Generate_Composite (struct cbuf_s *cbuf)
|
||||
{
|
||||
cbuf_args_t *args = cbuf->args;
|
||||
int i;
|
||||
|
||||
int i;
|
||||
|
||||
dstring_clearstr (GIB_DATA (cbuf)->arg_composite);
|
||||
for (i = 0; i < args->argc; i++) {
|
||||
// ->str could be moved by realloc when a dstring is resized
|
||||
// so save the offset instead of the pointer
|
||||
args->args[i] = (const char *) strlen (GIB_DATA (cbuf)->arg_composite->str);
|
||||
args->args[i] =
|
||||
(const char *) strlen (GIB_DATA (cbuf)->arg_composite->str);
|
||||
dstring_appendstr (GIB_DATA (cbuf)->arg_composite, args->argv[i]->str);
|
||||
dstring_appendstr (GIB_DATA (cbuf)->arg_composite, " ");
|
||||
}
|
||||
|
||||
|
||||
// Get rid of trailing space
|
||||
GIB_DATA (cbuf)->arg_composite->str[strlen(GIB_DATA (cbuf)->arg_composite->str)-1] = 0;
|
||||
|
||||
GIB_DATA (cbuf)->arg_composite->
|
||||
str[strlen (GIB_DATA (cbuf)->arg_composite->str) - 1] = 0;
|
||||
|
||||
for (i = 0; i < args->argc; i++)
|
||||
// now that arg_composite is done we can add the pointer to the stored
|
||||
// offsets and get valid pointers. This *should* be portable.
|
||||
args->args[i] += (unsigned long int) GIB_DATA (cbuf)->arg_composite->str;
|
||||
}
|
||||
args->args[i] +=
|
||||
(unsigned long int) GIB_DATA (cbuf)->arg_composite->str;
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Execute_Split_Array (cbuf_t *cbuf)
|
||||
GIB_Execute_Split_Array (cbuf_t * cbuf)
|
||||
{
|
||||
gib_var_t *var;
|
||||
gib_var_t *var;
|
||||
unsigned int i;
|
||||
int start = 0, end = 0;
|
||||
char *c, *str = cbuf->args->argv[cbuf->args->argc-1]->str+1;
|
||||
void *m = cbuf->args->argm[cbuf->args->argc-1];
|
||||
int start = 0, end = 0;
|
||||
char *c, *str = cbuf->args->argv[cbuf->args->argc - 1]->str + 1;
|
||||
void *m = cbuf->args->argm[cbuf->args->argc - 1];
|
||||
|
||||
i = strlen(str)-1;
|
||||
i = strlen (str) - 1;
|
||||
if (str[i] == ']')
|
||||
for (; i; i--)
|
||||
if (str[i] == '[') {
|
||||
str[i] = 0;
|
||||
start = atoi (str+i+1);
|
||||
if ((c = strchr (str+i+1, ':'))) {
|
||||
start = atoi (str + i + 1);
|
||||
if ((c = strchr (str + i + 1, ':'))) {
|
||||
if (c[1] != ']')
|
||||
end = atoi (c+1);
|
||||
end = atoi (c + 1);
|
||||
else
|
||||
end = (int) ((unsigned int)~0>>1);
|
||||
end = (int) ((unsigned int) ~0 >> 1);
|
||||
} else
|
||||
end = start+1;
|
||||
end = start + 1;
|
||||
break;
|
||||
}
|
||||
cbuf->args->argc--;
|
||||
if (!(var = GIB_Var_Get_Complex (&GIB_DATA(cbuf)->locals, &GIB_DATA(cbuf)->globals, str, &i, false)))
|
||||
if (!
|
||||
(var =
|
||||
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals,
|
||||
&GIB_DATA (cbuf)->globals, str, &i, false)))
|
||||
return;
|
||||
if (end < 0)
|
||||
end += var->size;
|
||||
|
@ -113,26 +120,26 @@ GIB_Execute_Split_Array (cbuf_t *cbuf)
|
|||
Cbuf_ArgsAdd (cbuf->args, var->array[i]->str);
|
||||
else
|
||||
Cbuf_ArgsAdd (cbuf->args, "");
|
||||
cbuf->args->argm[cbuf->args->argc-1] = m;
|
||||
cbuf->args->argm[cbuf->args->argc - 1] = m;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
GIB_Execute_Prepare_Line (cbuf_t *cbuf, gib_tree_t *line)
|
||||
GIB_Execute_Prepare_Line (cbuf_t * cbuf, gib_tree_t * line)
|
||||
{
|
||||
gib_tree_t *cur;
|
||||
cbuf_args_t *args = cbuf->args;
|
||||
unsigned int pos;
|
||||
|
||||
|
||||
args->argc = 0;
|
||||
|
||||
|
||||
for (cur = line->children; cur; cur = cur->next) {
|
||||
if (cur->flags & TREE_CONCAT) {
|
||||
pos = args->argv[args->argc-1]->size-1;
|
||||
pos = args->argv[args->argc - 1]->size - 1;
|
||||
if (cur->flags & TREE_P_EMBED) {
|
||||
GIB_Process_Embedded (cur, cbuf->args);
|
||||
} else
|
||||
dstring_appendstr (args->argv[args->argc-1], cur->str);
|
||||
dstring_appendstr (args->argv[args->argc - 1], cur->str);
|
||||
} else {
|
||||
pos = 0;
|
||||
if (cur->flags & TREE_P_EMBED) {
|
||||
|
@ -140,9 +147,10 @@ GIB_Execute_Prepare_Line (cbuf_t *cbuf, gib_tree_t *line)
|
|||
GIB_Process_Embedded (cur, cbuf->args);
|
||||
} else
|
||||
Cbuf_ArgsAdd (args, cur->str);
|
||||
args->argm[args->argc-1] = cur;
|
||||
args->argm[args->argc - 1] = cur;
|
||||
}
|
||||
if (cur->delim == '(' && GIB_Process_Math (args->argv[args->argc-1], pos))
|
||||
if (cur->delim == '('
|
||||
&& GIB_Process_Math (args->argv[args->argc - 1], pos))
|
||||
return -1;
|
||||
if (cur->flags & TREE_ASPLIT)
|
||||
GIB_Execute_Split_Array (cbuf);
|
||||
|
@ -151,30 +159,34 @@ GIB_Execute_Prepare_Line (cbuf_t *cbuf, gib_tree_t *line)
|
|||
}
|
||||
|
||||
int
|
||||
GIB_Execute_For_Next (cbuf_t *cbuf)
|
||||
GIB_Execute_For_Next (cbuf_t * cbuf)
|
||||
{
|
||||
unsigned int index;
|
||||
gib_var_t *var;
|
||||
struct gib_dsarray_s *array = GIB_DATA(cbuf)->stack.values+GIB_DATA(cbuf)->stack.p-1;
|
||||
gib_var_t *var;
|
||||
struct gib_dsarray_s *array =
|
||||
GIB_DATA (cbuf)->stack.values + GIB_DATA (cbuf)->stack.p - 1;
|
||||
if (array->size == 1) {
|
||||
GIB_Buffer_Pop_Sstack (cbuf);
|
||||
return 0;
|
||||
}
|
||||
array->size--;
|
||||
var = GIB_Var_Get_Complex (&GIB_DATA(cbuf)->locals, &GIB_DATA(cbuf)->globals, array->dstrs[0]->str, &index, true);
|
||||
var =
|
||||
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals,
|
||||
&GIB_DATA (cbuf)->globals, array->dstrs[0]->str,
|
||||
&index, true);
|
||||
dstring_clearstr (var->array[index]);
|
||||
dstring_appendstr (var->array[index], array->dstrs[array->size]->str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Execute (cbuf_t *cbuf)
|
||||
GIB_Execute (cbuf_t * cbuf)
|
||||
{
|
||||
gib_buffer_data_t *g = GIB_DATA (cbuf);
|
||||
gib_builtin_t *b;
|
||||
gib_function_t *f;
|
||||
int cond;
|
||||
|
||||
int cond;
|
||||
|
||||
if (!g->program)
|
||||
return;
|
||||
if (!g->ip)
|
||||
|
@ -183,7 +195,10 @@ GIB_Execute (cbuf_t *cbuf)
|
|||
if (GIB_Execute_Prepare_Line (cbuf, g->ip))
|
||||
return;
|
||||
if (g->ip->flags & TREE_COND) {
|
||||
cond = g->ip->flags & TREE_NOT ? atoi (cbuf->args->argv[1]->str) : !atoi (cbuf->args->argv[1]->str);
|
||||
cond =
|
||||
g->ip->flags & TREE_NOT ? atoi (cbuf->args->argv[1]->
|
||||
str) : !atoi (cbuf->args->
|
||||
argv[1]->str);
|
||||
if (cond)
|
||||
g->ip = g->ip->jump;
|
||||
} else if (g->ip->flags & TREE_FORNEXT) {
|
||||
|
@ -200,25 +215,34 @@ GIB_Execute (cbuf_t *cbuf)
|
|||
GIB_Buffer_Push_Sstack (cbuf);
|
||||
} else
|
||||
g->waitret = false;
|
||||
if (cbuf->args->argc >= 2 && !strcmp (cbuf->args->argv[1]->str, "=") && ((gib_tree_t *)cbuf->args->argm[1])->delim == ' ') {
|
||||
if (cbuf->args->argc >= 2 && !strcmp (cbuf->args->argv[1]->str, "=")
|
||||
&& ((gib_tree_t *) cbuf->args->argm[1])->delim == ' ') {
|
||||
unsigned int index;
|
||||
gib_var_t *var = GIB_Var_Get_Complex (&g->locals, &g->globals, cbuf->args->argv[0]->str, &index, true);
|
||||
GIB_Var_Assign (var, index, cbuf->args->argv+2, cbuf->args->argc-2);
|
||||
}
|
||||
else if ((b = GIB_Builtin_Find (cbuf->args->argv[0]->str))) {
|
||||
gib_var_t *var =
|
||||
GIB_Var_Get_Complex (&g->locals, &g->globals,
|
||||
cbuf->args->argv[0]->str, &index,
|
||||
true);
|
||||
GIB_Var_Assign (var, index, cbuf->args->argv + 2,
|
||||
cbuf->args->argc - 2);
|
||||
} else if ((b = GIB_Builtin_Find (cbuf->args->argv[0]->str))) {
|
||||
b->func ();
|
||||
} else if ((f = GIB_Function_Find (cbuf->args->argv[0]->str))) {
|
||||
cbuf_t *new = Cbuf_PushStack (&gib_interp);
|
||||
GIB_Function_Execute (new, f, cbuf->args->argv, cbuf->args->argc);
|
||||
cbuf_t *new = Cbuf_PushStack (&gib_interp);
|
||||
|
||||
GIB_Function_Execute (new, f, cbuf->args->argv,
|
||||
cbuf->args->argc);
|
||||
} else {
|
||||
GIB_Execute_Generate_Composite (cbuf);
|
||||
if (Cmd_Command (cbuf->args))
|
||||
GIB_Error ("command", "No builtin, function, or console command named '%s' was found.", cbuf->args->argv[0]->str);
|
||||
GIB_Error ("command",
|
||||
"No builtin, function, or console command named '%s' was found.",
|
||||
cbuf->args->argv[0]->str);
|
||||
}
|
||||
}
|
||||
if (!(g->ip = g->ip->next)) // No more commands
|
||||
if (!(g->ip = g->ip->next)) // No more commands
|
||||
g->done = true;
|
||||
if (cbuf->state) // Let the stack walker figure out what to do
|
||||
if (cbuf->state) // Let the stack walker figure out what
|
||||
// to do
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,9 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -49,7 +50,7 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "QF/gib_tree.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
hashtab_t *gib_functions = 0;
|
||||
hashtab_t *gib_functions = 0;
|
||||
|
||||
/*
|
||||
GIB_Function_New
|
||||
|
@ -61,7 +62,8 @@ static gib_function_t *
|
|||
GIB_Function_New (const char *name)
|
||||
{
|
||||
gib_function_t *new = calloc (1, sizeof (gib_function_t));
|
||||
new->text = dstring_newstr();
|
||||
|
||||
new->text = dstring_newstr ();
|
||||
new->name = strdup (name);
|
||||
return new;
|
||||
}
|
||||
|
@ -72,20 +74,21 @@ GIB_Function_New (const char *name)
|
|||
static const char *
|
||||
GIB_Function_Get_Key (void *ele, void *ptr)
|
||||
{
|
||||
return ((gib_function_t *)ele)->name;
|
||||
return ((gib_function_t *) ele)->name;
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Function_Free (void *ele, void *ptr)
|
||||
{
|
||||
gib_function_t *func = (gib_function_t *)ele;
|
||||
gib_function_t *func = (gib_function_t *) ele;
|
||||
|
||||
dstring_delete (func->text);
|
||||
free ((void *)func->name);
|
||||
free ((void *) func->name);
|
||||
if (func->program)
|
||||
GIB_Tree_Free_Recursive (func->program);
|
||||
if (func->script && !(--func->script->refs)) {
|
||||
free ((void *)func->script->text);
|
||||
free ((void *)func->script->file);
|
||||
free ((void *) func->script->text);
|
||||
free ((void *) func->script->file);
|
||||
free (func->script);
|
||||
}
|
||||
free (func);
|
||||
|
@ -99,23 +102,25 @@ GIB_Function_Free (void *ele, void *ptr)
|
|||
hash if needed.
|
||||
*/
|
||||
void
|
||||
GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, gib_script_t *script, hashtab_t *globals)
|
||||
GIB_Function_Define (const char *name, const char *text, gib_tree_t * program,
|
||||
gib_script_t * script, hashtab_t * globals)
|
||||
{
|
||||
gib_function_t *func;
|
||||
|
||||
|
||||
GIB_Tree_Ref (&program);
|
||||
if (script)
|
||||
script->refs++;
|
||||
if (!gib_functions)
|
||||
gib_functions = Hash_NewTable (1024, GIB_Function_Get_Key, GIB_Function_Free, 0);
|
||||
gib_functions =
|
||||
Hash_NewTable (1024, GIB_Function_Get_Key, GIB_Function_Free, 0);
|
||||
|
||||
func = Hash_Find(gib_functions, name);
|
||||
func = Hash_Find (gib_functions, name);
|
||||
if (func) {
|
||||
dstring_clearstr (func->text);
|
||||
GIB_Tree_Unref (&func->program);
|
||||
if (func->script && !(--func->script->refs)) {
|
||||
free ((void *)func->script->text);
|
||||
free ((void *)func->script->file);
|
||||
free ((void *) func->script->text);
|
||||
free ((void *) func->script->file);
|
||||
free (func->script);
|
||||
}
|
||||
} else {
|
||||
|
@ -144,22 +149,23 @@ GIB_Function_Find (const char *name)
|
|||
}
|
||||
|
||||
void
|
||||
GIB_Function_Prepare_Args (cbuf_t *cbuf, dstring_t **args, unsigned int argc)
|
||||
GIB_Function_Prepare_Args (cbuf_t * cbuf, dstring_t ** args, unsigned int argc)
|
||||
{
|
||||
static hashtab_t *zero = 0;
|
||||
unsigned int i;
|
||||
gib_var_t *var;
|
||||
gib_var_t *var;
|
||||
static char argss[] = "args";
|
||||
|
||||
var = GIB_Var_Get_Complex (&GIB_DATA(cbuf)->locals, &zero, argss, &i, true);
|
||||
var =
|
||||
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &zero, argss, &i, true);
|
||||
var->array = realloc (var->array, sizeof (dstring_t *) * argc);
|
||||
memset (var->array+1, 0, (argc-1) * sizeof (dstring_t *));
|
||||
memset (var->array + 1, 0, (argc - 1) * sizeof (dstring_t *));
|
||||
var->size = argc;
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (var->array[i])
|
||||
dstring_clearstr(var->array[i]);
|
||||
dstring_clearstr (var->array[i]);
|
||||
else
|
||||
var->array[i] = dstring_newstr();
|
||||
var->array[i] = dstring_newstr ();
|
||||
dstring_appendstr (var->array[i], args[i]->str);
|
||||
}
|
||||
}
|
||||
|
@ -172,13 +178,14 @@ GIB_Function_Prepare_Args (cbuf_t *cbuf, dstring_t **args, unsigned int argc)
|
|||
*/
|
||||
|
||||
void
|
||||
GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, dstring_t **args, unsigned int argc)
|
||||
GIB_Function_Execute (cbuf_t * cbuf, gib_function_t * func, dstring_t ** args,
|
||||
unsigned int argc)
|
||||
{
|
||||
GIB_Tree_Ref (&func->program);
|
||||
if (func->script)
|
||||
func->script->refs++;
|
||||
GIB_Buffer_Set_Program (cbuf, func->program);
|
||||
GIB_DATA(cbuf)->script = func->script;
|
||||
GIB_DATA(cbuf)->globals = func->globals;
|
||||
GIB_DATA (cbuf)->script = func->script;
|
||||
GIB_DATA (cbuf)->globals = func->globals;
|
||||
GIB_Function_Prepare_Args (cbuf, args, argc);
|
||||
}
|
||||
|
|
|
@ -32,8 +32,9 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -54,7 +55,8 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "QF/cvar.h"
|
||||
|
||||
static void
|
||||
GIB_Exec_Override_f (void) {
|
||||
GIB_Exec_Override_f (void)
|
||||
{
|
||||
char *f;
|
||||
int mark;
|
||||
|
||||
|
@ -69,18 +71,22 @@ GIB_Exec_Override_f (void) {
|
|||
Sys_Printf ("couldn't exec %s\n", Cmd_Argv (1));
|
||||
return;
|
||||
}
|
||||
if (!Cvar_Command() && (cmd_warncmd->int_val || (developer && developer->int_val)))
|
||||
if (!Cvar_Command ()
|
||||
&& (cmd_warncmd->int_val || (developer && developer->int_val)))
|
||||
Sys_Printf ("execing %s\n", Cmd_Argv (1));
|
||||
if (!strcmp (Cmd_Argv (1) + strlen (Cmd_Argv(1)) - 4, ".gib") || cbuf_active->interpreter == &gib_interp) {
|
||||
if (!strcmp (Cmd_Argv (1) + strlen (Cmd_Argv (1)) - 4, ".gib")
|
||||
|| cbuf_active->interpreter == &gib_interp) {
|
||||
// GIB script, put it in a new buffer on the stack
|
||||
cbuf_t *sub = Cbuf_PushStack (&gib_interp);
|
||||
GIB_DATA(sub)->script = malloc (sizeof (gib_script_t));
|
||||
GIB_DATA(sub)->script->file = strdup (Cmd_Argv(1));
|
||||
GIB_DATA(sub)->script->text = strdup (f);
|
||||
GIB_DATA(sub)->script->refs = 1;
|
||||
cbuf_t *sub = Cbuf_PushStack (&gib_interp);
|
||||
|
||||
GIB_DATA (sub)->script = malloc (sizeof (gib_script_t));
|
||||
GIB_DATA (sub)->script->file = strdup (Cmd_Argv (1));
|
||||
GIB_DATA (sub)->script->text = strdup (f);
|
||||
GIB_DATA (sub)->script->refs = 1;
|
||||
Cbuf_AddText (sub, f);
|
||||
if (gib_parse_error && cbuf_active->interpreter == &gib_interp)
|
||||
GIB_Error ("parse", "%s: Parse error while executing %s.", Cmd_Argv(0), Cmd_Argv(1));
|
||||
GIB_Error ("parse", "%s: Parse error while executing %s.",
|
||||
Cmd_Argv (0), Cmd_Argv (1));
|
||||
} else
|
||||
Cbuf_InsertText (cbuf_active, f);
|
||||
Hunk_FreeToLowMark (mark);
|
||||
|
@ -90,7 +96,7 @@ void
|
|||
GIB_Init (qboolean sandbox)
|
||||
{
|
||||
// Override the exec command with a GIB-aware one
|
||||
if (Cmd_Exists("exec")) {
|
||||
if (Cmd_Exists ("exec")) {
|
||||
Cmd_RemoveCommand ("exec");
|
||||
Cmd_AddCommand ("exec", GIB_Exec_Override_f, "Execute a script file.");
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] = "$Id$";
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
@ -87,6 +87,7 @@ static char
|
|||
GIB_Parse_Match_Dquote (const char *str, unsigned int *i)
|
||||
{
|
||||
unsigned int n = *i;
|
||||
|
||||
for ((*i)++; str[*i]; (*i)++) {
|
||||
if (str[*i] == '\n')
|
||||
break;
|
||||
|
@ -100,8 +101,9 @@ GIB_Parse_Match_Dquote (const char *str, unsigned int *i)
|
|||
char
|
||||
GIB_Parse_Match_Brace (const char *str, unsigned int *i)
|
||||
{
|
||||
char c;
|
||||
char c;
|
||||
unsigned int n = *i;
|
||||
|
||||
for ((*i)++; str[*i]; (*i)++) {
|
||||
if (str[*i] == '\"') {
|
||||
if ((c = GIB_Parse_Match_Dquote (str, i)))
|
||||
|
@ -110,7 +112,7 @@ GIB_Parse_Match_Brace (const char *str, unsigned int *i)
|
|||
if ((c = GIB_Parse_Match_Brace (str, i)))
|
||||
return c;
|
||||
} else if (str[*i] == '}')
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
*i = n;
|
||||
return '{';
|
||||
|
@ -119,8 +121,9 @@ GIB_Parse_Match_Brace (const char *str, unsigned int *i)
|
|||
char
|
||||
GIB_Parse_Match_Paren (const char *str, unsigned int *i)
|
||||
{
|
||||
char c;
|
||||
char c;
|
||||
unsigned int n = *i;
|
||||
|
||||
for ((*i)++; str[*i]; (*i)++) {
|
||||
if (str[*i] == '(') {
|
||||
if ((c = GIB_Parse_Match_Paren (str, i)))
|
||||
|
@ -138,12 +141,13 @@ GIB_Parse_Match_Paren (const char *str, unsigned int *i)
|
|||
char
|
||||
GIB_Parse_Match_Backtick (const char *str, unsigned int *i)
|
||||
{
|
||||
char c;
|
||||
char c;
|
||||
unsigned int n = *i;
|
||||
|
||||
for ((*i)++; str[*i]; (*i)++) {
|
||||
if (str[*i] == '`')
|
||||
return 0;
|
||||
else if (str[*i] == '\"') { // Skip over strings as usual
|
||||
else if (str[*i] == '\"') { // Skip over strings as usual
|
||||
if ((c = GIB_Parse_Match_Dquote (str, i)))
|
||||
return c;
|
||||
}
|
||||
|
@ -155,8 +159,9 @@ GIB_Parse_Match_Backtick (const char *str, unsigned int *i)
|
|||
char
|
||||
GIB_Parse_Match_Index (const char *str, unsigned int *i)
|
||||
{
|
||||
char c;
|
||||
char c;
|
||||
unsigned int n = *i;
|
||||
|
||||
for ((*i)++; str[*i]; (*i)++) {
|
||||
if (str[*i] == '[' && (c = GIB_Parse_Match_Index (str, i)))
|
||||
return c;
|
||||
|
@ -170,12 +175,13 @@ GIB_Parse_Match_Index (const char *str, unsigned int *i)
|
|||
char
|
||||
GIB_Parse_Match_Var (const char *str, unsigned int *i)
|
||||
{
|
||||
char c;
|
||||
char c;
|
||||
|
||||
(*i)++;
|
||||
if (str[*i] == '{' && (c = GIB_Parse_Match_Brace (str, i)))
|
||||
return c;
|
||||
else {
|
||||
for (; isalnum((byte) str[*i]) || str[*i] == '_'; (*i)++);
|
||||
for (; isalnum ((byte) str[*i]) || str[*i] == '_'; (*i)++);
|
||||
if (str[*i] == '[') {
|
||||
if ((c = GIB_Parse_Match_Index (str, i)))
|
||||
return c;
|
||||
|
@ -185,7 +191,7 @@ GIB_Parse_Match_Var (const char *str, unsigned int *i)
|
|||
return 0;
|
||||
}
|
||||
|
||||
qboolean gib_parse_error;
|
||||
qboolean gib_parse_error;
|
||||
unsigned int gib_parse_error_pos;
|
||||
const char *gib_parse_error_msg;
|
||||
|
||||
|
@ -212,19 +218,20 @@ GIB_Parse_ErrorPos (void)
|
|||
// FIXME: Concatenation in stupid circumstances should generate errors
|
||||
|
||||
static gib_tree_t *
|
||||
GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_tree_flags_t flags, gib_tree_t **embedded)
|
||||
GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs,
|
||||
gib_tree_flags_t flags, gib_tree_t ** embedded)
|
||||
{
|
||||
char c, delim, *str;
|
||||
char c, delim, *str;
|
||||
unsigned int tstart, start;
|
||||
gib_tree_t *nodes = 0, *cur, *new, *embs = 0, *tmp;
|
||||
gib_tree_t **node = &nodes;
|
||||
qboolean cat = false;
|
||||
qboolean cat = false;
|
||||
|
||||
gib_parse_error = false;
|
||||
|
||||
while (1) {
|
||||
// Skip whitespace
|
||||
while (program[*i] != '\n' && isspace((byte)program[*i]))
|
||||
while (program[*i] != '\n' && isspace ((byte) program[*i]))
|
||||
(*i)++;
|
||||
// Check for concatenation, skip comma and any more whitespace
|
||||
if (program[*i] == ',') {
|
||||
|
@ -256,7 +263,9 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_t
|
|||
// Find the end of a "normal" token
|
||||
delim = ' ';
|
||||
tstart = *i;
|
||||
for (;program[*i] && !isspace((byte)program[*i]) && program[*i] != ',' && program[*i] != ';'; (*i)++) {
|
||||
for (;
|
||||
program[*i] && !isspace ((byte) program[*i])
|
||||
&& program[*i] != ',' && program[*i] != ';'; (*i)++) {
|
||||
if (program[*i] == '{') {
|
||||
if ((c = GIB_Parse_Match_Brace (program, i)))
|
||||
goto ERROR;
|
||||
|
@ -266,9 +275,10 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_t
|
|||
} else if (program[*i] == '`') {
|
||||
if ((c = GIB_Parse_Match_Backtick (program, i)))
|
||||
goto ERROR;
|
||||
// Handle comments
|
||||
} else if (program[*i] == '/' && program[*i+1] == '/') {
|
||||
for((*i) += 2; program[*i] && program[*i] != '\n'; (*i)++);
|
||||
// Handle comments
|
||||
} else if (program[*i] == '/' && program[*i + 1] == '/') {
|
||||
for ((*i) += 2; program[*i] && program[*i] != '\n';
|
||||
(*i)++);
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
|
@ -278,20 +288,24 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_t
|
|||
cur->start = start + pofs;
|
||||
cur->end = *i + pofs;
|
||||
cur->delim = delim;
|
||||
str = calloc (*i - tstart + 1, sizeof(char));
|
||||
memcpy (str, program+tstart, *i - tstart);
|
||||
|
||||
// Don't bother parsing further if we are concatenating, as the resulting
|
||||
str = calloc (*i - tstart + 1, sizeof (char));
|
||||
memcpy (str, program + tstart, *i - tstart);
|
||||
|
||||
// Don't bother parsing further if we are concatenating, as the
|
||||
// resulting
|
||||
// string would differ from the parsed program.
|
||||
if (cur->delim == '{' && !cat) {
|
||||
// Try to parse sub-program
|
||||
if (!(new = GIB_Parse_Lines (str, tstart+pofs, flags)))
|
||||
if (!(new = GIB_Parse_Lines (str, tstart + pofs, flags)))
|
||||
goto ERROR;
|
||||
cur->children = new;
|
||||
// Check for embedded commands/variables
|
||||
// Check for embedded commands/variables
|
||||
} else if (cur->delim == ' ' || cur->delim == '(') {
|
||||
if (!(cur->children = GIB_Parse_Embedded (str, tstart+pofs, flags, &new))) {
|
||||
// There could be no embedded elements, so check for a real error
|
||||
if (!
|
||||
(cur->children =
|
||||
GIB_Parse_Embedded (str, tstart + pofs, flags, &new))) {
|
||||
// There could be no embedded elements, so check for a real
|
||||
// error
|
||||
if (gib_parse_error)
|
||||
goto ERROR;
|
||||
} else {
|
||||
|
@ -309,7 +323,7 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_t
|
|||
if (cur->delim == ' ' && str[0] == '@' && !cat) {
|
||||
cur->flags |= TREE_ASPLIT;
|
||||
}
|
||||
// We can handle escape characters now
|
||||
// We can handle escape characters now
|
||||
} else if (cur->delim == '\"')
|
||||
GIB_Process_Escapes (str);
|
||||
cur->str = str;
|
||||
|
@ -326,32 +340,40 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_t
|
|||
(*i)++;
|
||||
node = &cur->next;
|
||||
}
|
||||
DONE:
|
||||
DONE:
|
||||
*embedded = embs;
|
||||
return nodes;
|
||||
ERROR:
|
||||
ERROR:
|
||||
if (c)
|
||||
GIB_Parse_Error (va("Could not find match for '%c'.", c), *i+pofs);
|
||||
GIB_Parse_Error (va ("Could not find match for '%c'.", c), *i + pofs);
|
||||
if (nodes)
|
||||
GIB_Tree_Free_Recursive (nodes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gib_tree_t *
|
||||
GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
|
||||
GIB_Parse_Semantic_Preprocess (gib_tree_t * line)
|
||||
{
|
||||
gib_tree_t *p, *start = line;
|
||||
unsigned int flags = line->flags;
|
||||
while (!strcmp (line->children->str, "if") || !strcmp (line->children->str, "ifnot")) {
|
||||
|
||||
while (!strcmp (line->children->str, "if")
|
||||
|| !strcmp (line->children->str, "ifnot")) {
|
||||
// Sanity checking
|
||||
if (!line->children->next || !line->children->next->next) {
|
||||
GIB_Parse_Error ("Not enough arguments to 'if' statement.", line->start);
|
||||
GIB_Parse_Error ("Not enough arguments to 'if' statement.",
|
||||
line->start);
|
||||
return line;
|
||||
} else if (!line->children->next->next->children || line->children->next->next->delim != '{') {
|
||||
GIB_Parse_Error ("First program block in 'if' statement not enclosed in braces or invalid.", line->start);
|
||||
} else if (!line->children->next->next->children
|
||||
|| line->children->next->next->delim != '{') {
|
||||
GIB_Parse_Error
|
||||
("First program block in 'if' statement not enclosed in braces or invalid.",
|
||||
line->start);
|
||||
return line;
|
||||
} else if (line->flags & TREE_EMBED) {
|
||||
GIB_Parse_Error ("'if' statements may not be used in embedded commands.", line->start);
|
||||
GIB_Parse_Error
|
||||
("'if' statements may not be used in embedded commands.",
|
||||
line->start);
|
||||
return line;
|
||||
}
|
||||
// Set conditional flag
|
||||
|
@ -364,17 +386,21 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
|
|||
line->next = line->children->next->next->children;
|
||||
line->children->next->next->children = 0;
|
||||
// Find end of subprogram
|
||||
while (line->next) line = line->next;
|
||||
while (line->next)
|
||||
line = line->next;
|
||||
line->next = GIB_Tree_New (flags | TREE_END);
|
||||
line = line->next;
|
||||
// Mark jump point
|
||||
p->jump = line;
|
||||
line->flags |= TREE_END; // Last instruction of subprogram
|
||||
line->flags |= TREE_END; // Last instruction of subprogram
|
||||
// Handle "else"
|
||||
if (p->children->next->next->next && !strcmp (p->children->next->next->next->str, "else")) {
|
||||
if (p->children->next->next->next
|
||||
&& !strcmp (p->children->next->next->next->str, "else")) {
|
||||
// Sanity checking
|
||||
if (!p->children->next->next->next->next) {
|
||||
GIB_Parse_Error ("'if' statement contains 'else' but no secondary program block or command.", line->start);
|
||||
GIB_Parse_Error
|
||||
("'if' statement contains 'else' but no secondary program block or command.",
|
||||
line->start);
|
||||
return line;
|
||||
}
|
||||
// Is "else" followed by a subprogram?
|
||||
|
@ -382,7 +408,8 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
|
|||
// Move subprogram inline
|
||||
line->next = p->children->next->next->next->next->children;
|
||||
p->children->next->next->next->next->children = 0;
|
||||
while (line->next) line = line->next;
|
||||
while (line->next)
|
||||
line = line->next;
|
||||
} else {
|
||||
// Push rest of tokens into a new line
|
||||
line->next = GIB_Tree_New (flags);
|
||||
|
@ -390,7 +417,9 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
|
|||
p->children->next->next->next->next = 0;
|
||||
line = line->next;
|
||||
}
|
||||
} else break; // Don't touch if statements in the sub program
|
||||
} else
|
||||
break; // Don't touch if statements in the sub
|
||||
// program
|
||||
}
|
||||
// Now we know our exit point, set it on all our ending instructions
|
||||
while (start) {
|
||||
|
@ -405,13 +434,19 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
|
|||
if (!strcmp (line->children->str, "while")) {
|
||||
// Sanity checks
|
||||
if (!line->children->next || !line->children->next->next) {
|
||||
GIB_Parse_Error ("Not enough arguments to 'while' statement.", line->start);
|
||||
GIB_Parse_Error ("Not enough arguments to 'while' statement.",
|
||||
line->start);
|
||||
return line;
|
||||
} else if (!line->children->next->next->children || line->children->next->next->delim != '{') {
|
||||
GIB_Parse_Error ("Program block in 'while' statement not enclosed in braces or invalid.", line->start);
|
||||
} else if (!line->children->next->next->children
|
||||
|| line->children->next->next->delim != '{') {
|
||||
GIB_Parse_Error
|
||||
("Program block in 'while' statement not enclosed in braces or invalid.",
|
||||
line->start);
|
||||
return line;
|
||||
} else if (line->flags & TREE_EMBED) {
|
||||
GIB_Parse_Error ("'while' statements may not be used in embedded commands.", line->start);
|
||||
GIB_Parse_Error
|
||||
("'while' statements may not be used in embedded commands.",
|
||||
line->start);
|
||||
return line;
|
||||
}
|
||||
// Set conditional flag
|
||||
|
@ -432,16 +467,23 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
|
|||
p->jump = line;
|
||||
} else if (!strcmp (line->children->str, "for")) {
|
||||
gib_tree_t *tmp;
|
||||
|
||||
// Sanity checks
|
||||
if (!line->children->next || !line->children->next->next || strcmp (line->children->next->next->str, "in") || !line->children->next->next->next || !line->children->next->next->next->next) {
|
||||
if (!line->children->next || !line->children->next->next
|
||||
|| strcmp (line->children->next->next->str, "in")
|
||||
|| !line->children->next->next->next
|
||||
|| !line->children->next->next->next->next) {
|
||||
GIB_Parse_Error ("Malformed 'for' statement.", line->start);
|
||||
return line;
|
||||
}
|
||||
// Find last token in line (contains program block)
|
||||
for (tmp = line->children->next->next->next->next; tmp->next; tmp = tmp->next);
|
||||
for (tmp = line->children->next->next->next->next; tmp->next;
|
||||
tmp = tmp->next);
|
||||
// More sanity
|
||||
if (tmp->delim != '{' || !tmp->children) {
|
||||
GIB_Parse_Error ("Program block in 'for' statement not enclosed in braces or invalid.", line->start);
|
||||
GIB_Parse_Error
|
||||
("Program block in 'for' statement not enclosed in braces or invalid.",
|
||||
line->start);
|
||||
return line;
|
||||
}
|
||||
p = line;
|
||||
|
@ -457,19 +499,19 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
|
|||
line = line->next;
|
||||
// Mark jump point out of loop
|
||||
p->jump = line;
|
||||
}
|
||||
}
|
||||
return line;
|
||||
}
|
||||
}
|
||||
|
||||
gib_tree_t *
|
||||
GIB_Parse_Lines (const char *program, unsigned int pofs, gib_tree_flags_t flags)
|
||||
{
|
||||
unsigned int i = 0, lstart;
|
||||
gib_tree_t *lines = 0, *cur, *tokens, **line = &lines, *embs;
|
||||
char *str;
|
||||
char *str;
|
||||
|
||||
while (1) {
|
||||
while (isspace((byte)program[i]) || program[i] == ';')
|
||||
while (isspace ((byte) program[i]) || program[i] == ';')
|
||||
i++;
|
||||
if (!program[i])
|
||||
break;
|
||||
|
@ -479,8 +521,8 @@ GIB_Parse_Lines (const char *program, unsigned int pofs, gib_tree_flags_t flags)
|
|||
// Link it in
|
||||
cur = GIB_Tree_New (flags);
|
||||
cur->delim = '\n';
|
||||
str = calloc (i - lstart + 1, sizeof(char));
|
||||
memcpy (str, program+lstart, i - lstart);
|
||||
str = calloc (i - lstart + 1, sizeof (char));
|
||||
memcpy (str, program + lstart, i - lstart);
|
||||
cur->str = str;
|
||||
cur->start = lstart + pofs;
|
||||
cur->end = i + pofs;
|
||||
|
@ -500,48 +542,51 @@ GIB_Parse_Lines (const char *program, unsigned int pofs, gib_tree_flags_t flags)
|
|||
goto ERROR;
|
||||
}
|
||||
return lines;
|
||||
ERROR:
|
||||
ERROR:
|
||||
if (lines)
|
||||
GIB_Tree_Free_Recursive (lines);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gib_tree_t *
|
||||
GIB_Parse_Embedded (const char *program, unsigned int pofs, gib_tree_flags_t flags, gib_tree_t **embedded)
|
||||
GIB_Parse_Embedded (const char *program, unsigned int pofs,
|
||||
gib_tree_flags_t flags, gib_tree_t ** embedded)
|
||||
{
|
||||
unsigned int i, n, t;
|
||||
char c, d, *str;
|
||||
char c, d, *str;
|
||||
gib_tree_t *lines = 0, **line = &lines, *cur, *tokens, *emb, *tmp;
|
||||
unsigned int start, end;
|
||||
|
||||
|
||||
gib_parse_error = false;
|
||||
*embedded = 0;
|
||||
|
||||
|
||||
for (i = 0; program[i]; i++) {
|
||||
if (program[i] == '`' || (program[i] == '$' && program[i+1] == '(')) {
|
||||
if (program[i] == '`' || (program[i] == '$' && program[i + 1] == '(')) {
|
||||
// Extract the embedded command
|
||||
start = i;
|
||||
if (program[i] == '`') {
|
||||
n = i+1;
|
||||
n = i + 1;
|
||||
if ((c = GIB_Parse_Match_Backtick (program, &i)))
|
||||
goto ERROR;
|
||||
} else {
|
||||
n = ++i+1;
|
||||
n = ++i + 1;
|
||||
if ((c = GIB_Parse_Match_Paren (program, &i)))
|
||||
goto ERROR;
|
||||
}
|
||||
end = i+1;
|
||||
end = i + 1;
|
||||
// Construct the actual line to be executed
|
||||
cur = GIB_Tree_New (flags | TREE_EMBED);
|
||||
cur->delim = '`';
|
||||
str = calloc (i - n + 1, sizeof (char));
|
||||
memcpy (str, program+n, i - n);
|
||||
memcpy (str, program + n, i - n);
|
||||
cur->str = str;
|
||||
cur->start = start + pofs;
|
||||
cur->end = end + pofs;
|
||||
c = 0;
|
||||
t = 0;
|
||||
if (!(tokens = GIB_Parse_Tokens (cur->str, &t, start + pofs, flags, &emb)))
|
||||
if (!
|
||||
(tokens =
|
||||
GIB_Parse_Tokens (cur->str, &t, start + pofs, flags, &emb)))
|
||||
goto ERROR;
|
||||
cur->children = tokens;
|
||||
GIB_Parse_Semantic_Preprocess (cur)->next = *embedded;
|
||||
|
@ -555,7 +600,8 @@ GIB_Parse_Embedded (const char *program, unsigned int pofs, gib_tree_flags_t fla
|
|||
*embedded = emb;
|
||||
} else
|
||||
*embedded = cur;
|
||||
// Create a representative child node for GIB_Process_Embedded to use
|
||||
// Create a representative child node for GIB_Process_Embedded to
|
||||
// use
|
||||
cur = GIB_Tree_New (flags | TREE_EMBED);
|
||||
cur->delim = '`';
|
||||
// Save start/end indices
|
||||
|
@ -563,27 +609,28 @@ GIB_Parse_Embedded (const char *program, unsigned int pofs, gib_tree_flags_t fla
|
|||
cur->end = end;
|
||||
*line = cur;
|
||||
line = &cur->next;
|
||||
// Check for variable substitution
|
||||
// Check for variable substitution
|
||||
} else if (program[i] == '$' || program[i] == '#') {
|
||||
// Extract variable name
|
||||
start = i;
|
||||
end = 0;
|
||||
d = program[i];
|
||||
if (program[i+1] == '{') {
|
||||
n = i+2;
|
||||
if (program[i + 1] == '{') {
|
||||
n = i + 2;
|
||||
end++;
|
||||
} else
|
||||
n = i+1;
|
||||
n = i + 1;
|
||||
if ((c = GIB_Parse_Match_Var (program, &i)))
|
||||
goto ERROR;
|
||||
end += i;
|
||||
|
||||
|
||||
cur = GIB_Tree_New (flags | TREE_EMBED);
|
||||
cur->delim = d;
|
||||
str = calloc (i - n + 1, sizeof(char));
|
||||
memcpy (str, program+n, i - n);
|
||||
str = calloc (i - n + 1, sizeof (char));
|
||||
memcpy (str, program + n, i - n);
|
||||
cur->str = str;
|
||||
// Can we use the name as is, or must processing be done at runtime?
|
||||
// Can we use the name as is, or must processing be done at
|
||||
// runtime?
|
||||
if (strchr (str, '$') || strchr (str, '#'))
|
||||
cur->flags |= TREE_P_EMBED;
|
||||
// Save start/end indices
|
||||
|
@ -592,12 +639,12 @@ GIB_Parse_Embedded (const char *program, unsigned int pofs, gib_tree_flags_t fla
|
|||
*line = cur;
|
||||
line = &cur->next;
|
||||
// Don't skip anything important
|
||||
if (program[n-1] != '{')
|
||||
if (program[n - 1] != '{')
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
ERROR:
|
||||
ERROR:
|
||||
if (c)
|
||||
GIB_Parse_Error (va ("Could not find match for '%c'.", c), i + pofs);
|
||||
if (lines)
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] = "$Id$";
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
@ -52,13 +52,14 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "exp.h"
|
||||
|
||||
static int
|
||||
GIB_Process_Variable (dstring_t *token, unsigned int *i)
|
||||
GIB_Process_Variable (dstring_t * token, unsigned int *i)
|
||||
{
|
||||
hashtab_t *one = GIB_DATA(cbuf_active)->locals, *two = GIB_DATA(cbuf_active)->globals;
|
||||
hashtab_t *one = GIB_DATA (cbuf_active)->locals, *two =
|
||||
GIB_DATA (cbuf_active)->globals;
|
||||
unsigned int n = *i, j, k, start = *i, index = 0, len, len2;
|
||||
gib_var_t *var = 0;
|
||||
cvar_t *cvar;
|
||||
char c;
|
||||
gib_var_t *var = 0;
|
||||
cvar_t *cvar;
|
||||
char c;
|
||||
const char *str;
|
||||
|
||||
(*i)++;
|
||||
|
@ -70,7 +71,8 @@ GIB_Process_Variable (dstring_t *token, unsigned int *i)
|
|||
n += 2;
|
||||
len = 1;
|
||||
} else {
|
||||
for (; isalnum((byte) token->str[*i]) || token->str[*i] == '_'; (*i)++);
|
||||
for (; isalnum ((byte) token->str[*i]) || token->str[*i] == '_';
|
||||
(*i)++);
|
||||
if (token->str[*i] == '[') {
|
||||
if ((c = GIB_Parse_Match_Index (token->str, i))) {
|
||||
GIB_Error ("Parse", "Could not find match for %c.", c);
|
||||
|
@ -89,25 +91,26 @@ GIB_Process_Variable (dstring_t *token, unsigned int *i)
|
|||
if (GIB_Process_Variable (token, &n))
|
||||
return -1;
|
||||
index = 0;
|
||||
if (n && token->str[n-1] == ']')
|
||||
for (j = n-1; j; j--)
|
||||
if (n && token->str[n - 1] == ']')
|
||||
for (j = n - 1; j; j--)
|
||||
if (token->str[j] == '[') {
|
||||
index = atoi (token->str+j+1);
|
||||
index = atoi (token->str + j + 1);
|
||||
token->str[j] = 0;
|
||||
}
|
||||
if ((var = GIB_Var_Get (one, two, token->str+k)) && index < var->size && var->array[index]) {
|
||||
if ((var = GIB_Var_Get (one, two, token->str + k)) && index < var->size
|
||||
&& var->array[index]) {
|
||||
if (token->str[start] == '#')
|
||||
str = va("%u", var->size - index);
|
||||
str = va ("%u", var->size - index);
|
||||
else
|
||||
str = var->array[index]->str;
|
||||
} else if (token->str[start] == '#')
|
||||
str = "0";
|
||||
else if ((cvar = Cvar_FindVar (token->str+k)))
|
||||
else if ((cvar = Cvar_FindVar (token->str + k)))
|
||||
str = cvar->string;
|
||||
else
|
||||
str = "";
|
||||
token->str[n] = c;
|
||||
len += n-start;
|
||||
len += n - start;
|
||||
len2 = strlen (str);
|
||||
dstring_replace (token, start, len, str, len2);
|
||||
*i = start + len2 - 1;
|
||||
|
@ -117,91 +120,105 @@ GIB_Process_Variable (dstring_t *token, unsigned int *i)
|
|||
int
|
||||
GIB_Process_Math (struct dstring_s *token, unsigned int i)
|
||||
{
|
||||
double value;
|
||||
|
||||
value = EXP_Evaluate (token->str+i);
|
||||
double value;
|
||||
|
||||
value = EXP_Evaluate (token->str + i);
|
||||
if (EXP_ERROR) {
|
||||
GIB_Error ("math", "Expression \"%s\" caused an error:\n%s", token->str, EXP_GetErrorMsg());
|
||||
GIB_Error ("math", "Expression \"%s\" caused an error:\n%s", token->str,
|
||||
EXP_GetErrorMsg ());
|
||||
return -1;
|
||||
} else {
|
||||
token->str[i] = 0;
|
||||
token->size = i+1;
|
||||
token->size = i + 1;
|
||||
dasprintf (token, "%.10g", value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
GIB_Process_Embedded (gib_tree_t *node, cbuf_args_t *args)
|
||||
GIB_Process_Embedded (gib_tree_t * node, cbuf_args_t * args)
|
||||
{
|
||||
unsigned int n, j;
|
||||
gib_var_t *var;
|
||||
cvar_t *cvar;
|
||||
gib_var_t *var;
|
||||
cvar_t *cvar;
|
||||
gib_tree_t *cur;
|
||||
unsigned int index, prev = 0;
|
||||
const char *str = node->str;
|
||||
|
||||
|
||||
for (cur = node->children; cur; cur = cur->next) {
|
||||
if (cur->start > prev)
|
||||
dstring_appendsubstr (args->argv[args->argc-1], str+prev, cur->start - prev);
|
||||
dstring_appendsubstr (args->argv[args->argc - 1], str + prev,
|
||||
cur->start - prev);
|
||||
prev = cur->end;
|
||||
if (!cur->str) {
|
||||
struct gib_dsarray_s *retvals = GIB_DATA(cbuf_active)->stack.values+GIB_DATA(cbuf_active)->stack.p-1;
|
||||
struct gib_dsarray_s *retvals =
|
||||
GIB_DATA (cbuf_active)->stack.values +
|
||||
GIB_DATA (cbuf_active)->stack.p - 1;
|
||||
if (retvals->size != 1) {
|
||||
if (!*args->argv[args->argc-1]->str)
|
||||
if (!*args->argv[args->argc - 1]->str)
|
||||
args->argc--;
|
||||
for (j = 0; j < retvals->size; j++) {
|
||||
Cbuf_ArgsAdd (args, retvals->dstrs[j]->str);
|
||||
args->argm[args->argc-1] = node;
|
||||
args->argm[args->argc - 1] = node;
|
||||
}
|
||||
if (str[prev] && retvals->size) // Still more stuff left?
|
||||
if (str[prev] && retvals->size) // Still more stuff left?
|
||||
Cbuf_ArgsAdd (args, "");
|
||||
} else
|
||||
dstring_appendstr (args->argv[args->argc-1], retvals->dstrs[0]->str);
|
||||
dstring_appendstr (args->argv[args->argc - 1],
|
||||
retvals->dstrs[0]->str);
|
||||
GIB_Buffer_Pop_Sstack (cbuf_active);
|
||||
} else if (cur->flags & TREE_P_EMBED) {
|
||||
n = args->argv[args->argc-1]->size-1;
|
||||
n = args->argv[args->argc - 1]->size - 1;
|
||||
if (cur->delim == '$')
|
||||
dstring_appendstr (args->argv[args->argc-1], "${");
|
||||
dstring_appendstr (args->argv[args->argc - 1], "${");
|
||||
else
|
||||
dstring_appendstr (args->argv[args->argc-1], "#{");
|
||||
dstring_appendstr (args->argv[args->argc-1], cur->str);
|
||||
dstring_appendstr (args->argv[args->argc-1], "}");
|
||||
if (GIB_Process_Variable (args->argv[args->argc-1], &n))
|
||||
dstring_appendstr (args->argv[args->argc - 1], "#{");
|
||||
dstring_appendstr (args->argv[args->argc - 1], cur->str);
|
||||
dstring_appendstr (args->argv[args->argc - 1], "}");
|
||||
if (GIB_Process_Variable (args->argv[args->argc - 1], &n))
|
||||
return -1;
|
||||
} else if ((var = GIB_Var_Get_Complex (&GIB_DATA(cbuf_active)->locals, &GIB_DATA(cbuf_active)->globals, (char *)cur->str, &index, false))) {
|
||||
} else
|
||||
if ((var =
|
||||
GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals,
|
||||
&GIB_DATA (cbuf_active)->globals,
|
||||
(char *) cur->str, &index, false))) {
|
||||
if (cur->delim == '$')
|
||||
dstring_appendstr (args->argv[args->argc-1], var->array[index]->str);
|
||||
dstring_appendstr (args->argv[args->argc - 1],
|
||||
var->array[index]->str);
|
||||
else
|
||||
dasprintf (args->argv[args->argc-1], "%u", var->size - index);
|
||||
dasprintf (args->argv[args->argc - 1], "%u", var->size - index);
|
||||
} else if (cur->delim == '#')
|
||||
dstring_appendstr (args->argv[args->argc-1], "0");
|
||||
dstring_appendstr (args->argv[args->argc - 1], "0");
|
||||
else if ((cvar = Cvar_FindVar (cur->str)))
|
||||
dstring_appendstr (args->argv[args->argc-1], cvar->string);
|
||||
dstring_appendstr (args->argv[args->argc - 1], cvar->string);
|
||||
}
|
||||
if (str[prev])
|
||||
dstring_appendstr (args->argv[args->argc-1], str+prev);
|
||||
dstring_appendstr (args->argv[args->argc - 1], str + prev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Process_Escapes (char *str)
|
||||
{
|
||||
int i, j;
|
||||
char c;
|
||||
int i, j;
|
||||
char c;
|
||||
|
||||
for (i = 0, j = 0; str[i]; j++) {
|
||||
if (str[i] == '\\') {
|
||||
i++;
|
||||
if (isdigit ((byte) str[i]) &&
|
||||
isdigit ((byte) str[i+1]) &&
|
||||
isdigit ((byte) str[i+2])) {
|
||||
unsigned int num;
|
||||
if ((num = 100 * (str[i] - '0') + 10 * (str[i+1] - '0') + (str[i+2] - '0')) <= 255) {
|
||||
c = (char) num;
|
||||
i += 3;
|
||||
} else
|
||||
c = '\\';
|
||||
} else switch (str[i++]) {
|
||||
isdigit ((byte) str[i + 1]) && isdigit ((byte) str[i + 2])) {
|
||||
unsigned int num;
|
||||
|
||||
if ((num =
|
||||
100 * (str[i] - '0') + 10 * (str[i + 1] - '0') +
|
||||
(str[i + 2] - '0')) <= 255) {
|
||||
c = (char) num;
|
||||
i += 3;
|
||||
} else
|
||||
c = '\\';
|
||||
} else
|
||||
switch (str[i++]) {
|
||||
case 'n':
|
||||
c = '\n';
|
||||
break;
|
||||
|
@ -221,7 +238,7 @@ GIB_Process_Escapes (char *str)
|
|||
c = '\\';
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
str[j] = c;
|
||||
} else
|
||||
str[j] = str[i++];
|
||||
|
|
|
@ -32,8 +32,9 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -46,7 +47,7 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "QF/gib_regex.h"
|
||||
#include "QF/qtypes.h"
|
||||
|
||||
hashtab_t *gib_regexs;
|
||||
hashtab_t *gib_regexs;
|
||||
static char errstr[1024];
|
||||
|
||||
static const char *
|
||||
|
@ -63,7 +64,7 @@ GIB_Regex_Free (void *ele, void *ptr)
|
|||
free (ele);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
GIB_Regex_Init (void)
|
||||
{
|
||||
gib_regexs = Hash_NewTable (512, GIB_Regex_Get_Key, GIB_Regex_Free, 0);
|
||||
|
@ -74,8 +75,8 @@ GIB_Regex_Compile (const char *regex, int cflags)
|
|||
{
|
||||
static unsigned int num_regexs = 0;
|
||||
gib_regex_t *reg;
|
||||
int res;
|
||||
|
||||
int res;
|
||||
|
||||
// Already compiled ?
|
||||
if ((reg = Hash_Find (gib_regexs, regex))) {
|
||||
// Did cflags change?
|
||||
|
@ -84,21 +85,20 @@ GIB_Regex_Compile (const char *regex, int cflags)
|
|||
reg->cflags = cflags;
|
||||
if ((res = regcomp (&(reg->comp), regex, cflags))) {
|
||||
// Blew up, remove from hash
|
||||
regerror(res, &(reg->comp), errstr, sizeof(errstr));
|
||||
regerror (res, &(reg->comp), errstr, sizeof (errstr));
|
||||
regfree (&(reg->comp));
|
||||
free (reg->regex);
|
||||
free (Hash_Del (gib_regexs, regex));
|
||||
num_regexs--;
|
||||
return 0;
|
||||
} else
|
||||
} else
|
||||
return &(reg->comp);
|
||||
}
|
||||
else
|
||||
} else
|
||||
return &(reg->comp);
|
||||
} else {
|
||||
reg = calloc (1, sizeof (gib_regex_t));
|
||||
if ((res = regcomp (&(reg->comp), regex, cflags))) {
|
||||
regerror(res, &(reg->comp), errstr, sizeof(errstr));
|
||||
regerror (res, &(reg->comp), errstr, sizeof (errstr));
|
||||
regfree (&(reg->comp));
|
||||
free (reg);
|
||||
return 0;
|
||||
|
@ -108,7 +108,7 @@ GIB_Regex_Compile (const char *regex, int cflags)
|
|||
if (++num_regexs > 128) {
|
||||
Hash_FlushTable (gib_regexs);
|
||||
num_regexs = 0;
|
||||
}
|
||||
}
|
||||
Hash_Add (gib_regexs, reg);
|
||||
return &(reg->comp);
|
||||
}
|
||||
|
@ -124,44 +124,48 @@ GIB_Regex_Error (void)
|
|||
int
|
||||
GIB_Regex_Translate_Options (const char *opstr)
|
||||
{
|
||||
int options = 0;
|
||||
int options = 0;
|
||||
|
||||
if (strchr (opstr, 'i'))
|
||||
options |= REG_ICASE;
|
||||
if (strchr (opstr, 'n'))
|
||||
options |= REG_NEWLINE;
|
||||
return options;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
GIB_Regex_Apply_Match (regmatch_t match[10], dstring_t *dstr, unsigned int ofs, const char *replace)
|
||||
GIB_Regex_Apply_Match (regmatch_t match[10], dstring_t * dstr, unsigned int ofs,
|
||||
const char *replace)
|
||||
{
|
||||
int i, start, len, sub, rlen = strlen(replace);
|
||||
char *matched;
|
||||
|
||||
start = match[0].rm_so+ofs;
|
||||
int i, start, len, sub, rlen = strlen (replace);
|
||||
char *matched;
|
||||
|
||||
start = match[0].rm_so + ofs;
|
||||
len = match[0].rm_eo - match[0].rm_so;
|
||||
|
||||
|
||||
// Save matched pattern space
|
||||
matched = calloc (len + 1, sizeof(char));
|
||||
memcpy (matched, dstr->str+start, match[0].rm_eo - match[0].rm_so);
|
||||
|
||||
matched = calloc (len + 1, sizeof (char));
|
||||
memcpy (matched, dstr->str + start, match[0].rm_eo - match[0].rm_so);
|
||||
|
||||
dstring_replace (dstr, start, len, replace, rlen);
|
||||
for (i = start; i < start+rlen; i++) {
|
||||
for (i = start; i < start + rlen; i++) {
|
||||
if (dstr->str[i] == '\\') {
|
||||
if (dstr->str[i+1] == '&') {
|
||||
if (dstr->str[i + 1] == '&') {
|
||||
dstring_snip (dstr, i, 1);
|
||||
rlen--;
|
||||
continue;
|
||||
}
|
||||
if (isdigit ((byte) dstr->str[i+1])) {
|
||||
if (i && dstr->str[i-1] == '\\') { // Escaped, not a true back reference
|
||||
if (isdigit ((byte) dstr->str[i + 1])) {
|
||||
if (i && dstr->str[i - 1] == '\\') { // Escaped, not a true
|
||||
// back reference
|
||||
dstring_snip (dstr, i, 1);
|
||||
rlen--;
|
||||
continue;
|
||||
}
|
||||
sub = dstr->str[i+1] - '0';
|
||||
sub = dstr->str[i + 1] - '0';
|
||||
if (match[sub].rm_so != -1) {
|
||||
dstring_replace (dstr, i, 2, matched+match[sub].rm_so, match[sub].rm_eo - match[sub].rm_so);
|
||||
dstring_replace (dstr, i, 2, matched + match[sub].rm_so,
|
||||
match[sub].rm_eo - match[sub].rm_so);
|
||||
rlen += match[sub].rm_eo - match[sub].rm_so - 2;
|
||||
} else {
|
||||
dstring_snip (dstr, i, 2);
|
||||
|
@ -170,7 +174,7 @@ GIB_Regex_Apply_Match (regmatch_t match[10], dstring_t *dstr, unsigned int ofs,
|
|||
}
|
||||
} else if (dstr->str[i] == '&') {
|
||||
dstring_replace (dstr, i, 1, matched, len);
|
||||
rlen += strlen(matched) - 1;
|
||||
rlen += strlen (matched) - 1;
|
||||
}
|
||||
}
|
||||
free (matched);
|
||||
|
|
|
@ -32,14 +32,14 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] = "$Id$";
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "QF/sys.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/cbuf.h"
|
||||
#include "QF/gib_parse.h"
|
||||
#include "QF/gib_thread.h"
|
||||
|
@ -51,12 +51,12 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
gib_thread_t *gib_threads = 0;
|
||||
gib_thread_t **gib_thread_p = &gib_threads;
|
||||
|
||||
hashtab_t *gib_events;
|
||||
hashtab_t *gib_events;
|
||||
|
||||
static unsigned long int nextid = 0;
|
||||
|
||||
void
|
||||
GIB_Thread_Add (gib_thread_t *thread)
|
||||
GIB_Thread_Add (gib_thread_t * thread)
|
||||
{
|
||||
thread->prev = *gib_thread_p;
|
||||
*gib_thread_p = thread;
|
||||
|
@ -64,7 +64,7 @@ GIB_Thread_Add (gib_thread_t *thread)
|
|||
}
|
||||
|
||||
void
|
||||
GIB_Thread_Remove (gib_thread_t *thread)
|
||||
GIB_Thread_Remove (gib_thread_t * thread)
|
||||
{
|
||||
if (thread->prev)
|
||||
thread->prev->next = thread->next;
|
||||
|
@ -82,8 +82,8 @@ gib_thread_t *
|
|||
GIB_Thread_Find (unsigned long int id)
|
||||
{
|
||||
gib_thread_t *cur;
|
||||
|
||||
for (cur = gib_threads; cur; cur=cur->next)
|
||||
|
||||
for (cur = gib_threads; cur; cur = cur->next)
|
||||
if (cur->id == id)
|
||||
return cur;
|
||||
return 0;
|
||||
|
@ -92,7 +92,8 @@ GIB_Thread_Find (unsigned long int id)
|
|||
gib_thread_t *
|
||||
GIB_Thread_New (void)
|
||||
{
|
||||
gib_thread_t *new = calloc (1, sizeof(gib_thread_t));
|
||||
gib_thread_t *new = calloc (1, sizeof (gib_thread_t));
|
||||
|
||||
new->cbuf = Cbuf_New (&gib_interp);
|
||||
new->id = nextid;
|
||||
nextid++;
|
||||
|
@ -100,7 +101,7 @@ GIB_Thread_New (void)
|
|||
}
|
||||
|
||||
static void
|
||||
GIB_Thread_Delete (gib_thread_t *thread)
|
||||
GIB_Thread_Delete (gib_thread_t * thread)
|
||||
{
|
||||
Cbuf_DeleteStack (thread->cbuf);
|
||||
free (thread);
|
||||
|
@ -110,9 +111,10 @@ void
|
|||
GIB_Thread_Execute (void)
|
||||
{
|
||||
gib_thread_t *cur, *tmp;
|
||||
|
||||
if (!gib_threads)
|
||||
return;
|
||||
|
||||
|
||||
for (cur = gib_threads; cur; cur = tmp) {
|
||||
tmp = cur->next;
|
||||
if (cur->trash) {
|
||||
|
@ -126,14 +128,15 @@ GIB_Thread_Execute (void)
|
|||
static const char *
|
||||
GIB_Event_Get_Key (void *ele, void *ptr)
|
||||
{
|
||||
return ((gib_event_t *)ele)->name;
|
||||
return ((gib_event_t *) ele)->name;
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Event_Free (void *ele, void *ptr)
|
||||
{
|
||||
gib_event_t *ev = (gib_event_t *)ele;
|
||||
free ((void *)ev->name);
|
||||
gib_event_t *ev = (gib_event_t *) ele;
|
||||
|
||||
free ((void *) ev->name);
|
||||
free (ev);
|
||||
}
|
||||
|
||||
|
@ -141,7 +144,7 @@ gib_event_t *
|
|||
GIB_Event_New (const char *name)
|
||||
{
|
||||
gib_event_t *new;
|
||||
|
||||
|
||||
new = calloc (1, sizeof (gib_event_t));
|
||||
new->name = strdup (name);
|
||||
Hash_Add (gib_events, new);
|
||||
|
@ -149,10 +152,10 @@ GIB_Event_New (const char *name)
|
|||
}
|
||||
|
||||
int
|
||||
GIB_Event_Register (const char *name, gib_function_t *func)
|
||||
GIB_Event_Register (const char *name, gib_function_t * func)
|
||||
{
|
||||
gib_event_t *ev;
|
||||
|
||||
|
||||
if (!(ev = Hash_Find (gib_events, name)))
|
||||
return -1;
|
||||
ev->func = func;
|
||||
|
@ -160,28 +163,28 @@ GIB_Event_Register (const char *name, gib_function_t *func)
|
|||
}
|
||||
|
||||
void
|
||||
GIB_Event_Callback (gib_event_t *event, unsigned int argc, ...)
|
||||
GIB_Event_Callback (gib_event_t * event, unsigned int argc, ...)
|
||||
{
|
||||
gib_function_t *f = event->func;
|
||||
gib_thread_t *thread;
|
||||
cbuf_args_t *args;
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
unsigned int i;
|
||||
|
||||
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
|
||||
thread = GIB_Thread_New ();
|
||||
args = Cbuf_ArgsNew ();
|
||||
|
||||
|
||||
va_start (ap, argc);
|
||||
|
||||
|
||||
Cbuf_ArgsAdd (args, f->name);
|
||||
for (i = 0; i < argc; i++)
|
||||
Cbuf_ArgsAdd (args, va_arg (ap, const char *));
|
||||
|
||||
Cbuf_ArgsAdd (args, va_arg (ap, const char *));
|
||||
|
||||
va_end (ap);
|
||||
|
||||
|
||||
GIB_Function_Execute (thread->cbuf, f, args->argv, args->argc);
|
||||
GIB_Thread_Add (thread);
|
||||
Cbuf_ArgsDelete (args);
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] = "$Id$";
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -46,14 +46,15 @@ gib_tree_t *
|
|||
GIB_Tree_New (gib_tree_flags_t flags)
|
||||
{
|
||||
gib_tree_t *new = calloc (1, sizeof (gib_tree_t));
|
||||
|
||||
new->flags = flags;
|
||||
// All nodes are created for a reason, so start with 1 ref
|
||||
new->refs = 1;
|
||||
new->refs = 1;
|
||||
return new;
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Tree_Free_Recursive (gib_tree_t *tree)
|
||||
GIB_Tree_Free_Recursive (gib_tree_t * tree)
|
||||
{
|
||||
gib_tree_t *n;
|
||||
|
||||
|
@ -65,26 +66,24 @@ GIB_Tree_Free_Recursive (gib_tree_t *tree)
|
|||
// Parent is about to bite the dust, meaning one less reference
|
||||
GIB_Tree_Unref (&tree->children);
|
||||
if (tree->str)
|
||||
free((void *) tree->str);
|
||||
free(tree);
|
||||
free ((void *) tree->str);
|
||||
free (tree);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Tree_Ref (gib_tree_t **tp)
|
||||
GIB_Tree_Ref (gib_tree_t ** tp)
|
||||
{
|
||||
(*tp)->refs++;
|
||||
Sys_DPrintf ("Ref: %p %u\n", *tp, (*tp)->refs);
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Tree_Unref (gib_tree_t **tp)
|
||||
GIB_Tree_Unref (gib_tree_t ** tp)
|
||||
{
|
||||
Sys_DPrintf ("Unref: %p %u\n", *tp, (*tp)->refs-1);
|
||||
Sys_DPrintf ("Unref: %p %u\n", *tp, (*tp)->refs - 1);
|
||||
if (!(--(*tp)->refs)) {
|
||||
GIB_Tree_Free_Recursive (*tp);
|
||||
*tp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((unused))
|
||||
const char rcsid[] = "$Id$";
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -43,14 +43,15 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "QF/gib_vars.h"
|
||||
#include "QF/gib_buffer.h"
|
||||
#include "QF/gib_parse.h"
|
||||
|
||||
hashtab_t *gib_globals = 0;
|
||||
hashtab_t *gib_domains = 0;
|
||||
|
||||
hashtab_t *gib_globals = 0;
|
||||
hashtab_t *gib_domains = 0;
|
||||
|
||||
static gib_var_t *
|
||||
GIB_Var_New (const char *key)
|
||||
{
|
||||
gib_var_t *new = calloc (1, sizeof (gib_var_t));
|
||||
gib_var_t *new = calloc (1, sizeof (gib_var_t));
|
||||
|
||||
new->array = calloc (1, sizeof (dstring_t *));
|
||||
new->key = strdup (key);
|
||||
return new;
|
||||
|
@ -59,25 +60,27 @@ GIB_Var_New (const char *key)
|
|||
static const char *
|
||||
GIB_Var_Get_Key (void *ele, void *ptr)
|
||||
{
|
||||
return ((gib_var_t *)ele)->key;
|
||||
return ((gib_var_t *) ele)->key;
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Var_Free (void *ele, void *ptr)
|
||||
{
|
||||
unsigned int i;
|
||||
gib_var_t *l = (gib_var_t *)ele;
|
||||
gib_var_t *l = (gib_var_t *) ele;
|
||||
|
||||
for (i = 0; i < l->size; i++)
|
||||
if (l->array[i])
|
||||
dstring_delete (l->array[i]);
|
||||
free((void *)l->key);
|
||||
free(l);
|
||||
free ((void *) l->key);
|
||||
free (l);
|
||||
}
|
||||
|
||||
gib_var_t *
|
||||
GIB_Var_Get (hashtab_t *first, hashtab_t *second, const char *key)
|
||||
GIB_Var_Get (hashtab_t * first, hashtab_t * second, const char *key)
|
||||
{
|
||||
gib_var_t *var;
|
||||
gib_var_t *var;
|
||||
|
||||
if (first && (var = Hash_Find (first, key)))
|
||||
return var;
|
||||
else if (second && (var = Hash_Find (second, key)))
|
||||
|
@ -88,18 +91,19 @@ GIB_Var_Get (hashtab_t *first, hashtab_t *second, const char *key)
|
|||
|
||||
/* Modifies key but restores it before returning */
|
||||
gib_var_t *
|
||||
GIB_Var_Get_Complex (hashtab_t **first, hashtab_t **second, char *key, unsigned int *ind, qboolean create)
|
||||
GIB_Var_Get_Complex (hashtab_t ** first, hashtab_t ** second, char *key,
|
||||
unsigned int *ind, qboolean create)
|
||||
{
|
||||
unsigned int i, index;
|
||||
qboolean fix = false;
|
||||
gib_var_t *var;
|
||||
|
||||
i = strlen(key);
|
||||
qboolean fix = false;
|
||||
gib_var_t *var;
|
||||
|
||||
i = strlen (key);
|
||||
index = 0;
|
||||
if (i && key[i-1] == ']')
|
||||
if (i && key[i - 1] == ']')
|
||||
for (i--; i; i--)
|
||||
if (key[i] == '[') {
|
||||
index = atoi (key+i+1);
|
||||
index = atoi (key + i + 1);
|
||||
key[i] = 0;
|
||||
fix = true;
|
||||
break;
|
||||
|
@ -110,16 +114,20 @@ GIB_Var_Get_Complex (hashtab_t **first, hashtab_t **second, char *key, unsigned
|
|||
if (!*first)
|
||||
*first = Hash_NewTable (256, GIB_Var_Get_Key, GIB_Var_Free, 0);
|
||||
Hash_Add (*first, var);
|
||||
} else return 0;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
if (fix)
|
||||
key[i] = '[';
|
||||
if (index >= var->size) {
|
||||
if (create) {
|
||||
var->array = realloc (var->array, (index+1) * sizeof (dstring_t *));
|
||||
memset (var->array+var->size, 0, (index+1 - var->size) * sizeof (dstring_t *));
|
||||
var->size = index+1;
|
||||
} else return 0;
|
||||
var->array =
|
||||
realloc (var->array, (index + 1) * sizeof (dstring_t *));
|
||||
memset (var->array + var->size, 0,
|
||||
(index + 1 - var->size) * sizeof (dstring_t *));
|
||||
var->size = index + 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
if (!var->array[index])
|
||||
var->array[index] = dstring_newstr ();
|
||||
|
@ -128,7 +136,8 @@ GIB_Var_Get_Complex (hashtab_t **first, hashtab_t **second, char *key, unsigned
|
|||
}
|
||||
|
||||
void
|
||||
GIB_Var_Assign (gib_var_t *var, unsigned int index, dstring_t **values, unsigned int numv)
|
||||
GIB_Var_Assign (gib_var_t * var, unsigned int index, dstring_t ** values,
|
||||
unsigned int numv)
|
||||
{
|
||||
unsigned int i, len;
|
||||
|
||||
|
@ -136,7 +145,8 @@ GIB_Var_Assign (gib_var_t *var, unsigned int index, dstring_t **values, unsigned
|
|||
len = numv + index;
|
||||
if (len >= var->size) {
|
||||
var->array = realloc (var->array, len * sizeof (dstring_t *));
|
||||
memset (var->array+var->size, 0, (len-var->size) * sizeof (dstring_t *));
|
||||
memset (var->array + var->size, 0,
|
||||
(len - var->size) * sizeof (dstring_t *));
|
||||
var->size = len;
|
||||
} else if (len < var->size) {
|
||||
for (i = len; i < var->size; i++)
|
||||
|
@ -146,26 +156,27 @@ GIB_Var_Assign (gib_var_t *var, unsigned int index, dstring_t **values, unsigned
|
|||
}
|
||||
var->size = len;
|
||||
for (i = 0; i < numv; i++) {
|
||||
if (var->array[i+index])
|
||||
dstring_clearstr (var->array[i+index]);
|
||||
if (var->array[i + index])
|
||||
dstring_clearstr (var->array[i + index]);
|
||||
else
|
||||
var->array[i+index] = dstring_newstr ();
|
||||
dstring_appendstr (var->array[i+index], values[i]->str);
|
||||
var->array[i + index] = dstring_newstr ();
|
||||
dstring_appendstr (var->array[i + index], values[i]->str);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
GIB_Domain_Get_Key (void *ele, void *ptr)
|
||||
{
|
||||
return ((gib_domain_t *)ele)->name;
|
||||
return ((gib_domain_t *) ele)->name;
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Domain_Free (void *ele, void *ptr)
|
||||
{
|
||||
gib_domain_t *l = (gib_domain_t *)ele;
|
||||
gib_domain_t *l = (gib_domain_t *) ele;
|
||||
|
||||
Hash_DelTable (l->vars);
|
||||
free ((void *)l->name);
|
||||
free ((void *) l->name);
|
||||
free (l);
|
||||
}
|
||||
|
||||
|
@ -173,9 +184,10 @@ hashtab_t *
|
|||
GIB_Domain_Get (const char *name)
|
||||
{
|
||||
gib_domain_t *d = Hash_Find (gib_domains, name);
|
||||
|
||||
if (!d) {
|
||||
d = calloc (1, sizeof (gib_domain_t));
|
||||
d->name = strdup(name);
|
||||
d->name = strdup (name);
|
||||
d->vars = Hash_NewTable (1024, GIB_Var_Get_Key, GIB_Var_Free, 0);
|
||||
Hash_Add (gib_domains, d);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ OP_Div (double op1, double op2)
|
|||
double
|
||||
OP_Exp (double op1, double op2)
|
||||
{
|
||||
return pow(op1, op2);
|
||||
return pow (op1, op2);
|
||||
}
|
||||
|
||||
double
|
||||
|
|
Loading…
Reference in a new issue