EXTERNALfunction. Use your editor to view the file
" This is a Comment "
" This is a comment that extends over two lines "
DELTAG = -1;
DIAG = SQRT( (XVALUE1 - XVALUE2)**2 + (YVALUE1 - YVALUE2) **2 + (ZVALUE1 - ZVALUE2) **2 );
UCHKTAGfile is everything up to but not including:
"&COMMON/JAZELL/"Many lines in the header section are enclosed in Prepmort comment characters. However, some of these comment lines are actually used by the Prepmort compiler and the DUCS code distribution software. So do not assume that these lines can be left out.
Many of these comment lines are read by DUCS when the file is installed for use by the rest of the SLD collaboration. The lines contain information that DUCS turns into a help file. Thus every routine that contains a properly written header will automatically generate a help file when it is installed into DUCS.
$SLD_INTEGER_FUNCTION. The declaration includes the name and type of all of the routine's arguments. In the current example, the integer function definition extends over four lines.
KEYWORDSline is another special comment line used by the automatic help system. The applications that were meant to use these keywords were never implemented, so you can actually put whatever you want on this line. Just put in a few relevant words that people searching through files might use to find this particular file.
When the file is installed into DUCS, a help file is generated. The help can be read by issuing the help command from DCL with the appropriate library specified. Separate help libraries are maintained for each DUCS section.
Since the file
UCHKTAG.PREPMORT lives in section SLD,
you can view it with the command:
HELP/LIBRARY=DUCSSLD:SLDAs another example, you could view the help library for section MFIT:
UCHKTAGfile is everything from
LOGICAL FIRST / .TRUE. /;This part of the file declares what external code is to be included, what variables are to be used and what initial values these variables are to have.
"&can not have spaces before them.
P_MA_BELare both declared to be pointers to the Jazelle family
MA_BEL. The comma in this statement allows you to declare more than one pointer with a single statement.
The same pointers could have been set up with a pair of statements:
POINTER F_MA_BEL --> MA_BEL; POINTER P_MA_BEL --> MA_BEL;As was mentioned earlier, any statement can stretch over multiple lines. The end of the statement is determined by the semicolon. The spaces have no significane; they are only there to make the code easy to read. A statement can stretch over up to 19 lines.
UCHKTAGroutine. How you do this declaration depends on what kind of routine will be called. Some examples are as follows:
$SLD_INTEGER_FUNCTION, declare it with an
INTEGERstatement. Most SLD offline routines are of this type. For example:
$SLD_REAL_FUNCTION, declare it with a
REALstatement. For example:
$SLD_DOUBLE PRECISION_FUNCTION, declare it with a
REALstatement. For example:
$SLD_CHARACTER*(*)_FUNCTION, declare it with a
CHARACTERstatement requires an additional number to tell how long the string will be. Examples are:
CHARACTER*8 JZC8; CHARACTER*80 JZC;
INTEGER PREVTAG; INTEGER SEVTAG; INTEGER SAVCTRAC(10); INTEGER SAVCTRIB(10); INTEGER I;Or it could be written:
INTEGER PREVTAG, SEVTAG, SAVCTRAC(10), SAVCTRIB(10), I;Or they could have been grouped many other ways. You get the idea.
There is no real reason that this integer statement could not be joined
to the one that declared the routine
That might have looked as follows:
INTEGER JZBLOC, PREVTAG, SEVTAG, SAVCTRAC(10), SAVCTRIB(10), I;In general, it keeps things more clear if you separate the function declarations from the variable declarations. But this is not required.
The arrays like
SEVCTRAC(10) contain elements indexed from
You also have the option of specifying your start and end indexes.
For example, if you want the elements of
to be indexed from
Be careful. If no initial value is declared, the variable will initially contain whatever value happens to be in the piece of memory that the computer allocates to that variable. This could make your routine behave differently depending on what order code is loaded in or on what order you run other unrelated functions.
To repeat: the offline sortware system will not initialize the variable unless you tell it to.
CHARACTER*some other string size.
Here are some other examples of variable declarations:
REAL MCST(0:7), "cos(theta) from hits" Integer Nmc, Nktag, I, Nhits, Iktag, IdKtag, Imc, Imcs, IdMc, IdMc0, Layer, McId, Adc, Igain(0:7)/1,1,2,2,2,2,3,3/; CHARACTER*9 VALSTRG / 'VALUATOR=' /; REAL XARRAY(8), YARRAY(8); Real*4 bPos(3)/0.,0.,0./ ;
UCHKTAGexample starts with a very common construction called the "If First Block." This construction works together with the last declarations statement. Together, they create a section of code that will only be executed the first time the routine is called:
LOGICAL FIRST / .TRUE. /; IF FIRST [ $CALL JZBLOC( 'MA_BEL', F_MA_BEL ) ERROR RETURN; FIRST = .FALSE.; ]
$CALL. We will talk about this particular called routine,
JZBLOCa little later when we talk about calling Jazelle from Prepmort.
$CALL, the parentheses and the
are required for all calls to other Prepmort routines.
The Prepmort pre-compiler turns this construction into a standard
Fortran call plus some extra code that allows informational and error
messages to be handled in a sophisiticated way.
We will talk about this message handling later when we discuss the
Inside the parentheses are the arguments.
JZBLOC is a routine that finds the pointer to the head
of a Jazelle family.
'MA_BEL'. Note how strings are delimited by single quotes.
F_MA_BEL. This pointer was declared in the declarations section of this routine to be a pointer to a
JZBLOCsets this pointer to point to the zero
MA_BELbank, the head of the family.
IF INIT .EQ. 1. [ PREVTAG = 0; DO I = 1, 10 [ SAVTAG(I) = 0; ] ]
IFstatements allow a large number of operators. In general there are at least two ways to write any operator. In the following chart, operators on the same line do the same thing:
.GT. > .GE. >= .EQ. = .LE. <= .LT. < .NE. <> ^= .AND. & .OR. | .NOT. ^
DOstatements are self-explanatory. And, unlike IDA, you can use the loop index outside of the loop. Thus, after the
DOstatement in the example, you can expect
Ito be 10.
MA_BELbank. It does this by setting
P_MA_BELto be one bank forward from
P_MA_BEL = F_MA_BEL%(JB$FORPT);In Jazelle, each bank contains the pointer to the next bank in its family.
F_MA_BEL%(JB$FORPT)is this pointer (the FORPT comes from FORwards PoinTer).
This construction may look complicated, but there are actually very few such constructions that you will need to learn. For users who are already familiar with other pointer-based languages, such as C, this construction is nothing special.
Instead of using this
IF FIRST construction and the
JB$FORPT pointer, we could have obtained the pointer to the
first bank directly by calling a different Jazelle routine,
$CALL JZBFND( 'MA_BEL', P_MA_BEL ) ERROR RETURN;This would mean that every time the routine
UCHKTAGis called, it has to make a call to the routine
UCHKTAGmight get called a very large number of times, we chose to use the faster method. We only call to a Jazelle routine,
JZBLOC, the first time that
UCHKTAGis called. Every other time, we get away with a single assignment statement.
P_MA_BEL, we can get the variable
TAGby the expression
P_MA_BEL%(TAG)The expression starts with the pointer, then has a percent sign, then has the variable name within parentheses.
Here are some examples of other Jazelle variables:
P_MA_BEL%(CONTRACT) P_DSPWIND%(INTERLEV) P_KDGHIT%(HITS(J),TOWERID) PHPSUM%(X(3)) PHCHRG%(HLXPAR(1))
IF...ELSEstructure a little bit later.
IF P_MA_BEL%(TAG) .EQ. SAVTAG(I) [ IF P_MA_BEL%(CONTRACT) .EQ. SAVCTRAC(I) .AND. P_MA_BEL%(CONTRIBU) .EQ. SAVCTRIB(I) [ DUPLICAT = 1; EXIT; ] ELSE [ SPLIT = 1; EXIT; ] ]There is no
THENstatement in Prepmort. The block structure defined by the square brackets makes this unnecessary.
EXITstatement exists the nearest loop.
$RETURNis used along with the top line,
$SLD_INTEGER_FUNCTION, to tie this routine to the other routines that call it. The Prepmort pre-compiler turns the
$RETURNinto a standard Fortran
RETURNstatement plus some sophisticated error handling code.
Fortran fans, note that there is no
STOP in the routine.
STOP does not belong in any user routines.
DATAstatement can be used to assign an initial value to a variable. This has the same affect as the method we saw earlier in which the data was just appended to the end of the variable declaration statement. So you could replace:
LOGICAL FIRST / .TRUE. /; INTEGER COUNT / 10. /;with the following:
LOGICAL FIRST; INTEGER COUNT; DATA FIRST / .TRUE. /, COUNT / 10. /;
PARAMETERstatement is like a
DATAstatement except that the variable becomes an unchangeable parameter. The value can never be changed in the routine. The syntax is a little different from
INTEGER MAXEVT; PARAMETER (MAXEVT=50);Note that the variable must have been declared before the parameter statement.
A parameter can be used in later parts of the declaration section of the
For example, the routine
VXWRCCD PREPMORT uses a parameter this
integer i,j,k, "counters" bankid, hiloop, ndead; parameter (ndead = 38); integer dead(ndead) /53, 65,66,67,68,69,70,71,72, 105,106,107,108,109,110,111,112, 166, 201,202,203,204,205,206,207,208, 285,286, 316, 353,354,355,356,357,358,359,360, 365/; real effic(ndead) /95., 50.,50.,50.,50.,50.,50.,50.,50., 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,75., 20., 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0/;
EXITstatements. With proper use of square brackets and
ELSEstatements, you will not need statement labels very often. But here is how they work.
Any statement can have a label.
Put the label at the beginning of the statement
(as always with Prepmort, exact column position does not matter).
The label can be any set of up to eight characters with colons on either side.
Then put this label name after
:TRACK: DO I = 1, NTRACKS [ DO J = 1, NHITS [ ... ... IF BAD [ NEXT :TRACK:; ] ] ]
Code that is enclosed by the lines
will only be run on DEC VMS systems
(the VM version of the Prepmort compiler comments this code out).
Code that is enclosed by the lines
will only be run on IBM VM systems
(the VMS version of the Prepmort compiler comments this code out).
Edit the file
PRODUTIL:UGTIME:PREPMORT to see how the
routine that gets the current time uses this construction.