Compatibility between KCML versions

KCML programs saved by previous versions of KCML will execute on later versions with a few exceptions documented below. If you want to develop on a particular version of KCML, say on KCML 6.0, but execute it on an earlier version, then you need to set an environment variable appropriate to the target version. Then SAVE will warn if any construct that would not be supported in the target version is used in the program. The program will always be saved.

The parser may well generate different, compatible code, when you edit a line in the workbench, LOAD an ascii program or when you use $COMPILE. Generally the code differences ensure that the program behaves consistently in the current KCML and in the target environment. For instance setting COMPAT32 will allow local variables passed back from subroutines to be referenced out of scope. To do this KCML must generate different code.

The runtime environment may also be affected by these compatibility flags making the modern KCML behave in a different, compatible way. For instance setting COMPAT40 will suppress the P41.6 error that results from RETURN CLEAR inside a function returning a value. This can lead to stack overflow problems so modern KCMLs error this but older software may rely on this behaviour.

Setting COMPAT40 environment variable implies setting COMPAT32 and COMPAT32 so you do not need to set all of them. These variables can also be set by flags specific bytes of $OPTIONS RUN. This second method gives better control but can only be done inside the application.

KCML6.60 differences

KCML6.20 differences

KCML6 differences

Note that there is no COMPAT50 and any differences most be coded around to be compatible with both versions. The forms manual lists the differences between 5.02 and 6.0 here. The differences between 5.02 and the interim 5.03 limited release listed here should also be considered. You will not be warned by SAVE if you use new KCML 6.00 properties or events in a program intended for KCML 5.x.

Other differences include:

COMPAT40 differences

If enabled, either with the environment variable COMPAT40 or by setting byte 38 of $OPTIONS RUN, this will cause KCML 5.0 or later to behave differently in the following areas

Byte 38AffectsControls
HEX(01)RuntimeSAVE will warn about constructs added after KCML 4.0, including 0xNN numeric literals
HEX(02)RuntimeNormally a P41.6 error will be thrown if a RETURN CLEAR is issued inside a subroutine which is involved in an arithmetic expression e.g.
a = b + 'fred()
This error can be suppressed with this flag though this may lead to eventual stack overflow and the fatal termination of KCML.
HEX(04)ParserPrograms will be SAVEd with their symbols in upper case. This was the convention prior to KCML 5.0 which allowed the preservation of mixed case in symbol names. The KCML4 editor and program LIST feature always lower cases variables.
HEX(08)ParserEmpty string literals, e.g. "", are not allowed.

There are other KCML4 to KCML5 differences that are not covered by these compatibility flags:

COMPAT32 differences

If enabled, either with the environment variable COMPAT32 or by setting byte 16 of $OPTIONS RUN, this will cause KCML 4.0 or later to behave differently in the following areas

Byte 16AffectsControls
HEX(01)RuntimeSAVE will warn about constructs added after KCML 3.22
HEX(02)RuntimeThe length of a program line is limited to 1900 bytes and checked after editing in the line editor. This can only be set using the COMPAT32 environment variable though it can be overridden using the LINELEN environment variable.
HEX(04)ParserLOCAL DIM works the same way as in KCML 3.2. This has a particular impact in the case of a function returning a LOCAL DIMed string where the program must be compiled with the COMPAT32 flag to keep the KCML 3.2x behaviour of allowing out of scope reference to such strings.
HEX(08)ParserFALSE is compiled differently to be compatible with what KCML 3.2 expected.
HEX(10)ParserSigned arguments are not allowed in $DECLARE definitions e.g. no INT(-). This is a compile time check with a P23.8 error if parsed when COMPAT32 is set.
HEX(20)ParserSYM(*)$() is compiled differently as KCML3.2x did not support SYM of string arrays properly
HEX(40)ParserCode will be compiled for subroutines so that the GOSUB (optional in KCML4 and later) will be regenerated in KCML 3.2x.

COMPAT30 differences

If enabled, either with the environment variable COMPAT30 or by setting byte 1 of $OPTIONS RUN, this will cause KCML 3.2 or later to behave differently in the following areas

Byte 1AffectsControls
HEX(01)RuntimeSAVE will warn about constructs added after KCML 3.0
HEX(02)RuntimeSTR() operator does not allow zero length substrings.
HEX(04)RuntimeThe recreator will strip () from DEFFN' subroutines with no arguments
HEX(08)ParserThe NEXT BREAK operator will not be recreated as BREAK but as the compatible NEXT BREAK. In KCML 3 NEXT BREAK was required to break out of a FOR loop. In later versions of KCML the BREAK operator was used.
HEX(10)ParserPTR() will be recreated instead of SYM(*)$. In KCML 3 the PTR() operator was used to dereference string symbols.
HEX(20)ParserNormally KCML evaluates all the argument expressions of a DEFFN' and then matches them. However for a 2200 compatible numeric function e.g. DEFFN'99(a, b(a)) code will be compiled differently allowing a later argument to depend on an earlier one as was the case with BASIC-2. Setting COMPAT30 will not treat these numeric functions differently.
HEX(40)ParserIf set KCML will generate code to evaluate the start and end expressions of a FOR loop completely before starting the loop as was the case in KCML 3.0. Starting with KCML 3.2, to be compatible with BASIC-2, code is compiled differently allowing the end expression to be revaluated on each iteration allowing end expressions that change as the loop is executed.

DOS Features dropped from KCML5 and later versions

A number of real mode DOS specific functions were dropped from KCML5 that were supported on KCML4.