Control structures

The extension function language provides the usual statements to control program execution.

  • If Then Else
  • While Do and Repeat Until
  • Numeric For
  • Break
  • Goto

If Then Else

If statements select blocks of statements to execute based on one or more conditions. There are three forms:

If then Form

if expression then
     statements to execute if expression is not false or nil
end
<!--NeedCopy-->

If then else Form

if expression then
     statements to execute if expression is not false or nil
else
     statements to execute if expression is false or nil
end
<!--NeedCopy-->

If then elseif else Form

if expression1 then
     statements to execute if expression1 is not false or nil
     elseif expression2 then
          statements to execute if expression2 is not false or nil
. . .
else
     statements to execute if all expressions are false or nil
end
<!--NeedCopy-->

Example:

if headers[name] then

     local next_value_index = #(headers[name]) + 1
     headers[name][next_value_index] = value

else

     headers[name] = {name .. ":" .. value}

end
<!--NeedCopy-->

Note:

  • The expression is not enclosed in parentheses as is the case in C and Java.
  • There is no equivalent to the C/Java switch statement. You have to use a series of if elseif statements to do the equivalent.

While Do and Repeat Until

The while and repeat statements provide loops controlled by an expression.

while expression do
     statements to execute while expression is not false or nil
end

repeat

     statements to execute until expression is not false or nil

until expression
<!--NeedCopy-->

Example for while:

local a = {1, 2, 3, 4}
local sum, i = 0, 1 -- multiple assignment initializing sum and i
while i <= #a do -- check if at the end of the array
     sum = sum + a[i] -- add array element with index i to sum
     i = i + 1 -- move to the next element
end
<!--NeedCopy-->

Example for repeat:

sum, i = 0, 1 -- multiple assignment initializing sum and i
repeat
     sum = sum + a[i] -- add array element with index i to sum
     i = i + 1 -- move to the next element
until i > #a -- check if past the end of the array
<!--NeedCopy-->

Of course it is possible to write a loop that does not terminate, for example, if you omit the i = i + 1 statement in either of these examples. When such a function is executed, Citrix ADC will detect that the function did not complete in a reasonable time and will kill it with a runtime error:

Cpu limit reached. Terminating extension execution in [[string "function extension function..."]]: line line-number.

will be reported in /var/log/ns.log.

Numeric For

There are two types of for loops. The first is the numeric for, which is similar to the usual use of the for statement in C and Java. The numeric for statement initializes a variable, tests if the variable has passed a final value, and if not executes a block of statements, increments the variable, and repeats. The syntax for the numerical for loop is:

for variable = initial, final, increment do

     statements in the loop body

end

where initial, final, and increment are all expressions that yield (or can be converted to) numbers. variable is considered to be local to the for loop statement block; it cannot be used outside of the loop. increment can be omitted; the default is 1. The expressions are evaluated once at the beginning of the loop. The terminating condition is variable > final if the increment is positive and variable < final if the increment is negative. The loop terminates immediately if the increment is 0.

Example (equivalent to the while and repeat loops in the preceding section):

sum = 0
for i = 1, #a do -- increment defaults to 1
     sum = sum + a[i]
end
<!--NeedCopy-->

The second type of for loop is the generic for, which can be used for more flexible types of loops. It involves the use of functions, so will be discussed later after functions have been introduced.

Break

The break statement is used inside a while, repeat, or for loop. It will terminate the loop and resume execution at the first statement after the loop. Example (also equivalent to the preceding while, repeat, and for loops):

sum, i = 0, 1
while true do
     if i > #a then
          break
     end
     sum = sum + a[i]
     i = i + 1
end
<!--NeedCopy-->

Goto

The goto statement can be used to jump forward or backward to a label. The label is an identifier, and its syntax is ::label::. The goto statement is goto label. Example (once again equivalent to the preceding loops):

sum, i = 0, 1
::start_loop::
     if i > #a then
          goto end_loop -- forward jump
     end
     sum = sum + a[i]
     i = i + 1
     goto start_loop -- backwards jump
::end_loop::
. . .
<!--NeedCopy-->

There has been a long running controversy over using gotos in programming. In general, you should try to use the other control structures to make your functions more readable and reliable. But occasional judicious use of gotos may lead to better programs. In particular, gotos may be useful in handling errors.

Control structures