Specifications

a CR (though it has some tricks of its own: see UDUMP, this issue). In TAB, you
sho :ld delete the: jsr getchar_ and substitute for it the
loop loop shown at left. KYPUTB_, as with any 'get1, is happy to
jsr kyputb_ get a null, so you must loop until you see a character. You
cmpb #0 must stuff: kyputb_ equ $dd82 into your .asm file, right af-
until ne ter service_ equ $32, so SPET knows where to look. Waterloo
didn't document KYPUTB_, but Gary Ratliff did, on page 83 of
issue 7. The character 'got' is found in the B register. Reserve GETCHAR_ for
multi-character strings or to give users a chance to correct input errors.
Last, we said TAB wouldn't interfere with APL or COBOL if you overloaded them in
Bank 15 after using TAB. Well, that's true if you make origin $9000. We didn't;
we shoved TAB way up to $9f00, and APL didn't know where APL quit and the left
over shard of TAB started. Origin should be $9000 for TAB or any other ML pro
gram in Bank 15. That low, it is surely overwritten by APL and COBOL. In other
languages/facilities, you needn't change origin to $9000.
< x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x >
USING MACROS IN DEVELOPMENT PROGRAMS Last issue, I wrote about straight-line
Part II : by John A. Toebes, VIII macros and those to which you can pass
145 C Jones Franklin parameters as operands. They are quite
Raleigh, N.C. 27606 simple and easy to use. This issue, we
. look at complex macros, and end with a
general macro which will clean up the stack for you. Complex macros are the most
advanced but most useful; you can do almost anything, including some high-level
language constructs.
One I find most useful is CALL.MACRO; it automatically loads parameters, calls a
a routine, and then cleans up the stack. It must be able to accept any number of
parameters (a subroutine may have a large number of them) and then determine how
much space to take from the stack. This last is a problem the macro processor
doesn't know how many parms* there are. We therefore test each parm to see if
it's null; when we find the null, and if we arrange to count parms, we've solv
ed the problem. So, let's first look at finding the null parameter. (* I use the
abbreviation 'parm' for 'parameter'.)
Two conditional Assembler directives are most useful: IFC (IF Comparable), and
IFNC (IF Not Comparable). (The 'comparable' means exactly alike. For fuller de
tails, see p. 138, Development manual.) Both IFC and IFNC take two operands and
compare them. If they are identical, the code following IFC is executed; if they
are not identical, code following IFNC is executed. We simply test each paramet
er against a null until we find a match. Before I pass to an example, remember
that parms are passed to macros to match a psuedo-variable, identified in the
macro as '\0, \1...\n'. The first parm is assigned to psuedo-variable \0, the
second to psuedo-variable \1, etc. While it might seem simple to test the parms
against a null, there is a pitfall— the comma, which is a data separator.
If, for example, we pass a single parm '5,X' to a macro as psuedo-variable \1,
and if we test to see if the it is the string TEST, our macro code will be that
at left, top line. In operation, our code will compare TEST
IFC TEST,\1 with 5, because 5 is followed by a comma, which excludes the
is seen as following 'X', even though it is part of parm \1. We manage
IFC TEST,5,X to sneak by this comparison through luck, not design. But now
suppose we pass the parm ',S' to psuedo-variable \1 and we
want to compare it to a null. We are in trouble. Our code in the macro again is
SuperpPET Gazette. Vol.I No.11
-158-
December 1983/January 1984