[<<Previous Entry]
[^^Up^^]
[Next Entry>>]
[Menu]
[About The Guide]
Quality of the recovered code
The code Rescue5 recovers is similar to a formatted version of
the .PPO code emitted when you specify the /p switch with the
CA-Clipper compiler, except that the code recovered has
undergone compiler optimisation.
This means that the code recovered is procedure instead of
command based (all CA-Clipper commands, except flow-control
statements, are pre-processed to procedure calls). This has
the following implications:
1) Some CA-Clipper "internals" may be referenced
directly in the source code. For example, an @ .. GET
command becomes a sequence of function calls including a
call to _GET_(), the QUIT command becomes a call the _QUIT()
function etc. This has no effect on the compatibility of
the code with the original system.
2) Manifest constants are lost (K_F2 becomes -1 etc.).
3) The CA-Clipper optimiser will have removed some redundant
code. In most cases this makes statements more logical:
Original PRG code
-----------------
USE clients
PPO output (CA-Clipper /p switch)
---------------------------------
dbusearea(.f.,,"clients",,if(.f. .or. .f., !.f., nil), .f.)
The code Rescue5 recovered
--------------------------
dbusearea(.f.,NIL,"clients",NIL,NIL,.f.)
In the above example, if(.f. .or. .f., !.f., nil) has been
resolved by the CA-Clipper optimiser to the constant nil.
In addition to the above, the following code statements may be
recovered in a slightly different form to that originally
written. In all cases this is because the CA-Clipper compiler
has produced p- code that can be decompiled in more than one
way. Note that the code recovered by Rescue5 is functionally
identical to the original:
1) DO CASE may become IF ELSEIF
Under some circumstances it is impossible to
differentiate between IF..ELSEIF..ENDIF and DO
CASE..ENDCASE, since both sometimes compile to the same
p-code. Rescue5 generates an IF construct. Since both
constructs have exactly the same effect this does not change
the functionality of the program.
2) Unary increment and decrement
Where a unary increment or decrement operator appears on a
line by itself, CA-Clipper produces p-code for the "pre"
version, even if the "post" version was used in the original
code (nCount++ on a line by itself will become ++nCount).
Outside compound statements the two expressions are
arithmetically equivalent.
3) Declared but unreferenced static variables become 'file-wide'
Rescue5 determines whether a static variable is file-wide
or function-scoped according to its actual usage. Therefore
a function that declared a static variable but never
actually references it cannot 'claim ownership' of the
variable.
4) Logically equivalent IF statements
CA-Clipper produces the same p-code for:
if x
if y
:
endif
endif
and
if x .and. y
:
endif
Since the two are functionally equivalent, Rescue5 generates
the second, less verbose version.
5) Code grouping
A technique that is widely used, code grouping is the
placing of a comma-separated list of expressions within
parentheses:
cName := (cust->(dbsetorder(2), dbseek('123')), cust->name)
The expressions are evaluated from left to right, the result
of the entire group being the value of the last expression.
Thus the expression above is the equivalent of:
cust->(dbsetorder(2))
cust->(dbseek('123'))
cName = cust->name
Under rare circumstances Rescue5 may encounter p-code that
is ambiguous to the extent that the original code might have
been grouped or might not. In these cases Rescue5 will
not group the recovered code.
It is possible (although very unusual) for Rescue not to group
code that was originally grouped. The /c switch forces Rescue5
to try to group ambiguous code, eliminating errors introduced by
the default grouping strategy. /c should be used with caution,
since it can introduce other problems by causing Rescue to attempt
to group code that was not originally grouped.
6) Macro in a code block becomes a macro-ed code block
Under some circumstances the CA-Clipper compiler 'converts'
a code block into a macro:
eval({|| memvar->&"str"})
Becomes:
eval(&"{|| memvar->" + chr(34) + "str" + chr(34) + "}")
The two expressions are functionally identical.
7) 'Phantom' procedures
If the original system was compiled without the /n switch,
CA-Clipper will have automatically declared a procedure for
each of the source files.
These are emitted by Rescue5 as procedures with no body (no
code between the procedure declaration and the return
statement).
It is possible for CA-Clipper to create procedures with
illegal names in this manner (CA- Clipper has created a
procedure 'internally' that it could not normally compile).
This page created by ng2html v1.05, the Norton guide to HTML conversion utility.
Written by Dave Pearson