PROGRAM MACMOD; { THIS PROGRAM CREATES A IMPLEMENTTATION MODULE FOR THE RT11 MODULA SYSTEM IT USES A LNK FILE CREATED BY THE COMPILER AND A SAV FILE WITH THE MACRO TO INCLUDE IN IT. AT THIS TIME THE NUMBER OF PROCEDURES AND THEIR LENGTHS IN WORDS WILL BE ENTERED to use this program 1) write a definition module for the subroutine(s) you want. 2) write a implementation module accessing the various variables in the subroutine. when this module is compiled and run thru DECLNK you will then know how to access the variables of the subroutine. 3) write the subroutine in position independent code!!! 4) macro and link the subroutine with base address 1000 (the default) 5) run macmod and answer the questions 6) rename the file (.dat) to (.lnk) 7) reverse assemble the (.lnk) module to check your work 8) if ok go to 99 9) rewrite your subroutine 10) go to 4 99) continue } LABEL 99; CONST HEADERLENGTH = 31; FSL = 14; TYPE FILESTRINGTYPE = ARRAY[1..FSL] OF CHAR; CARDINAL = 0..-1; VAR INP1, INP2, OUT :FILE OF CARDINAL; TOTAL, WORDCOUNT :CARDINAL; PROCEDURE GETFILE(VAR STRING:FILESTRINGTYPE); BEGIN (*$C .MCALL .GTLIN ; THIS PROG USES GTLIN WHICH MAY SWAP THE USR ; THEREFORE THE STACK IS PLACED AT 1000 SO THE PASCAL ; STACK CAN BE OVERLAYED BY THE USR ; CAUTION THIS PROCEDURE MAY NOT BE NESTED MOV SP,R1 ;SAVE STACK POINTER IN R1 MOV #^O654,SP ;GET SPACE FOR GETLINE ON LOW STACK MOV SP,R3 ;SAVE ADDRESS OF SPACE FOR GTLIN .LIST MEB .GTLIN R3 .NLIST MEB MOV R1,SP ;RESTORE PASCAL STACK MOV 2(SP),R1 ;GO PAST RETURN ADDRESS (NO STATIC LINK) MOV #7.,R4 ;SET UP LOOP COUNT 100$: MOV (R3)+,(R1)+ ;MOVE FILESPEC INTO USER SPACE SOB R4,100$ *) END; PROCEDURE OPENFILES; VAR I:INTEGER; FS:FILESTRINGTYPE; BEGIN WRITELN( 'ENTER NAME OF LNK FILE'); GETFILE( FS); RESET( INP1, FS, 'LNK', I); IF I < 0 THEN BEGIN WRITELN( 'FILE NOT FOUND'); GOTO 99 END; WRITELN( 'ENTER NAME OF SAV FILE'); GETFILE( FS); RESET( INP2, FS, 'SAV', I); IF I < 0 THEN BEGIN WRITELN( 'FILE NOT FOUND'); GOTO 99 END; WRITELN( 'ENTER NAME OF OUT FILE'); GETFILE( FS); I := -1; REWRITE( OUT, FS, 'DAT', I); IF I < 0 THEN BEGIN WRITELN( 'FILE NOT OPENED'); GOTO 99 END; END; PROCEDURE OUTCARD( C:CARDINAL); BEGIN IF WORDCOUNT = 255 THEN BEGIN OUT^ := WORDCOUNT; PUT( OUT); WORDCOUNT := 0; END; OUT^ := C; PUT( OUT); WORDCOUNT := SUCC( WORDCOUNT); END; PROCEDURE GETHEADER; { USE FACT THAT LAST WORD READ HAS CHECKSUM SO FAR. READ LNK DESCRIP} VAR I:INTEGER; BEGIN WORDCOUNT := 0; FOR I:= 1 TO HEADERLENGTH DO BEGIN TOTAL := INP1^; GET( INP1); OUTCARD( TOTAL); END; END; FUNCTION CTOI( F:FILESTRINGTYPE):INTEGER; VAR I, J, K:INTEGER; BEGIN FOR I := 1 TO FSL DO BEGIN J := I; IF F[ I] <>' ' THEN EXIT; END; K := 0; FOR I := J TO FSL DO BEGIN IF NOT (F[ I] IN ['0'..'9']) THEN EXIT; K := K*10+ (ORD( F[ I]) - ORD( '0')); END; CTOI := K; END; PROCEDURE GETOUTPUTCODE; VAR I:INTEGER; J:INTEGER; PROCNUM:INTEGER; PROCLENGTH :INTEGER; TEMP :CARDINAL; F :FILESTRINGTYPE; BEGIN FOR I := 1 TO 256 DO GET( INP2); { SKIP BLOCK 0 } WRITELN( 'ENTER NUMBER OF PROCEDURES TO READ'); GETFILE( F); PROCNUM := CTOI( F); WRITELN( 'NUMBER OF PROCEDURES', PROCNUM); FOR I := 1 TO PROCNUM DO BEGIN WRITELN( 'ENTER NUMBER OF BYTES OF PROC IN DECIMAL'); GETFILE( F); PROCLENGTH := CTOI( F); WRITELN( 'NUMBER OF BYTES', PROCLENGTH); OUTCARD( 4B); OUTCARD( I); TEMP := I; OUTCARD( 0); OUTCARD( PROCLENGTH); TOTAL := TOTAL + 4B + TEMP + PROCLENGTH; { FIX CHECKSUM } PROCLENGTH := PROCLENGTH DIV 2; { READ DATA BY WORD} FOR J := 1 TO PROCLENGTH DO BEGIN TEMP := INP2^; GET( INP2); OUTCARD( TEMP); TOTAL := TOTAL + TEMP; END; OUTCARD( TOTAL); END; OUTCARD( 22B); TOTAL := TOTAL + 22B; OUTCARD( TOTAL); END; PROCEDURE FINISH; VAR I:INTEGER; J:INTEGER; BEGIN J := WORDCOUNT; WRITELN( 'WORDCOUNT', J, J MOD 256); FOR I := SUCC( J MOD 256) TO 255 DO BEGIN OUT^ := 0; PUT( OUT); END; OUT^ := WORDCOUNT; PUT( OUT); CLOSE( OUT); END; BEGIN OPENFILES; GETHEADER; GETOUTPUTCODE; FINISH; WRITE('NORMAL '); 99: WRITELN( 'EXECUTION TERMINATION'); END.