📄 l_precomp.c
字号:
case P_LOGIC_AND:
case P_LOGIC_OR:
case P_LOGIC_GEQ:
case P_LOGIC_LEQ:
case P_LOGIC_EQ:
case P_LOGIC_UNEQ:
case P_LOGIC_GREATER:
case P_LOGIC_LESS:
case P_RSHIFT:
case P_LSHIFT:
case P_BIN_AND:
case P_BIN_OR:
case P_BIN_XOR:
case P_COLON:
case P_QUESTIONMARK:
{
if (!lastwasvalue)
{
SourceError(source, "operator %s after operator in #if/#elif", t->string);
error = 1;
break;
} //end if
break;
} //end case
default:
{
SourceError(source, "invalid operator %s in #if/#elif", t->string);
error = 1;
break;
} //end default
} //end switch
if (!error && !negativevalue)
{
//o = (operator_t *) GetClearedMemory(sizeof(operator_t));
AllocOperator(o);
o->operator = t->subtype;
o->priority = PC_OperatorPriority(t->subtype);
o->parentheses = parentheses;
o->next = NULL;
o->prev = lastoperator;
if (lastoperator) lastoperator->next = o;
else firstoperator = o;
lastoperator = o;
lastwasvalue = 0;
} //end if
break;
} //end case
default:
{
SourceError(source, "unknown %s in #if/#elif", t->string);
error = 1;
break;
} //end default
} //end switch
if (error) break;
} //end for
if (!error)
{
if (!lastwasvalue)
{
SourceError(source, "trailing operator in #if/#elif");
error = 1;
} //end if
else if (parentheses)
{
SourceError(source, "too many ( in #if/#elif");
error = 1;
} //end else if
} //end if
//
gotquestmarkvalue = qfalse;
questmarkintvalue = 0;
questmarkfloatvalue = 0;
//while there are operators
while(!error && firstoperator)
{
v = firstvalue;
for (o = firstoperator; o->next; o = o->next)
{
//if the current operator is nested deeper in parentheses
//than the next operator
if (o->parentheses > o->next->parentheses) break;
//if the current and next operator are nested equally deep in parentheses
if (o->parentheses == o->next->parentheses)
{
//if the priority of the current operator is equal or higher
//than the priority of the next operator
if (o->priority >= o->next->priority) break;
} //end if
//if the arity of the operator isn't equal to 1
if (o->operator != P_LOGIC_NOT
&& o->operator != P_BIN_NOT) v = v->next;
//if there's no value or no next value
if (!v)
{
SourceError(source, "mising values in #if/#elif");
error = 1;
break;
} //end if
} //end for
if (error) break;
v1 = v;
v2 = v->next;
#ifdef DEBUG_EVAL
if (integer)
{
Log_Write("operator %s, value1 = %d", PunctuationFromNum(source->scriptstack, o->operator), v1->intvalue);
if (v2) Log_Write("value2 = %d", v2->intvalue);
} //end if
else
{
Log_Write("operator %s, value1 = %f", PunctuationFromNum(source->scriptstack, o->operator), v1->floatvalue);
if (v2) Log_Write("value2 = %f", v2->floatvalue);
} //end else
#endif //DEBUG_EVAL
switch(o->operator)
{
case P_LOGIC_NOT: v1->intvalue = !v1->intvalue;
v1->floatvalue = !v1->floatvalue; break;
case P_BIN_NOT: v1->intvalue = ~v1->intvalue;
break;
case P_MUL: v1->intvalue *= v2->intvalue;
v1->floatvalue *= v2->floatvalue; break;
case P_DIV: if (!v2->intvalue || !v2->floatvalue)
{
SourceError(source, "divide by zero in #if/#elif\n");
error = 1;
break;
}
v1->intvalue /= v2->intvalue;
v1->floatvalue /= v2->floatvalue; break;
case P_MOD: if (!v2->intvalue)
{
SourceError(source, "divide by zero in #if/#elif\n");
error = 1;
break;
}
v1->intvalue %= v2->intvalue; break;
case P_ADD: v1->intvalue += v2->intvalue;
v1->floatvalue += v2->floatvalue; break;
case P_SUB: v1->intvalue -= v2->intvalue;
v1->floatvalue -= v2->floatvalue; break;
case P_LOGIC_AND: v1->intvalue = v1->intvalue && v2->intvalue;
v1->floatvalue = v1->floatvalue && v2->floatvalue; break;
case P_LOGIC_OR: v1->intvalue = v1->intvalue || v2->intvalue;
v1->floatvalue = v1->floatvalue || v2->floatvalue; break;
case P_LOGIC_GEQ: v1->intvalue = v1->intvalue >= v2->intvalue;
v1->floatvalue = v1->floatvalue >= v2->floatvalue; break;
case P_LOGIC_LEQ: v1->intvalue = v1->intvalue <= v2->intvalue;
v1->floatvalue = v1->floatvalue <= v2->floatvalue; break;
case P_LOGIC_EQ: v1->intvalue = v1->intvalue == v2->intvalue;
v1->floatvalue = v1->floatvalue == v2->floatvalue; break;
case P_LOGIC_UNEQ: v1->intvalue = v1->intvalue != v2->intvalue;
v1->floatvalue = v1->floatvalue != v2->floatvalue; break;
case P_LOGIC_GREATER: v1->intvalue = v1->intvalue > v2->intvalue;
v1->floatvalue = v1->floatvalue > v2->floatvalue; break;
case P_LOGIC_LESS: v1->intvalue = v1->intvalue < v2->intvalue;
v1->floatvalue = v1->floatvalue < v2->floatvalue; break;
case P_RSHIFT: v1->intvalue >>= v2->intvalue;
break;
case P_LSHIFT: v1->intvalue <<= v2->intvalue;
break;
case P_BIN_AND: v1->intvalue &= v2->intvalue;
break;
case P_BIN_OR: v1->intvalue |= v2->intvalue;
break;
case P_BIN_XOR: v1->intvalue ^= v2->intvalue;
break;
case P_COLON:
{
if (!gotquestmarkvalue)
{
SourceError(source, ": without ? in #if/#elif");
error = 1;
break;
} //end if
if (integer)
{
if (!questmarkintvalue) v1->intvalue = v2->intvalue;
} //end if
else
{
if (!questmarkfloatvalue) v1->floatvalue = v2->floatvalue;
} //end else
gotquestmarkvalue = qfalse;
break;
} //end case
case P_QUESTIONMARK:
{
if (gotquestmarkvalue)
{
SourceError(source, "? after ? in #if/#elif");
error = 1;
break;
} //end if
questmarkintvalue = v1->intvalue;
questmarkfloatvalue = v1->floatvalue;
gotquestmarkvalue = qtrue;
break;
} //end if
} //end switch
#ifdef DEBUG_EVAL
if (integer) Log_Write("result value = %d", v1->intvalue);
else Log_Write("result value = %f", v1->floatvalue);
#endif //DEBUG_EVAL
if (error) break;
lastoperatortype = o->operator;
//if not an operator with arity 1
if (o->operator != P_LOGIC_NOT
&& o->operator != P_BIN_NOT)
{
//remove the second value if not question mark operator
if (o->operator != P_QUESTIONMARK) v = v->next;
//
if (v->prev) v->prev->next = v->next;
else firstvalue = v->next;
if (v->next) v->next->prev = v->prev;
else lastvalue = v->prev;
//FreeMemory(v);
FreeValue(v);
} //end if
//remove the operator
if (o->prev) o->prev->next = o->next;
else firstoperator = o->next;
if (o->next) o->next->prev = o->prev;
else lastoperator = o->prev;
//FreeMemory(o);
FreeOperator(o);
} //end while
if (firstvalue)
{
if (intvalue) *intvalue = firstvalue->intvalue;
if (floatvalue) *floatvalue = firstvalue->floatvalue;
} //end if
for (o = firstoperator; o; o = lastoperator)
{
lastoperator = o->next;
//FreeMemory(o);
FreeOperator(o);
} //end for
for (v = firstvalue; v; v = lastvalue)
{
lastvalue = v->next;
//FreeMemory(v);
FreeValue(v);
} //end for
if (!error) return qtrue;
if (intvalue) *intvalue = 0;
if (floatvalue) *floatvalue = 0;
return qfalse;
} //end of the function PC_EvaluateTokens
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_Evaluate(source_t *source, signed long int *intvalue,
double *floatvalue, int integer)
{
token_t token, *firsttoken, *lasttoken;
token_t *t, *nexttoken;
define_t *define;
int defined = qfalse;
if (intvalue) *intvalue = 0;
if (floatvalue) *floatvalue = 0;
//
if (!PC_ReadLine(source, &token))
{
SourceError(source, "no value after #if/#elif");
return qfalse;
} //end if
firsttoken = NULL;
lasttoken = NULL;
do
{
//if the token is a name
if (token.type == TT_NAME)
{
if (defined)
{
defined = qfalse;
t = PC_CopyToken(&token);
t->next = NULL;
if (lasttoken) lasttoken->next = t;
else firsttoken = t;
lasttoken = t;
} //end if
else if (!strcmp(token.string, "defined"))
{
defined = qtrue;
t = PC_CopyToken(&token);
t->next = NULL;
if (lasttoken) lasttoken->next = t;
else firsttoken = t;
lasttoken = t;
} //end if
else
{
//then it must be a define
#if DEFINEHASHING
define = PC_FindHashedDefine(source->definehash, token.string);
#else
define = PC_FindDefine(source->defines, token.string);
#endif //DEFINEHASHING
if (!define)
{
SourceError(source, "can't evaluate %s, not defined", token.string);
return qfalse;
} //end if
if (!PC_ExpandDefineIntoSource(source, &token, define)) return qfalse;
} //end else
} //end if
//if the token is a number or a punctuation
else if (token.type == TT_NUMBER || token.type == TT_PUNCTUATION)
{
t = PC_CopyToken(&token);
t->next = NULL;
if (lasttoken) lasttoken->next = t;
else firsttoken = t;
lasttoken = t;
} //end else
else //can't evaluate the token
{
SourceError(source, "can't evaluate %s", token.string);
return qfalse;
} //end else
} while(PC_ReadLine(source, &token));
//
if (!PC_EvaluateTokens(source, firsttoken, intvalue, floatvalue, integer)) return qfalse;
//
#ifdef DEBUG_EVAL
Log_Write("eval:");
#endif //DEBUG_EVAL
for (t = firsttoken; t; t = nexttoken)
{
#ifdef DEBUG_EVAL
Log_Write(" %s", t->string);
#endif //DEBUG_EVAL
nexttoken = t->next;
PC_FreeToken(t);
} //end for
#ifdef DEBUG_EVAL
if (integer) Log_Write("eval result: %d", *intvalue);
else Log_Write("eval result: %f", *floatvalue);
#endif //DEBUG_EVAL
//
return qtrue;
} //end of the function PC_Evaluate
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_DollarEvaluate(source_t *source, signed long int *intvalue,
double *floatvalue, int integer)
{
int indent, defined = qfalse;
token_t token, *firsttoken, *lasttoken;
token_t *t, *nexttoken;
define_t *define;
if (intvalue) *intvalue = 0;
if (floatvalue) *floatvalue = 0;
//
if (!PC_ReadSourceToken(source, &token))
{
SourceError(source, "no leading ( after $evalint/$evalfloat");
return qfalse;
} //end if
if (!PC_ReadSourceToken(source, &token))
{
SourceError(source, "nothing to evaluate");
return qfalse;
} //end if
indent = 1;
firsttoken = NULL;
lasttoken = NULL;
do
{
//if the token is a name
if (token.type == TT_NAME)
{
if (defined)
{
defined = qfalse;
t = PC_CopyToken(&token);
t->next = NULL;
if (lasttoken) lasttoken->next = t;
else firsttoken = t;
lasttoken = t;
} //end if
else if (!strcmp(token.string, "defined"))
{
defined = qtrue;
t = PC_CopyToken(&token);
t->next = NULL;
if (lasttoken) lasttoken->next = t;
else firsttoken = t;
lasttoken = t;
} //end if
else
{
//then it must be a define
#if DEFINEHASHING
define = PC_FindHashedDefine(source->definehash, token.string);
#else
define = PC_FindDefine(source->defines, token.string);
#endif //DEFINEHASHING
if (!define)
{
SourceError(source, "can't evaluate %s, not defined", token.string);
return qfalse;
} //end if
if (!PC_ExpandDefineIntoSource(source, &token, define)) return qfalse;
} //end else
} //end if
//if the token is a number or a punctuation
else if (token.type == TT_NUMBER || token.type == TT_PUNCTUATION)
{
if (*token.string == '(') indent++;
else if (*token.string == ')') indent--;
if (indent <= 0) break;
t = PC_CopyToken(&token);
t->next = NULL;
if (lasttoken) lasttoken->next = t;
else firsttoken = t;
lasttoken = t;
} //end else
else //can't evaluate the token
{
SourceError(source, "can't evaluate %s", token.string);
return qfalse;
} //end else
} while(PC_ReadSourceToken(source, &token));
//
if (!PC_EvaluateTokens(source, firsttoken, intvalue, floatvalue, integer)) return qfalse;
//
#ifdef DEBUG_EVAL
Log_Write("$eval:");
#endif //DEBUG_EVAL
for (t = firsttoken; t; t = nexttoken)
{
#ifdef DEBUG_EVAL
Log_Write(" %s", t->string);
#endif //DEBUG_EVAL
nexttoken = t->next;
PC_FreeToken(t);
} //end for
#ifdef DEBUG_EVAL
if (integer) Log_Write("$eval result: %d", *intvalue);
else Log_Write("$eval result: %f", *floatvalue);
#endif //DEBUG_EVAL
//
return qtrue;
} //end of the function PC_DollarEvaluate
//============================================================================
//
// Parameter: -
// Returns: -
// Chan
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -