The SYNTAX condition can be raised for a great many reasons. As just one example, it may be raised because you passed an 'option' that isn't one of the allowable options to the TIME() built-in function. Or it may be raised because you passed a 'position' to the CHARIN() built-in function that wasn't actually a numeric value. Or it may be raised because you forgot the closing quote character of a literal string. There are literally over 100 other reasons why a SYNTAX condition may be raised.

ANSI error/sub-error numbers

Whenever a SYNTAX condition is raised, an error number, and possibly a sub-error number as well, is associated with that instance of the condition being raised. Each one of the numerous reasons for SYNTAX being raised will produce a different combination of error/sub-error numbers. So, by checking the error/sub-error numbers, you can deduce exactly what went wrong in your script (ie, why the SYNTAX condition was raised).

As mentioned previously, the default handling for the SYNTAX condition is to display some information to the command prompt window, and then end the script right there. The information displayed includes the line number and the actual line in the script where the condition was raised, the error number and sub-error numbers, the name of the script, and finally a descriptive message that tells why the condition was raised.

The error/sub-error numbers are displayed after the word "ERROR". They are separated by a dot. For example, 40.28 will be displayed for a SYNTAX condition raised because you passed an unrecognized 'option' to TIME(). 40 is the error number, and 28 is the sub-error number.

For example, consider that you have the following REXX script named "myscript.rex" which passes TIME() some option that isn't one of the recognized ones:

newtime = TIME('b')
EXIT
Because we aren't trapping SYNTAX condition, REXX uses its default handling. So, the script will be aborted at the first line, with the following text displayed to the command prompt window:
     1 +++ newtime = TIME('b')
ERROR 40.28 in "myscript.rex" at line 1
TIME argument 1, option must start with one of "CEHJLMNORS"; found "B"
But if you trap the SYNTAX condition, then such default handling doesn't happen (usually. The exception is with "fatal" SYNTAX errors discussed below). Instead, REXX calls your own SYNTAX handler. Your handler can use the CONDITION() built-in function's 'E' option to fetch the error and sub-error numbers associated with a given instance of that condition. CONDITION('E') will return the two numbers separated by a dot. For example, 40.28 will be returned for the above SYNTAX condition.

The error number can be thought of as a "general category number". And the sub-error number is a specific error within that category.

The ANSI REXX specification defines about 50 categories of errors. For example, all errors that have to do with bad arguments passed to some Function have an error (ie, category) number of 40. All errors that have to do with using a non-numeric value in a math expression have an error (category) number of 41. There are categories having to do with mistakes in your PARSE templates (ie, search strings and offsets), mistakes in specifying the expressions used in conditional instructions, mistakes in the names you choose for variables, etc. All of these raise the SYNTAX condition.

Each category may have one or more sub-errors associated with it. For example, the category of 40 has many sub-errors associated with it, since there are many different mistakes you can make in specifying arguments to functions. We saw above that passing an unrecognized 'option' to TIME() results in a category of 40 and a sub-error of 28. If you pass a 'position' to the CHARIN() built-in function that isn't actually a numeric value, then this also results in a SYNTAX condition with a error (category) number of 40, but a sub-error of 14.

Sometimes, REXX will not have enough information about the cause of the SYNTAX condition being raised in order to provide a sub-error number. In this case, only the category number is reported. Such a case may happen when you're calling a Function in a DLL/EXE, and it doesn't provide enough information about what went wrong. In this case, the Function may simply report a category number of 40 to indicate that something is wrong with your call to the Function. But without a sub-error, you are given no more information than that.

You can use the "PARSE SOURCE" and "SAY" REXX instructions, the SIGL variable, and the CONDITION() built-in function to duplicate the default handling for SYNTAX (or HALT) condition, as so:

/* Handler for SYNTAX that duplicates the default handling */
SYNTAX:
   linenum = SIGL
   PARSE SOURCE . . scriptname
   SAY "    " SIGL "+++" SOURCELINE(linenum)
   SAY 'ERROR' CONDITION('E') 'in "'||scriptname||'" at line' linenum
   SAY CONDITION('D')
   RETURN
But Reginald's CONDITION() function offers an extra, more useful option. CONDITION('M') will open a message box with all of the above information plus a "Help" button to bring up an online help page for the error. This is analogous to what Reginald's MSGBOX option does for untrapped SYNTAX and HALT conditions. So, to display an error message to the user, you need do no more than:
/* Handler for SYNTAX that duplicates Reginald's MSGBOX OPTION */
SYNTAX:
   CALL CONDITION('M')
   RETURN
The following chart lists the ANSI error and sub-error numbers associated with the SYNTAX condition, and what is the meaning of each combination of error/sub-error number.

2 Category: An error during script cleanup
  2.1 An error during script cleanup
3 Category: An error during script initialization
  3.1 An error during script initialization
5 Category: Memory allocation error
  5.1 Memory allocation error
6 Category: There's an unmatched /* in a comment, or unmatched quote in a literal string
  6.1 There's an unmatched /* in a comment
  6.2 There's an unmatched single quote in a literal string
  6.3 There's an unmatched double quote in a literal string
7 Category: There's an problem in a SELECT group
  7.1 Missing the first WHEN in a SELECT group
  7.2 There is some other keyword where a WHEN, OTHERWISE, or END is expected
  7.3 None of the WHEN statements are true, and you failed to supply an OTHERWISE
8 Category: There's a THEN or ELSE keyword in an unexpected place
  8.1 There's a THEN keyword without an IF or WHEN before it
  8.2 There's an ELSE keyword without an IF/THEN before it
9 Category: There's a WHEN or OTHERWISE keyword in an unexpected place
  9.1 There's a WHEN keyword without a SELECT before it
  9.2 There's an OTHERWISE keyword without a SELECT before it
10 Category: There's an END keyword in an unexpected place, or a missing END where one is expected
  10.1 There's an END keyword without a DO or SELECT before it
  10.2 There's a variable name after END which doesn't match any variable being used with a DO instruction
  10.3 There's a variable name after END which goes with a DO instruction that uses no variable
  10.4 An END, belonging to a SELECT group, has some variable name after it
  10.5 There's an END keyword immediately following a THEN keyword, without at least a NOP inbetween
  10.6 There's an END keyword immediately following an ELSE keyword, without at least a NOP inbetween
11 Category: There's a problem with the file system. There may be a sub-error number too. If so, this is an operating system specific number which may give a more informative message when passed to UNIXERROR().
13 Category: There's an invalid character in your REXX script
  13.1 There's an invalid character in your REXX script
14 Category: There's an incomplete DO, SELECT, or IF/THEN instruction
  14.1 There's a DO keyword without a matching END keyword after it
  14.2 There's a SELECT keyword without a matching END keyword after it
  14.3 There's a THEN keyword without another REXX instruction (or NOP) after it
  14.4 There's an ELSE keyword without another REXX instruction (or NOP) after it
15 Category: There's a mistake with a string in hexadecimal or binary
  15.1 There's a space in a hexadecimal string where no space is allowed
  15.2 There's a space in a binary string where no space is allowed
  15.3 You specified something other than the allowable characters of a to f, A to F, 0 to 9, or a space in a hexadecimal string
  15.4 You specified something other than the allowable characters of 0, 1, or a space in a binary string
16 Category: You referenced a label that is not found within your script
  16.1 You tried to SIGNAL to a label name that can't be found
  16.3 You tried to SIGNAL to a label inside of a DO loop, SELECT group, or IF/THEN instruction. (Some interpreters do not allow this)
  16.3 You tried to call a label that isn't a subroutine/function, but instead, is some label in a DO loop, SELECT group, or IF/THEN instruction. (Some interpreters do not allow this)
17 Category: There's an PROCEDURE keyword in an unexpected place
  17.1 A PROCEDURE instruction wasn't the first instruction in a subroutine/function
18 Category: There's a missing THEN keyword
  18.1 There is an IF keyword with no subsequent THEN
  18.2 There is a WHEN keyword (in a SELECT group) with no subsequent THEN
19 Category: There's a missing string or variable name
  19.1 There is no environment name after an ADDRESS keyword
  19.2 There is no subroutine name after a CALL keyword
  19.3 There is no label name after a NAME keyword
  19.4 There is no label name after a SIGNAL keyword (to jump somewhere)
  19.5 There is no string or variable name after a TRACE keyword
  19.6 There is no variable name after a PARSE keyword
20 Category: There's a missing label name where one is expected
  20.1 Found an illegal label name
  20.2 Found something that wasn't a label name
21 Category: An instruction ended unexpectedly (ie, missing the remainder of the instruction)
  21.1 An instruction ended unexpectedly
22 Category: An invalid literal string
  22.1 An invalid literal string
23 Category: An invalid data string
  23.1 An invalid data string
24 Category: An invalid trace setting
  24.1 An invalid trace setting
25 Category: An invalid keyword found
  25.1 An unrecognized keyword followed CALL ON
  25.2 An unrecognized keyword followed CALL OFF
  25.3 An unrecognized keyword followed SIGNAL ON
  25.4 An unrecognized keyword followed SIGNAL OFF
  25.5 An unrecognized keyword followed ADDRESS WITH
  25.6 An unrecognized keyword followed INPUT
  25.7 An unrecognized keyword followed OUTPUT
  25.8 An unrecognized keyword followed APPEND
  25.9 An unrecognized keyword followed REPLACE
  25.11 An unrecognized keyword followed NUMERIC FORM
  25.12 An unrecognized keyword followed PARSE
  25.13 An unrecognized keyword followed UPPER
  25.14 An unrecognized keyword followed ERROR
  25.15 An unrecognized keyword followed NUMERIC
  25.16 An unrecognized keyword followed FOREVER
  25.17 An unrecognized keyword followed PROCEDURE
26 Category: An invalid whole number
  26.1 The whole number is larger than the current NUMERIC DIGITS setting
  26.2 The repetition count after DO is not a whole number
  26.3 The value after FOR (in a DO instruction) is not a whole number
  26.4 A position in a PARSE template is not a whole number
  26.5 NUMERIC DIGITS setting is not a whole number
  26.6 NUMERIC FUZZ setting is not a whole number
  26.7 Number of instructions to skip in interactive trace is not a whole number
  26.8 Tried to raise to a power that wasn't a whole number
  26.11 Remainder of division exceeds NUMERIC DIGITS
  25.12 Division result exceeds NUMERIC DIGITS
27 Category: An invalid DO instruction
  27.1 An invalid keyword was used in a DO instruction
28 Category: An unexpected LEAVE or ITERATE
  28.1 There is a LEAVE keyword outside of a loop
  28.2 There is an ITERATE keyword outside of a loop
  28.3 The variable name after a LEAVE keyword is not used with any DO instruction
  28.4 The variable name after an ITERATE keyword is not used with any DO instruction
29 Category: An environment name is too long
  29.1 An environment name is too long
30 Category: A variable name or literal string is too long
  30.1 A variable name is too long
  30.2 A literal string is too long
31 Category: A variable name starts with a '.' or number
  31.1 A variable name consists of a number
  31.2 A variable name starts with a number
  31.3 A variable name starts with a '.'
33 Category: Invalid expression
  33.1 NUMERIC DIGITS setting is greater than NUMERIC FUZZ setting
  33.2 NUMERIC DIGITS setting is larger than maximum
  33.3 NUMERIC FORM is not followed by either an 'E' or 'S'
34 Category: A conditional expression doesn't evaluate to 0 or 1
  34.1 The expression after IF doesn't evaluate to 0 or 1
  34.2 The expression after WHEN doesn't evaluate to 0 or 1
  34.3 The expression after WHILE doesn't evaluate to 0 or 1
  34.4 The expression after UNTIL doesn't evaluate to 0 or 1
  34.5 The expression before a boolean operator isn't a 0 or 1
  34.6 The expression after a boolean operator isn't a 0 or 1
35 Category: Invalid expression is encountered
  35.1 Invalid expression is encountered
36 Category: A closing parenthesis '(' is missing
37 Category: Unexpected closing parenthesis '(' or comma
  37.1 Unexpected comma
  37.2 Unexpected closing parenthesis '('
38 Category: Invalid PARSE template
  38.1 Invalid parse search string
  38.2 Invalid parse position
  38.3 Missing WITH keyword after PARSE VALUE
40 Category: Incorrect call to a subroutine/function
  40.1 Generic error
  40.3 You passed too few arguments
  40.4 You passed too many arguments
  40.5 A required arg is missing
  40.9 A numeric arg exceeds the NUMERIC DIGITS setting
  40.11 An arg is supposed to be numeric, but isn't
  40.12 An arg is supposed to be a whole number, but isn't
  40.13 An arg is supposed to be 0 or positive, but isn't
  40.14 An arg is supposed to be positive, but isn't
  40.15 A numeric arg is has more digits than it is supposed to have
  40.16 A numeric whole number arg is has more digits than it is supposed to have
  40.17 A numeric arg is not within a required range
  40.18 A numeric arg representing a year is not within a required range
  40.19 An arg is not in the expected format
  40.21 A required arg has been omitted
  40.23 An arg is supposed to consist of a single character, but has more
  40.24 An arg is supposed to be expressed in binary, but isn't
  40.25 An arg is supposed to be expressed in hexadecimal, but isn't
  40.26 An arg is not a valid variable name
  40.27 An arg is not a valid stream name
  40.28 An unrecognized option
  40.29 Conversion is not supported to the requested format
  40.31 An arg to RANDOM() exceeds the maximum value
  40.32 The args to RANDOM() exceed the maximum range
  40.33 A numeric arg that is not supposed to be larger than another arg, is
  40.34 The linenumber passed to SOURCELINE exceeds the number of lines in the script
  40.35 An arg is supposed to be converted to a whole number, cannot be converted
  40.36 An arg is supposed to be the name of an existing variable, but isn't
  40.37 An arg is supposed to be the name of an environment, but isn't
  40.38 An arg is not large enough to format
  40.39 An arg whose value is that supposed to be either 0 or 1, isn't
  40.41 An arg that represents a position in a stream, is beyond the end of the stream
  40.42 Attempted to set the position on a TRANSIENT stream
41 Category: Bad math expression
  41.1 A non-numeric value is to the left of a math operator
  41.2 A non-numeric value is to the right of a math operator
  41.3 A non-numeric value is used with a prefix operator such as '\'
  41.4 The value of the expression of a TO keyword (in a DO instruction) is not numeric
  41.5 The value of the expression of a BY keyword (in a DO instruction) is not numeric
  41.6 The expression that represents the loop count in a DO instruction is not numeric
  41.7 A numeric value in exponential format has too big an exponent
42 Category: Overflow/underflow in math result
  42.1 Overflow in math result
  42.2 Underflow in math result
  42.3 Tried to divide by 0
43 Category: A script you tried to run cannot be found
  43.1 A script you tried to run cannot be found
44 Category: A function didn't return any value when it was supposed to
  44.1 A function didn't return any value when it was supposed to
45 Category: A REXX script didn't return any value when it was supposed to
  45.1 A REXX script didn't return any value when it was supposed to
46 Category: Invalid variable reference
  46.1 There's a missing closing parenthesis in a variable name
47 Category: Label found in an unexpected place
  47.1 There's a label found in an INTERPRET string
  47.2 There's a duplicate label. Reginald-only, when the 'LABELCHECK' OPTION is on
48 Category: The operating system reported some problem
  48.1 The operating system reported some problem
49 Category: REXX reported some internal problem
  49.1 REXX reported some internal problem. Most likely a bug
50 Category: Encountered an unrecognized reserved keyword
  50.1 Encountered an unrecognized reserved keyword
51 Category: Invalid function name
  51.1 An unquoted function name erroneously ends with a dot
52 Category: A function/subroutine tried to return a value that has too many characters
53 Category: Invalid option
  53.1 A variable name was supposed to appear after the STREAM keyword
  53.2 A variable name was supposed to appear after the STEM keyword
  53.3 The variable name after the STEM keyword was supposed to end with a dot
54 Category: Invalid use of STEM keyword
  54.1 An count of lines does not follow STEM APPEND
65 Category: An untrapped SYNTAX condition occurred in a child script. OPTIONS 'TRAP' must be on. CONDITION('D') reports the script name, exact error, and line number. Reginald-only
80 Category: An error in an environment. Reginald-only
  80.5 An environment had a problem when you tried to fetch the value of one of its variables
  80.5 An environment tried to return a value that has too many characters


Fatal (untrappable) SYNTAX errors

Even if you have the SYNTAX condition trapped in your script, there are certain of the above errors that will cause REXX to do its default handling of displaying some information about the problem, and aborting your script. Why? Because there are just some SYNTAX problems which REXX considers insurmountable. For example, if there is a missing quote on some literal string, REXX can't be sure what is supposed to be part of a literal string and what is supposed to be your instructions. So, REXX simply aborts your script regardless of whether you have a SYNTAX handler. In practice, REXX does this only for errors you make in the actual notation of your script, so you should be able to track down and eliminate these SYNTAX errors before finalizing your script. Some interpreters, such as Reginald, will not even begin running the script if there is such a "fatal" SYNTAX error in the script. As soon as you attempt to run the script, it will abort with an error message. So, if your script runs at all, then you know that you have no such fatal SYNTAX errors in it, and all other SYNTAX errors that crop up while your script is running can be trapped by your own handler. (Reginald also offers a SYNTAX Checker that will report all fatal SYNTAX errors in a script).

The majority of SYNTAX errors that could crop up while your script is running, such as category 40, can be trapped by your SYNTAX handler.


RC variable

If a SYNTAX condition is handled via SIGNAL ON, then the special variable RC will be set to the ANSI error number associated with why the SYNTAX condition was raised. The CONDITION() built-in function's 'E' option can return both the error and sub-error numbers, but RC is set to the error number only. Since some interpreters do not implement the 'E' option for CONDITION(), in this case, you'll have to make due with the RC variable, and perhaps the 'D' option only.

Note: The RC variable is created by REXX, which assigns it a value when a condition is raised. You should never name your own variable RC, but may reference this variable.