1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-12 17:14:46 +02:00

Code cleanup in conf_preprocessor.c (Conditional Config)

This commit is contained in:
Bram Matthys
2026-03-22 18:59:13 +01:00
parent 17a8182efc
commit 2346aa3977
+74 -153
View File
@@ -15,6 +15,23 @@ NameValuePrioList *config_defines = NULL; /**< List of @defines, only valid duri
/* Forward declarations */
NameValuePrioList *find_config_define(const char *name);
typedef struct {
const char *keyword;
ConfigIfCondition condition;
} IfFunction;
/** Table of function-style @if conditions.
* NOTE: If two keywords share a prefix, put the longer one first,
* since we use strncmp for matching.
*/
static IfFunction if_functions[] = {
{ "module-loaded", IF_MODULE_LOADED },
{ "module-exists", IF_MODULE_EXISTS },
{ "minimum-version", IF_MINIMUM_VERSION },
{ "file-exists", IF_FILE_EXISTS },
{ "defined", IF_DEFINED },
};
static inline int ValidVarCharacter(char x)
{
if (isupper(x) || isdigit(x) || strchr("_", x))
@@ -22,10 +39,56 @@ static inline int ValidVarCharacter(char x)
return 0;
}
/** Parse a function-style @if condition: funcname("argument")
* @param p Position right after the keyword
* @param funcname Function name (for error messages only)
* @param condition The ConfigIfCondition enum value to set
* @param negative Whether the condition was negated with !
* @param statement Full statement string (for error messages)
* @param filename Config filename (for error messages)
* @param linenumber Line number (for error messages)
* @param cc_out Result stored here on success
* @returns PREPROCESSOR_IF on success, PREPROCESSOR_ERROR on failure
*/
static PreprocessorItem parse_if_function(char *p, const char *funcname, ConfigIfCondition condition,
int negative, char *statement, const char *filename,
int linenumber, ConditionalConfig **cc_out)
{
char *name;
ConditionalConfig *cc;
skip_whitespace(&p);
if (*p != '(')
{
config_error("%s:%i: expected '(' for %s(...",
filename, linenumber, funcname);
return PREPROCESSOR_ERROR;
}
p++;
skip_whitespace(&p);
if (*p == '"')
p++;
name = p;
read_until(&p, ")\"");
if (!*p)
{
config_error("%s:%i: invalid if statement (termination error): %s",
filename, linenumber, statement);
return PREPROCESSOR_ERROR;
}
*p = '\0';
cc = safe_alloc(sizeof(ConditionalConfig));
cc->condition = condition;
cc->negative = negative;
safe_strdup(cc->name, name);
*cc_out = cc;
return PREPROCESSOR_IF;
}
PreprocessorItem evaluate_preprocessor_if(char *statement, const char *filename, int linenumber, ConditionalConfig **cc_out)
{
char *p=statement, *name;
int negative = 0;
char *p=statement;
int i, negative = 0;
ConditionalConfig *cc;
/* Currently we support:
@@ -53,159 +116,17 @@ PreprocessorItem evaluate_preprocessor_if(char *statement, const char *filename,
skip_whitespace(&p);
}
/* Now comes the keyword or a variable name */
if (!strncmp(p, "module-loaded", 13))
/* Check function-style conditions from the table */
for (i = 0; i < ARRAY_SIZEOF(if_functions); i++)
{
p += 13;
skip_whitespace(&p);
if (*p != '(')
{
config_error("%s:%i: expected '(' for module-loaded(...",
filename, linenumber);
return PREPROCESSOR_ERROR;
}
p++;
skip_whitespace(&p);
if (*p == '"')
p++;
name = p;
read_until(&p, ")\"");
if (!*p)
{
config_error("%s:%i: invalid if statement (termination error): %s",
filename, linenumber, statement);
return PREPROCESSOR_ERROR;
}
*p = '\0';
cc = safe_alloc(sizeof(ConditionalConfig));
cc->condition = IF_MODULE_LOADED;
cc->negative = negative;
safe_strdup(cc->name, name);
*cc_out = cc;
return PREPROCESSOR_IF;
} else
if (!strncmp(p, "module-exists", 13))
int len = strlen(if_functions[i].keyword);
if (!strncmp(p, if_functions[i].keyword, len))
return parse_if_function(p + len, if_functions[i].keyword, if_functions[i].condition, negative, statement, filename, linenumber, cc_out);
}
/* Otherwise it should be a $VARIABLE comparison */
{
p += 13;
skip_whitespace(&p);
if (*p != '(')
{
config_error("%s:%i: expected '(' for module-exists(...",
filename, linenumber);
return PREPROCESSOR_ERROR;
}
p++;
skip_whitespace(&p);
if (*p == '"')
p++;
name = p;
read_until(&p, ")\"");
if (!*p)
{
config_error("%s:%i: invalid if statement (termination error): %s",
filename, linenumber, statement);
return PREPROCESSOR_ERROR;
}
*p = '\0';
cc = safe_alloc(sizeof(ConditionalConfig));
cc->condition = IF_MODULE_EXISTS;
cc->negative = negative;
safe_strdup(cc->name, name);
*cc_out = cc;
return PREPROCESSOR_IF;
} else
if (!strncmp(p, "minimum-version", 15))
{
p += 15;
skip_whitespace(&p);
if (*p != '(')
{
config_error("%s:%i: expected '(' for minimum-version(...",
filename, linenumber);
return PREPROCESSOR_ERROR;
}
p++;
skip_whitespace(&p);
if (*p == '"')
p++;
name = p;
read_until(&p, ")\"");
if (!*p)
{
config_error("%s:%i: invalid if statement (termination error): %s",
filename, linenumber, statement);
return PREPROCESSOR_ERROR;
}
*p = '\0';
cc = safe_alloc(sizeof(ConditionalConfig));
cc->condition = IF_MINIMUM_VERSION;
cc->negative = negative;
safe_strdup(cc->name, name);
*cc_out = cc;
return PREPROCESSOR_IF;
} else
if (!strncmp(p, "file-exists", 11))
{
p += 11;
skip_whitespace(&p);
if (*p != '(')
{
config_error("%s:%i: expected '(' for file-exists(...",
filename, linenumber);
return PREPROCESSOR_ERROR;
}
p++;
skip_whitespace(&p);
if (*p == '"')
p++;
name = p;
read_until(&p, ")\"");
if (!*p)
{
config_error("%s:%i: invalid if statement (termination error): %s",
filename, linenumber, statement);
return PREPROCESSOR_ERROR;
}
*p = '\0';
cc = safe_alloc(sizeof(ConditionalConfig));
cc->condition = IF_FILE_EXISTS;
cc->negative = negative;
safe_strdup(cc->name, name);
*cc_out = cc;
return PREPROCESSOR_IF;
} else
if (!strncmp(p, "defined", 7))
{
p += 7;
skip_whitespace(&p);
if (*p != '(')
{
config_error("%s:%i: expected '(' for defined(...",
filename, linenumber);
return PREPROCESSOR_ERROR;
}
p++;
skip_whitespace(&p);
if (*p == '"')
p++;
name = p;
read_until(&p, ")\"");
if (!*p)
{
config_error("%s:%i: invalid if statement (termination error): %s",
filename, linenumber, statement);
return PREPROCESSOR_ERROR;
}
*p = '\0';
cc = safe_alloc(sizeof(ConditionalConfig));
cc->condition = IF_DEFINED;
cc->negative = negative;
safe_strdup(cc->name, name);
*cc_out = cc;
return PREPROCESSOR_IF;
} else
{
char *name_terminate, *name2;
char *name, *name_terminate, *name2;
// Should be one of:
// $XYZ == "something"
// $XYZ != "something"