[Date Prev][Date Next][Subject Prev][Subject Next][
Date Index][
Subject Index]
Brief primer: Debugging and learning how XPL (was: AU program)
- Subject: Brief primer: Debugging and learning how XPL (was: AU program)
- From: Robert Holmgren holmgren@xxxxxxxx
- Date: Tue, 28 May 2002 13:29:56 -0400
** Reply to message from "Morris Krok" on Mon, 27 May
2002 06:42:44 -0700
Morris:
> I understand the general trend of [Carl's] AU program superficially, but
> for me to comprehend its logic in greater detail, I need the following
> explanations...
I want to discuss the how-to aspect of self-help (and let Carl address the
specifics of his program). In general, there are several basic techniques for
analyzing the content and progress of an XPL program, that an interested user --
and it's nice to see someone this interested -- can use to figure out how they
work.
Let's take this short example from Carl's routine: >
Your question, I suppose, is what does mean? Probably the simplest,
on-the-fly method to find out is to insert, immediately after >,
something like >. That displays a PRompt showing the content
of S/G 03 (which now holds the value of ). The second statement pauses
execution while you read the PRompt (it awaits a keystroke, which is then thrown
away because S/G 99 has no other role in the program, being a transient
[non-permanent] Save/Get selected for this temporary purpose because it is *not
otherwise used* in the program). You could put > _before_
Carl's code to see what S/G 04 means before S/G 03 extracts information from it.
That way you have a before-and-after. If it still isn't clear what's going on,
you could make a minor modification to Carl's code, such as or
, to observe the differences. But since this modifies the program, and
may crash it, one should probably also terminate the program after this point
with .
I suppose, for anyone who has read this far, it's unfair to withhold the
answer: VA@04|1 parses string 04 for the separator "|", and grabs the first
(leftmost) element defined by that separator. An example unrelated to Carl's
program: if S/G 04 contained "a|b|c|d", would be "a", would
be "d", and would be "" (empty), because there are only four
"|elements|" in string 04. Note this subtle difference: if S/G 04 contains
"|a|b|c|d|", there are now *six* elements in the statement (the outermost two of
which have no length, to the left and right side of the first and last "|"):
would be "" (empty), would be "a", would be "d",
and would be "" (empty). And would "" (empty) too, because
separator "." doesn't occur in S/G 04. This kind of parsing is valuable, but
has limitations also. If we learn that is "" (empty), we don't know
whether it just happens to be empty (unlike or other elements), or the
separator "|" doesn't exist in S/G 04, or maybe S/G 04 itself doesn't exist, or
it exists but is altogether empty (), or what. So you may need to use
this tool in combination with other tools (a test for size greater than zero, or
a test for containment of "|", etc), or else under highly controlled conditions
(where you KNOW that S/G 04 contains specific content).
Note that you can do the same thing with VAriables, without needing to specify
the separator (because it's always a comma), e.g. , get the second
element of the Tab Setting, e.g. "16" from "8,16,24,32,...". Many of these
capabilities are summarized (albeit very pithily) by TABLE VARIABLES.
Another technique for analyzing XPL code is to use the native DeBug variable,
DB. You can set it to pause on various statements in parts or all of a program,
and report the results of the current operation on the Prompt line. DeBug is
quite an interesting tool, and allows you to map the progress of a program
through the code. To use it, or experiment with it, insert code in the program
where you want to start DeBugging, e.g. "BX d db=23,3Q2 ". (Be sure to turn
DeBugging off before the routine terminates, with "BX d db=0,0Q2 " -- if you
forget, do it on the CMline: "d db=0,0".) DeBug is a very broad brush, and
often supplies too much information, but is excellent for describing the path
taken through code when it is RUN (especially the conditional True/False path,
together with LaBels and Go-To's).
A different, and quite targeted, way to proceed is to use the XRAY utility, in
U2. XRAY doesn't get in the way of program operation. It simply logs the value
of all S/Gs in a program, or of a specified narrower range of Save/Get(s), to a
report that is compiled in another window, tabling the value of Save/Gets each
time the program passes (and optionally pauses at) one or more "checkpoints".
So in Carl's AU program, you would establish a checkpoint, by inserting "JM
2.xray:03-04Q2 ", right after >. On termination, you could look
at the report, and see whether (if!) the values of VA@04 and VA@04|1 change each
time the program loops past this instruction. From that, you could probably
infer how VA@04|1 works. See HELP XRAY*, for details and more
sophisticated usages of XRAY.
Another important tool is RUNCODE, in U2. RUNCODE allows you to "detach" a
fragment of code (by DeFining it) from its larger context, and run it
(RUNCODE) in isolation. This has the advantage of speed and economy,
and of focusing on a narrow result, or how a single operation works, pinpointing
mistakes in coding, etc. It has the drawback that if you simply DeFined and ran
> out of context, S/G 04 would have no content when entering the
procedure, and hence the result will always be "" (empty). Since you just want
to find out what means, you might put a little dummy code in there
right in front of your target statement -- something like
>
and then RUNCODE that in isolation (S/G 03 result = "what")
There are many ways to deconstruct an XPL program, but these will get you
started.
-----------------------------
Robert Holmgren
holmgren@xxxxxxxx
-----------------------------