Directives are special commands to the compiler. Currently, only $assert and $print directives are supported. Directives are only allowed at non-global scope.
Syntax:
$assert(condition-expression [, message [, fatal-expression]]);
Assert directive is evaluated at run-time. First, condition-expression is evaluated. If it evaluates to non-zero value, nothing happens. But if it evaluates to a zero value, message is displayed to the user and structure binding is terminated. If message is omitted, standard "Assertion Failed" message is displayed. message, if present, must be a string expression. fatal-expression, if present, must be a constant expression. If it evaluates to a non-zero value, the assertion is fatal (this is a default behavior), that is, fired assertion terminates structure binding. If it evaluates to zero, assertion is only informational.
Assertions are good at verifying whether the data structure is being bound to correct data.
Note: Hex Editor Neo currently does not support non-fatal assertions. They behave exactly like fatal assertions.
struct A
{
int a;
$assert(5 < a && a < 10,"a must be between 5 and 10");
};
If condition-expression is a constant expression, then the assert directive is either completely removed from the compiled file (if the expression is non-zero), or compilation fails (if the expression is zero). You can combine it with conditional compilation to stop compiling a source file if some condition is not met.
#if !defined(MY_CONSTANT)
struct A
{
$assert(0);
};
#endif
Syntax:
$print(var-name-string-expression,var-value-expression);
The first expression must be a constant string expression and serves as a pseudo-field name. This name is displayed in the Structure Viewer Tool Window. It also is added as a real field into the current scope and may be later referenced in expressions. The second expression is a field's value. It may be either a constant expression or a non-const expression, that will be evaluated at run time.
struct A
{
int a;
int b;
$print("double_a",a * 2);
$print("a/b",double(a)/b);
};
Both $print directives in the example above introduce new fields into the current scope (of struct A), but only the first one may be referenced in expressions, because the second one has incorrect name. So, it's OK to use any name for the first argument, but only syntactically correct ones may be referenced in expressions.
Syntax:
$break_array(const-conditional-expression);
When used in a user-defined type, unconditionally breaks an enclosed array.
The parameter, which must be a constant value, specifies whether the current element should be included into an array (const-conditional-expression = true), or not (const-conditional-expression = false)
May be used either in conjunction with infinite array or with an ordinary array. If used not inside an array, the directive is ignored.
struct StringCharacter
{
char c;
if (c==0)
$break_array(true);
};
struct NullTerminatedString
{
StringCharacter chars[*];
};
Syntax:
$bind(type-string-expr,var-string-expr,addr-expr);
All directive expressions are evaluated at run time. First two are automatically converted to strings, while the third is expected to be of integer type.
This directive instructs parser to bind another structure to a given address. Binding is delayed until the current structure binding is successfully finished.
You must reference the full type name, for example "struct MyStruct", not the "MyStruct", and the referenced type must have been declared as public.
public struct B
{
// …
};
public struct A
{
int Offset;
if (Offset != 0)
$bind("struct B","pB",Offset);
};