• Aucun résultat trouvé

RETURN CODES

Dans le document Pascal in MTS (Page 43-47)

CALLING SUBROUTINES FROM PASCAL/JB

RETURN CODES

Most system subroutines return a value called the return code. This value is normally zero if the subroutine was called and returned properly, and nonzero if an error occurred.

In Pascal/JB, the predefined function FORTRANRC contains the return code from the most recent call to a Fortran procedure or function. The Pascal/JB code generator produces highly efficient code (a single instruction) to effect the FORTRANRC function call. This means that there is almost no overhead associated with using the FORTRANRC function.

Pascal/JB: Calling Subroutines From Pascal/JB 43

The following example is similar to the GFINFO example above except that the return code is checked and the associated error message is accessed.

Program Test(Input,Output);

Type

Char4 = Packed Array [1..4] of Char;

Char8 = Packed Array [1..8] of Char;

Char16 = Packed Array [1..16] of Char;

Char20 = Packed Array [1..20] of Char;

Char80 = Packed Array [1..80] of Char;

Intgr2 = Array [1..2] of Integer;

Retrec = Packed Record Chr : Char20;

Int : Integer End;

Catrec = Packed Record Cial : Integer;

Cirl : Integer;

Cionid : Char4;

Civol : Char8;

Ciuc : Integer;

Cilrd : Integer;

Cicd : Integer;

Cifo : Integer;

Cidt : Integer;

Ciflg : Integer;

Cilcd : Integer;

Cipkey : Char16;

Cilcct : Intgr2;

Cilncd : Integer;

Cilnct : Intgr2;

Cicdt : Intgr2;

Cilrdt : Intgr2;

End;

Refname = Record End;

Var

Unit : Char8;

Rtn : Retrec;

Flag : Integer;

Cinfo : Catrec;

Ercode : Integer;

Errmsg : Char80;

I : Integer;

Procedure GFINFO(Const Gfunit : Char8;

Var Gfrtn : Retrec;

Const Gfflag : Integer;

Var Gfcinf : Catrec;

Const Gffinf : Integer;

Const Gfsinf : Integer;

Const Gfecod : Integer;

Const Gfemsg : Char80); Fortran;

Begin

Unit := 'SCARDS '; {Set unit name}

Rtn.Int := 0; {Zero file name return region}

Flag := '00000002'X; {Mark as unit name call}

Cinfo.Cial := 25; {Set Cinfo length}

GFINFO(Unit,Rtn,Flag,Cinfo,0,0,Ercode,Errmsg);

If FORTRANRC > 0 Then Begin

44 Pascal/JB: Calling Subroutines From Pascal/JB

If FORTRANRC = 4 Then Writeln(Ercode,' ',Errmsg);

If FORTRANRC > 4 Then

Writeln('Error return from GFINFO subroutine');

Return End;

Writeln(Rtn.Chr,' Owner = ',Cinfo.Cionid);

End.

The following example illustrates the use of FORTRANRC with both a procedure and a function.

Program Test(Input,Output);

Const

Mask = '00000010'X;

Type

Char4 = Packed Array [1..4] of Char;

Char18 = Packed Array [1..18] of Char;

Trplrec = Packed Record Ccid : Char4;

Proj : Char4;

Pkey : Char18 End;

Refname = Record End;

Var

Access : Integer;

Oldnam : Char18;

Newnam : Char18;

Triple : Trplrec;

Function CHKACC(Const Chknam : Char18;

Const Chktrp : Trplrec):Integer;Fortran;

Procedure RENAME(Const Renold : Char18;

Const Rennew : Char18); Fortran;

Begin

Oldnam := 'DATA1 '; {Set old file name}

Newnam := 'NEWDATA1 '; {Set new file name}

Triple.Ccid := 'WABC'; {Set triple}

Triple.Proj := 'WXYZ';

Triple.Pkey := '*EXEC ';

Access := CHKACC(Oldnam,Triple);

If FORTRANRC > 0 Then {Test return code}

Begin

Writeln('File does not exist');

Return End;

If (Access & Mask) ˜= Mask Then {Test access bit}

Begin

Writeln('Rename access not allowed');

Return End;

RENAME(Oldnam,Newnam);

If FORTRANRC > 0 Then {Test return code}

Begin

Writeln('Error return from RENAME subroutine');

Return End;

Writeln('File successfully renamed');

End.

The above example calls the CHKACC subroutine to determine if the file WABC:DATA1 exists and if

Pascal/JB: Calling Subroutines From Pascal/JB 45

the user has rename access to the file. If both conditions are true, the program renames the file to NEWDATA1. In this example, the FORTRANRC function must be called following the call to both the CHKACC and RENAME subroutines.

R-TYPE SUBROUTINES

R-type subroutines can be called from Pascal/JB by using the RCALL and ADROF subroutines.

The RCALL subroutine sets up a call to an R-type subroutine by inserting the parameters to the RCALL subroutine into the proper registers for the call to the R-type subroutine. The ADROF subroutine is used to obtain the address of a variable as required both for the RCALL subroutine and for other system subroutines such as GETFD.

The format of the declarations is as follows:

TYPE

refname = RECORD END;

REF

RCALL : refname;

fcn : refname;

FUNCTION ADROF(CONST subr : refname) : INTEGER; FORTRAN;

PROCEDURE RCALL(CONST subr : refname;

par1;par2;...;parn); FORTRAN;

The call is made in the following manner:

RCALL(ADROF(subr),r1,p1,...,r2,p2,...);

where “r1” is the number of registers to be set up on the call to “subr” and “p1,...” are the values to be inserted into the registers beginning with general register 0; “r2” is the number of registers to contain return values from “subr” and “p2,...” are the variables that will contain the returned values starting with general register 0. If the return codes are desired from the subroutine being called via RCALL, then FORTRANRC may be used.

The following example illustrates the use of RCALL and ADROF for a call to the GDINFO subroutine.

Program Test(Input,Output);

Type

Char4 = Packed Array [1..4] of Char;

Hlfwrd = Packed -32768..32767;

Byte = Packed 0..255;

Gdfrec = Packed Record Fdub : Integer;

Devtyp : Char4;

Inlen : Hlfwrd;

Outlen : Hlfwrd;

Use : Byte;

Device : Byte;

Sws1 : Byte;

Sws2 : Byte;

Mods : Integer;

Beglnr : Integer;

Prvlnr : Integer;

Endlnr : Integer;

Inclnr : Integer;

46 Pascal/JB: Calling Subroutines From Pascal/JB

Namptr : Integer;

Msgptr : Integer;

Iosave : Integer;

Lastrc : Integer;

Reglen : Hlfwrd;

Width : Hlfwrd;

Macid : Integer;

End;

Recptr = @ Gdfrec;

Refname = Record End;

Ref

GDINFO : Refname;

Var

Unit1 : Char4;

Unit2 : Char4;

Dumy : Integer;

Info : Gdfrec;

Infoptr : Recptr;

Function ADROF(Const Subr : Refname) : Integer; Fortran;

Procedure RCALL(Const Subr : Refname;

Const Gdnam : Integer;

Const Rnum1 : Integer;

Const Name1 : Char4;

Const Name2 : Char4;

Const Rnum2 : Integer;

Const Dummy : Integer;

Var Regn : Recptr); Fortran;

Begin

Unit1 := 'SCAR'; {Set I/O unit name}

Unit2 := 'DS ';

RCALL(ADROF(GDINFO),2,Unit1,Unit2,2,Dumy,Infoptr);

If FORTRANRC > 0 Then Begin

Writeln('Error return from GDINFO subroutine');

Return End;

Info := Infoptr@; {Copy GDINFO region into Info}

Writeln('Type = ',Info.Devtyp);

End.

In this example, the GDINFO subroutine is called by the RCALL subroutine. Two registers (general registers 0 and 1) are set up on the call to contain the eight-character logical I/O unit name. Two registers are also set up for the return. Register 1 will contain the address of the GDINFO information region; register 0 is not used, hence a dummy argument must be inserted into the RCALL parameter list. This example also illustrates the case where a system subroutine returns a pointer to an area of storage acquired by the subroutine itself. Hence the variable INFOPTR, which upon return will contain the address of the acquired storage, must be declared as a pointer variable. The statement following the subroutine call is then used to copy the contents of that storage into the Pascal record variable Info so that the individual items of GDINFO information can be accessed by the program. Note that the GDINF alternative entry to the GDINFO subroutine also could have been called; this would circumvent the problem of using pointer variables in the Pascal program.

Dans le document Pascal in MTS (Page 43-47)