Ernest G. Allen wrote:
On Sun, 14 Jul
2013, Jerome H. Fine wrote:
Date: Sun, 14 Jul 2013 16:11:16
From: Jerome H. Fine <jhfinedp3k at compsys.to>
Reply-To: "General Discussion: On-Topic and Off-Topic Posts"
<cctalk at classiccmp.org>
To: General Discussion: On-Topic and Off-Topic Posts <cctalk at classiccmp.org>
;
Subject: Help with a .MACRO in MACRO-11
I have a program in MACRO-11 and I have retained just
the essential aspects related to my question. That portion
of the program is at the bottom.
I have unsuccessfully attempted to isolate the first 5 characters
of STRING in the MACRO ABC, but I have been unsuccessful.
Concatenation is possible along with checking individual characters
of the argument, but there does not seem to be support for
changing the last character from "T" to "2" as in my example.
If that were possible, I could always use "ABC WRKTXT"
and check to determine if "WRKTX2" was a defined STRING
name at which point the MACRO ABC would automatically use:
: Mov #WRKTX2,-(SP)
without the necessity of providing the explicit STRING name
of WRKTX2 to be used WITHIN the conditional A$. It
is essential that the address of the STRING be placed on the
stack when the text is in the .PSect TX2. Sometimes, the
text must remain in .PSect TXT, so that is why ABC has
the additional code to detect the last character of STRING.
As I have shown, it is possible to determine if the 6th character
of the STRING name is a :"2", but I don't seem to be able to
strip off the 6th character of the name from STRING and
replace it with a "2". At that point, it would be possible, still
within the MACRO ABC, to test to see if the STRING name
for which the 6th character has been replaced by a "2" exists
and use the second form of ABC.
Thank you in advance for any suggestions?
Jerome Fine
=============================
.IIf NDF A$,A$ = 0
.IIf NDF A$,A$ = 1
.MACRO ABC STRING
..STRI = 0
...STR = 0
.IRPC ..STR.,<STRING>
...STR = ...STR+1
.If EQ ...STR-6
.If IDN ..STR.,<2>
..STRI = 1
.EndC;IDN ..STR.,<2>
.EndC;EQ ...STR-6
.EndR;.IRPC
.If EQ ..STRI
Mov #STRING,R0
.IfF;EQ ..STRI
Mov #STRING,-(SP)
.EndC;EQ ..STRI
.ENDM ABC
.If EQ A$
.PSect TXT RW,D
WRKTXT: .Ascii /Work/
.IfF;EQ A$
.PSect TX2 RW,D
WRKTX2: .Ascii /Work/
.EndC;EQ A$
.PSect Code RW,I
.If EQ A$
ABC WRKTXT
.IfF;EQ A$
ABC WRKTX2
.EndC;EQ A$
.End
Jerome,
I've never used MACRO-11, but have done a lot of macro and
string manipulation work. Given the limitation that you have
listed (cannot change a character of a string), and the ability
to test the sixth character of the passed string, one solution
might be to
(1) create or build up a new string NEWSTR that contains the
first five characters of the passed argument, then
(2) test the last character of the passed argument and,
depending on the results of the test,
(3) append the appropriate character to the NEWSTR and do any
other actions that use the complete NEWSTR but are based on the
value of the last character of the passed argumenet.
In a pseudocode, using PASSED as the passed six-char value, and
NEWSTR as the built-up string, it would be:
; initialize NEWSTR
NEWSTR = ""
;
; Next, build up NEWSTR to hold the first five chars of PASSED
;
; Here the setting of the value of NEWSTR is shown as a single
; line, but it might be necessary to build it up with a long
; series of test much like the testing of the sixth character of
; PASSED. You might have to use 5 loops, or if that isn't
; possible, five blocks with each block containing 36 to 40
; tests.
;
NEWSTR = first five chars of PASSED
;
; test the sixth char of PASSED, append it to NEWSTR, and
; perform any other required actions. "##" is a CPP-style
; concatenation operator.
;
if sixth-char-of-PASSED == "A"
NEWSTR = NEWSTR ## "A"
; use NEWSTR based on 6th char of PASSED
endif
if sixth-char-of-PASSED == "B"
NEWSTR = NEWSTR ## "B"
; use NEWSTR based on 6th char of PASSED
endif
if sixth-char-of-PASSED == "C"
NEWSTR = NEWSTR ## "C"
; use NEWSTR based on 6th char of PASSED
endif
if sixth-char-of-PASSED == "D"
NEWSTR = NEWSTR ## "D"
; use NEWSTR based on 6th char of PASSED
.
.
.
if sixth-char-of-PASSED == "0"
NEWSTR = NEWSTR ## "0"
; use NEWSTR based on 6th char of PASSED
endif
if sixth-char-of-PASSED == "1"
NEWSTR = NEWSTR ## "1"
; use NEWSTR based on 6th char of PASSED
endif
if sixth-char-of-PASSED == "2"
NEWSTR = NEWSTR ## "2"
; use NEWSTR based on 6th char of PASSED
endif
.
.
.
It isn't pretty or elegant, but I've had success with this
approach several times when the tool or simple language I've
had to use cannot change a character in an existing string.
THANK YOU for your suggestions. They will also work.
The reason that I have avoided them is the nature of the situation:
(a) I started with the code for a 10,000 line device driver in RT-11
which is one version behind the most recent executable version.
(b) I added about 4000 lines of code so the the source file now
produces both the original executable file and the most recent
executable version. Whenever I added a line of code, the last 5
characters in the line were:
";AAAn"
where AAA was usually the initials of the author (if it is possible
to identify the author) who actually made those changes followed
by a number or letter to identify the version number being changed.
(c) For this example, most of the the changes were made to reduce
the Low Memory used by the device driver and place as much
as possible of the code and data from that one version behind
level of code to the current version which actually filled all of
PAR1 with code and data when a Mapped Monitor is being used
under the RT11XM variant of RT-11. Anyone who is extremely
familiar with RT-11 and Mapped Monitors will be aware that a few
of the other device drivers, such as DUX.SYS and SLX.SYS, also
place some of their code and data in extended memory to be used
in PAR1.
(d) I then proceeded to add additional lines of code which move even
more of the code and data into a second PAR1 for the device
driver - although in principle this possibility seems impossible.
The solution is actually quite simple - use a few instructions
in Low memory to change the value of KISAR1 to the value
(in practice, just add 200) used by the additional PAR1 code
and data usually followed by those few same instructions to return
to the original PAR1 code and data. In all cases, another set of
5 characters at the end of each new line of code again identifies
the additional added lines of code.
NOTE that in many cases, using the .Macro ABC was part of the the
original version of the source code and those lines did NOT include
those special 5 characters. Consequently, I adopted the first solution
and used a symbol set to "1/0" to activate the extra code (or NOT)
depending on which variant was being assembled by MACRO-11.
As a result, the new source code is still able to produce any of the
old original variants of the device driver along with the newer variants.
The presence of those last 5 characters serve a two fold purpose:
(i) They identify an added line.
(ii) It is trivial to remove those added lines and revert to an identical
copy of the original source file by deleting those lines using either
TECO or KED in one simple repeated operation.
In this situation, since some of the code which invokes the .Macro ABC
are original lines in the original source file, making any change to those
lines would prevent being able to remove new lines and revert either
to the old original version of the source code or the version or the source
code which produces the current version of the executable file.
I realize that my guidelines for making changes restricts me quite a bit,
but there is also a considerable advantage to making sure that I don't
somehow modify something that must remain the same. In any case,
having happily adopted those guidelines and found them to be extremely
helpful, that is the primary reason I will NOT make any changes at all
to the original source code.
If anyone else has any comments, they would be very appreciated.
Ernest, if you have any questions, please ask.
And finally, I will now answer the brilliant suggestion by John Wilson
who actually provided a solution to my problem!!!!!!!!!!!!!!!!!!!!!
Jerome Fine