### 4.14 Expressions

Expressions are language constructs, that evaluate to a value, that can subsequently be echoed, tested in a conditional statement, assigned to a variable or passed to a function.

#### 4.14.1 Constant Expressions

Literals and numbers are constant expressions. They evaluate to string and numeric types.

#### 4.14.2 Function Calls

A function call is an expression. Its type is the return type of the function.

#### 4.14.3 Concatenation

Concatenation operator is ‘.’ (a dot). For example, if `\$f` is ‘smith’, and `\$client_addr` is ‘10.10.1.1’, then:

```\$f . "-" . \$client_addr ⇒ "smith-10.10.1.1"
```

Any two adjacent literal strings are concatenated, producing a new string, e.g.

```"GNU's" " not " "UNIX" ⇒ "GNU's not UNIX"
```

#### 4.14.4 Arithmetic Operations

The filter script language offers the common arithmetic operators: ‘+’, ‘-’, ‘*’ and ‘/’. In addition, the ‘%’ is a modulo operator, i.e. it computes the remainder of division of its operands.

All of them follow usual precedence rules and work as you would expect them to.

#### 4.14.5 Bitwise shifts

The ‘<<’ represents a bitwise shift left operation, which shifts the binary representation of the operand on its left by the number of bits given by the operand on its right.

Similarly, the ‘>>’ represents a bitwise shift right.

#### 4.14.6 Relational Expressions

Relational expressions are:

ExpressionResult
x `<` yTrue if x is less than y.
x `<=` yTrue if x is less than or equal to y.
x `>` yTrue if x is greater than y.
x `>=` yTrue if x is greater than or equal to y.
x `=` yTrue if x is equal to y.
x `!=` yTrue if x is not equal to y.

Table 4.5: Relational Expressions

The relational expressions apply to string as well as to numbers. When a relational operation applies to strings, case-sensitive comparison is used, e.g.:

```"String" = "string" ⇒ False
"String" < "string" ⇒ True
```

#### 4.14.7 Special Comparisons

In addition to the traditional relational operators, described above, `mailfromd` provides two operators for regular expression matching:

ExpressionResult
x `matches` yTrue if the string x matches the regexp denoted by y.
x `fnmatches` yTrue if the string x matches the globbing pattern denoted by y.

Table 4.6: Regular Expression Matching

The type of the regular expression used by `matches` operator is controlled by `#pragma regex` (see pragma regex). For example:

```\$f ⇒ "gray@gnu.org.ua"
\$f matches '.*@gnu\.org\.ua' ⇒ `true`
\$f matches '.*@GNU\.ORG\.UA' ⇒ `false`
#pragma regex +icase
\$f matches '.*@GNU\.ORG\.UA' ⇒ `true`
```

The `fnmatches` operator compares its left-hand operand with a globbing pattern (see glob(7)) given as its right-hand side operand. For example:

```\$f ⇒ "gray@gnu.org.ua"
\$f fnmatches "*ua" ⇒ `true`
\$f fnmatches "*org" ⇒ `false`
\$f fnmatches "*org*" ⇒ `true`
```

Both operators have a special form, for MX’ pattern matching. The expression:

```  x mx matches y
```

is evaluated as follows: first, the expression x is analyzed and, if it is an email address, its domain part is selected. If it is not, its value is used verbatim. Then the list of ‘MX’s for this domain is looked up. Each of ‘MX’ names is then compared with the regular expression y. If any of the names matches, the expression returns true. Otherwise, its result is false.

Similarly, the expression:

```  x mx fnmatches y
```

returns true only if any of the ‘MX’s for (domain or email) x match the globbing pattern y.

Both `mx matches` and `mx fnmatches` can signal the following exceptions: `e_temp_failure`, `e_failure`.

The value of any parenthesized subexpression occurring within the right-hand side argument to `matches` or `mx matches` can be referenced using the notation ‘\d’, where d is the ordinal number of the subexpression (subexpressions are numbered from left to right, starting at 1). This notation is allowed in the program text as well as within double-quoted strings and here-documents, for example:

```if \$f matches '.*@\(.*\)\.gnu\.org\.ua'
set message "Your host name is \1;"
fi
```

Remember that the grouping symbols are ‘\(’ and ‘\)’ for basic regular expressions, and ‘(’ and ‘)’ for extended regular expressions. Also make sure you properly escape all special characters (backslashes in particular) in double-quoted strings, or use single-quoted strings to avoid having to do so (see singe-vs-double, for a comparison of the two forms).

#### 4.14.8 Boolean Expressions

A boolean expression is a combination of relational or matching expressions using the boolean operators `and`, `or` and `not`, and, eventually, parentheses to control nesting:

ExpressionResult
x `and` yTrue only if both x and y are true.
x `or` yTrue if any of x or y is true.
`not` xTrue if x is false.

table 4.1: Boolean Operators

Binary boolean expressions are computed using shortcut evaluation:

`x and y`

If `x ⇒ false`, the result is `false` and y is not evaluated.

`x or y`

If `x ⇒ true`, the result is `true` and y is not evaluated.

#### 4.14.9 Operator Precedence

Operator precedence is an abstract value associated with each language operator, that determines the order in which operators are executed when they appear together within a single expression. Operators with higher precedence are executed first. For example, ‘*’ has a higher precedence than ‘+’, therefore the expression `a + b * c` is evaluated in the following order: first `b` is multiplied by `c`, then `a` is added to the product.

When operators of equal precedence are used together they are evaluated from left to right (i.e., they are left-associative), except for comparison operators, which are non-associative (these are explicitly marked as such in the table below). This means that you cannot write:

```if 5 <= x <= 10
```

Instead, you should write:

```if 5 <= x and x <= 10
```

The precedences of the `mailfromd` operators where selected so as to match that used in most programming languages.14

The following table lists all operators in order of decreasing precedence:

`(...)`

Grouping

`\$ %`

`Sendmail` macros and `mailfromd` variables

`* /`

Multiplication, division

`+ -`

`<< >>`

Bitwise shift left and right

`< <= >= >`

Relational operators (non-associative)

`= != matches fnmatches`

Equality and special comparison (non-associative)

`&`

Logical (bitwise) AND

`^`

Logical (bitwise) XOR

`|`

Logical (bitwise) OR

`not`

Boolean negation

`and`

Logical ‘and’.

`or`

Logical ‘or

`.`

String concatenation

#### 4.14.10 Type Casting

When two operands on each side of a binary expression have different type, `mailfromd` evaluator coerces them to a common type. This is known as implicit type casting. The rules for implicit type casting are:

1. Both arguments to an arithmetical operation are cast to numeric type.
2. Both arguments to the concatenation operation are cast to string.
3. Both arguments to ‘match’ or ‘fnmatch’ function are cast to string.
4. The argument of the unary negation (arithmetical or boolean) is cast to numeric.
5. Otherwise the right-hand side argument is cast to the type of the left-hand side argument.

The construct for explicit type cast is:

```type(expr)
```

where type is the name of the type to coerce expr to. For example:

```string(2 + 4*8) ⇒ "34"
```

### (14)

The only exception is ‘not’, whose precedence in MFL is much lower than usual (in most programming languages it has the same precedence as unary ‘-’). This allows to write conditional expressions in more understandable manner. Consider the following condition:

```if not x < 2 and y = 3
```

It is understood as “if `x` is not less than 2 and `y` equals 3”, whereas with the usual precedence for ‘not’ it would have meant “if negated `x` is less than 2 and `y` equals 3”.