!***COPYRIGHT (C) 1974, 1975, 1976, 1977 DIGITAL EQUIPMENT CORPORATION., MAYNARD, MASS.*** MODULE MPP(SREG = #17, FREG = #16, VREG = #15, !*** LAST MODIFIED BY CDO 21-JUN-76 MLIST,TIMER=EXTERNAL(SIX12),FSAVE)= BEGIN ! THIS MODULE CONTAINS THOSE ROUTINES REQUIRED TO HANDLE MPP GENERATIONS GLOBAL BIND MPP = 1; REQUIRE MGNMAC.BLI; REQ(MGNEXT); REQ(MGNMC2); EXTERNAL MOVE, LINK, UNLINK, COMPARE, GETNODEPTR, HASMPP, MAXSLOTS; OWN LASTMPP; COMMENT; ! ROUTINE PRINTMPPNAME ! ======= ============= ! OUTPUTS MPPNAME TO CONTROLLING TTY ROUTINE PRINTMPPNAME( MPPNAME ) = BEGIN TYPE( 'FOR [MPP ]'); OUTSA( .MPPNAME ); TYPE( '[:?M?J]' ); END; COMMENT; ! ROUTINE INMPP ! ======= ====== ! THIS ROUTINE ASKS FOR AND ACCEPTS A MPP NAME FROM THE USER ROUTINE INMPP(A)= BEGIN ! TYPE THE QUESTION IF ASKL( .A ) THEN RETURN 0; ! ACCEPT AN ALTERNATE LINE ANSWER ! IF THE LINE WAS EMPTY RETURN 0 IF NOT .ERRORFLG THEN GETNAME(ALINE,ACHAR); ! IF NO ERROR ACCEPTING THE LINE THEN GATHER A NAME IF NOT .ERRORFLG THEN TOOMUCHINPUT(); ! IF NOT END OF LINE THEN ERROR IF NOT .ERRORFLG THEN IF SUBQUEUES() OR .PERIODS NEQ 0 THEN ERROR( 18 ); ! IF STILL NO ERRORS, SEE IF THE USER ! PUT PERIODS IN THE MPP NAME IF .ERRORFLG THEN 0 ELSE 1 ! IF ERROR IN ANY PART, RETURN 0 ELSE 1 END; COMMENT; ! ROUTINE NUMMPPS ! ======= ========== ! THIS ROUTINE KILLS ALL MPP SPECS GLOBAL ROUTINE NUMMPPS = BEGIN REGISTER I, MPPADDR; MAP FORMAT MPPADDR; MPPADDR _ .MPPTAB; I _ -1; WHILE .MPPADDR NEQ 0 DO BEGIN MPPADDR[M0MPPNO] _ I _ .I + 1; MPPADDR _ .MPPADDR[M0FORE] END; LASTMPP _ .I END; COMMENT; ! ROUTINE CREATEMPP ! ======= ========== ! THIS ROUTINE STUFFS A NEW MPP IN THE MPPTAB ! INPUT POINTER TO MPPNAME ! OUTPUT POINTER TO MPP TABLE ENTRY ROUTINE CREATEMPP( MPPNAME ) = BEGIN REGISTER MPPADDR; MAP FORMAT MPPADDR; MPPADDR _ GMEM(M0SIZE); MPPADDR[M0LINKS] _ 0; MOVE( %FROM% .MPPNAME, %TO% MPPADDR[M0NAME], M0NAMELEN %WORDS%); LINK( %TO% MPPTAB, MPPADDR[M0LINKS]); .MPPADDR END; COMMENT; ! ROUTINE NULLMPPNAME ! ======= ============ ! RETURNS TRUE IF THE MPPNAME IS NULL ROUTINE NULLMPPNAME(LOC)= BEGIN ! RETURNS TRUE IF THE CONTENTS OF LOC IS NULL, ELSE FALSE RETURN IF ..LOC EQL 0 THEN TRUE ELSE FALSE END; FORWARD GETMPPADDR(1); COMMENT; ! ROUTINE MAKUMPP ! ======= ======== ! THIS ROUTINE MAKES A MPP TO ATTACH TO A NODE GLOBAL ROUTINE MAKUMPP( NODEPTR, QUESTION ) = BEGIN OWN MPPADDR; LABEL LOOP; MAP FORMAT MPPADDR; MAP FORMAT NODEPTR; LOOP: REPEAT ! UNTIL WE GET A GOOD ANSWER OR A LONE BEGIN IF INMPP( .QUESTION ) NEQ 0 THEN LEAVE LOOP ! GOT A GOOD ONE SO CONTINUE ELSE BEGIN IF .ERRORFLG THEN BEGIN ERROR( 75 ); !BAD MPP NAME WARN( 0 ); ERRORFLG _ 0 END ELSE IF EOL( ACHAR ) THEN RETURN 0 ! ONLY ? YES THEN RETURN END END; ! IF WE GOT A MPP NAME IF (MPPADDR _ GETMPPADDR( PRIM<36,7> )) EQL 0 THEN BEGIN MPPADDR _ CREATEMPP( PRIM<36,7> ); MPPADDR[M0TOBEDEFINED] _ TRUE END; ATTACH( %TO% MPPADDR[M0LISTPTRS], .NODEPTR, N0MPPOFFSETT ); .MPPADDR END; FORWARD ACCEPTMPP(1),MAKMPP(1); COMMENT; ! ROUTINE MAKEMPP ! ======= ======== ! GIVEN THE ADDRESS OF A MPPNAME, THIS ROUTINE CAUSE THE APPROPRIATE ! QUESTIONS TO BE ASKED TO GENERATE ONE OR MORE MPPS ( MORE IF ! THE MPP NAME WAS NULL) GLOBAL ROUTINE MAKEMPP(MPPNAME)= BEGIN REGISTER MPPADDR; MAP FORMAT MPPADDR; ERRORFLG _ 0; IF .ALLSWITCH THEN BEGIN MPPADDR _ .MPPTAB; WHILE .MPPADDR NEQ 0 DO BEGIN IF .MPPADDR[M0TOBEDEFINED] THEN BEGIN PRINTMPPNAME( MPPADDR[M0NAME] ); MAKMPP( .MPPADDR); END; MPPADDR _ .MPPADDR[M0FORE]; CRLF END; ZERO( .MPPNAME, .MPPNAME + M0NAMELEN ) END; IF SUBQUEUES() OR .PERIODS NEQ 0 THEN RETURN( ERROR( 18 ) ); ! PERIODS IN A MPP NAME ARE NO NO'S IF NULLMPPNAME(.MPPNAME) THEN ! IF NO MPP SPECIFIED BEGIN ! ASK THE USER FOR MPP NAMES REPEAT ! UNTIL HE INPUTS A BY BEGIN ! ITSELF IF INMPP( PAZ '[MPPNAME]?R(,?R)[: ??') EQL 0 THEN IF NOT .ERRORFLG THEN RETURN ELSE BEGIN ! IF THE ANSWER WAS UNACCEPTABLE ERROR( 75 ); ! TELL THE USER IT WAS BAD WARN( 0 ); ! AND HAVE HIM TRY AGAIN ERRORFLG _ 0; END ELSE ACCEPTMPP(PRIM<36,7>); ! IF OK NAME EXECUTE THE FUNCTION CRLF END END; ACCEPTMPP(.MPPNAME) ! IF A MPP WAS SPECIFIED, USE IT END; COMMENT; ! ROUTINE GETMPPADDR ! ======= =========== ! SEARCHES THE MPPTAB FOR THE MPPNAME CONTAINED AT THE CONTENTS OF MPPNAME ! IF FOUND, RETURNS THE ADDRESS OF THE MPP TABLE ENTRY ! OTHERWISE RETURNS 0 ROUTINE GETMPPADDR(MPPNAME) = BEGIN REGISTER MPPADDR; MAP FORMAT MPPADDR; IF TOOLONG(.MPPNAME,M0NAMESIZE, M0NAMELEN * 5) THEN BEGIN WARN( 5 ); TRUNCATE(.MPPNAME, M0NAMESIZE, M0NAMELEN * 5) END; IF ( MPPADDR _ .MPPTAB ) EQL 0 THEN RETURN 0; ! START AT THE BEGINNING ! WHILE THE NAME AT MPPNAME ISN'T THE NAME IN THE TABLE DO WHILE NOT COMPARE(.MPPNAME,MPPADDR[M0NAME],M0NAMELEN) DO ! IF END OF TABLE RETURN 0 IF (MPPADDR _ .MPPADDR[M0FORE]) EQL 0 THEN RETURN 0; .MPPADDR ! A MATCH! SO RETURN THE ADDRESS END; FORWARD MAKMPP(1), MODMPP(1); COMMENT; ! ROUTINE ACCEPTMPP ! ======= ========== ! THIS ROUTINE CREATES A MPP TABLE ENTRY IF ONE DOES NOT EXIST ! THEN CALLS MAKMPP TO ASK THE QUESTIONS TO FILL THE ENTRY ! IF THE MPP ALREADY EXISTS, THE USER IS ASKED HOW HE WANTS TO ! HANDLE IT ROUTINE ACCEPTMPP(MPPNAME)= BEGIN REGISTER MPPADDR; MAP FORMAT MPPADDR; PRINTMPPNAME( .MPPNAME ); ! SEE IF ALREADY DEFINED IF (MPPADDR _ GETMPPADDR(.MPPNAME)) EQL 0 THEN MPPADDR _ CREATEMPP( .MPPNAME ) ! MAKE A MPP TABLE ENTRY ELSE BEGIN IF NOT .MPPADDR[M0TOBEDEFINED] THEN BEGIN ASKSTR( '[MPP ALREADY EXISTS]?R(IGNORE, MODIFY, REPLACE?R)[: ??]', PLIT( ASCII 'REPLA', MAKMPP, ASCII 'MODIF', MODMPP, 0, IGNORE, ASCII 'IGNOR', IGNORE), .MPPADDR); RETURN END END; MAKMPP(.MPPADDR) END; COMMENT; !! !!! ROUTINE SETLOCK !!! ======= ======= !!! SETS THE LOCK BIT TO TRUE INDICATING LOCKING IS DESIRED !! !!ROUTINE SETLOCK( MPPADDR ) = !! BEGIN !! MAP FORMAT MPPADDR; !! !! MPPADDR[M0LOCK] _ TRUE !! !! END; !! !!COMMENT; !! !!! ROUTINE CLEARLOCK !!! ======= ========= !!! SETS THE LOCK BIT TO FALSE INDICATING LOCKING IS NOT DESIRED !! !!ROUTINE CLEARLOCK( MPPADDR ) = !! BEGIN !! MAP FORMAT MPPADDR; !! !! MPPADDR[M0LOCK] _ FALSE !! !! END; !! COMMENT; ! ROUTINE SETIMMORTAL ! ======= ======= ! SETS THE IMMORTAL BIT TO TRUE INDICATING IMMORTAL IS DESIRED ROUTINE SETIMMORTAL( MPPADDR ) = BEGIN MAP FORMAT MPPADDR; MPPADDR[M0IMMORTAL] _ TRUE END; COMMENT; ! ROUTINE CLEARIMMORTAL ! ======= ========= ! SETS THE IMMORTAL BIT TO FALSE INDICATING IMMORTAL IS NOT DESIRED ROUTINE CLEARIMMORTAL( MPPADDR ) = BEGIN MAP FORMAT MPPADDR; MPPADDR[M0IMMORTAL] _ FALSE END; FORWARD MAKEEGO(2); COMMENT; ! ROUTINE MAKMPP ! ======= ======= ! THIS ROUTINE ASKS THE QUESTIONS TO MAKE ONE (AND ONLY ONE) MPP ! AND RECORDS THE RESPONSES IN THE APPROPRIATE MPP TABLE ENTRY ROUTINE MAKMPP(MPPADDR)= BEGIN OWN SPECBLK[4]; MAP FORMAT MPPADDR; WHILE ASKFSPEC( '[FILE] DESIGNATION ?R(?R)[: ??]', SPECBLK) EQL CRONLY DO BEGIN ERROR( 76 ); WARN( 0 ); END; MAKEEGO( SPECBLK, .MPPADDR ); TYPE( '[BACKUPS]?R(, ?R)[:]' ); WHILE NOT (ASKFSPEC('[ ??]', SPECBLK) EQL CRONLY) DO BEGIN MAKEEGO( SPECBLK, .MPPADDR ) END; MPPADDR[M0MAX] _ ASKDNUM( '[MAX]IMUM[ COPIES] THAT CAN RUN?R(, ?R)[: ??]', DEFAULTOK, BIGNUMBER, 0, .MAXSLOTS); MPPADDR[M0MIN] _ ASKDNUM( '[MIN]IMUM[ COPIES] THAT MUST RUN?R(0, ?R)[: ??]', DEFAULTOK, 0, 0, .MPPADDR[ M0MAX ]); MPPADDR[M0INITIAL] _ ASKDNUM( '[COPIES] TO START[ INITIALLY]?R(0, ?R)[: ??]', DEFAULTOK, 0, 0, .MPPADDR[ M0MAX ]); MPPADDR[M0HPQ] _ ASKDNUM( '[HPQ] TO USE?R(,?R)[: ??]', DEFAULTOK, 0, 1, 15); !! ASKSTR('[LOCK] JOB IN CORE?R(NO,YES?R)[: ??]', !! PLIT( ASCII 'YES', SETLOCK, !! ASCII 'NO', CLEARLOCK, !! 0, CLEARLOCK), !! .MPPADDR); ASKSTR('CAN THIS [MPP ]BE [KILL(ABLE)]ED BY MCS?R(YES,NO?R)[: ??]', PLIT( ASCII 'YES', CLEARIMMORTAL, ASCII 'NO', SETIMMORTAL, 0, CLEARIMMORTAL), .MPPADDR); MPPADDR[M0TOBEDEFINED] _ FALSE END; COMMENT; ! ROUTINE MAKEEGO ! ======= ======== ! THIS ROUTINE GETS CORE FOR AN ALTEREGO, STORES THE FILE SPEC, AND ASKS ! FOR THE AMOUNT OF CORE REQUIRED BY THE PROGRAM. ROUTINE MAKEEGO( SPECBLK, MPPADDR ) = BEGIN REGISTER EGOPTR; MAP FORMAT MPPADDR; MAP FORMAT EGOPTR; MAP FORMAT SPECBLK; IF .SPECBLK[ SB0EXT ] NEQ 0 THEN BEGIN WARN(27); !EXTENSION IGNORED SPECBLK[SB0EXT] _ 0 ! AND FORCE TO ZERO END; EGOPTR _ GMEM( E0SIZE ); EGOPTR[E0EGOS] _ 0; LINK( %TO% MPPADDR[M0EGOS], .EGOPTR); MOVE( %FROM% .SPECBLK, %TO% EGOPTR[E0SPECBLK], SPECBLKLEN ); EGOPTR[E0CORE] _ ASKSIZE( '?I?I[CORE] TO START MPP WITH ?R(, ?R)[: ??]'); END; FORWARD DISMPP(1); COMMENT; ! ROUTINE DISPMPP ! ======= =========== ! THIS ROUTINE HANDLES THE INDIVIDUAL CASES OF DISPLAY MPP:... ! CASE 1: IF AN INDIVIDUAL MPP IS REQUESTED ( BY NAME ), DISMPP IS ! CALLED WITH THE ADDRESS OF THE MPP TABLE ENTRY ! CASE 2: IF /ALL WAS SPECIFIED, DISMPP IS CALLED FOR EACH ENTRY IN ! MPP TABLE ! CASE 3: IF NO NAME OR SWITCH WAS GIVEN, THE USER IS ASKED FOR THE ! NAMES OF THE MPPS TO BE DISPLAYED GLOBAL ROUTINE DISPMPP(MPPNAME)= BEGIN REGISTER MPPADDR; MAP FORMAT MPPADDR; IF SUBQUEUES() OR .PERIODS NEQ 0 THEN RETURN( ERROR( 18 ) ); ! PERIODS IN A MPP NAME ARE NO NO'S IF NULLMPPNAME(.MPPNAME) AND NOT .ALLSWITCH THEN BEGIN ! ASK THE USER FOR MPP NAMES REPEAT ! UNTIL HE INPUTS A BY BEGIN ! ITSELF IF INMPP( PAZ '[MPPNAME]?R(,?R)[: ??') EQL 0 THEN IF NOT .ERRORFLG THEN RETURN ELSE BEGIN ! IF THE ANSWER WAS UNACCEPTABLE ERROR( 75 ); ! TELL THE USER IT WAS BAD WARN( 0 ); ! AND HAVE HIM TRY AGAIN ERRORFLG _ 0; END ELSE IF (MPPADDR _ GETMPPADDR(PRIM)) EQL 0 THEN RETURN(ERROR(16)) ELSE DISMPP(.MPPADDR); CRLF END END; IF .ALLSWITCH THEN BEGIN MPPADDR _ .MPPTAB; WHILE .MPPADDR NEQ 0 DO BEGIN DISMPP( .MPPADDR); MPPADDR _ .MPPADDR[M0FORE] END; RETURN END; IF (MPPADDR _ GETMPPADDR(.MPPNAME)) EQL 0 THEN RETURN(ERROR(16)) ELSE DISMPP(.MPPADDR) END; FORWARD DMPPNAME,DMPPFILE,DMPPBACKUPS,DMPPMAX,DMPPMIN,DMPPINIT,DMPPHPQ,DMPPIMMORTAL; !!FORWARD DMPPLOCK; COMMENT; ! ROUTINE DISMPP ! ======= ======= ! THIS ROUTINE DISPLAYS THE MPP'S NAME, AND IF THE MPP IS UNDEFINED, ! THEN "NOT YET DEFINED..." IS DISPLAYED, OTHERWISE THE MPP PARAMETERS ! ARE DISPLAYED ROUTINE DISMPP(MPPADDR)= BEGIN MAP FORMAT MPPADDR; DMPPNAME(.MPPADDR); IF .MPPADDR[M0TOBEDEFINED] THEN BEGIN OUTPUT('NOT YET DEFINED, PLEASE MAKE OR MODIFY IT'); END ELSE BEGIN DMPPFILE( .MPPADDR ); DMPPBACKUPS( .MPPADDR ); DMPPMAX(.MPPADDR); DMPPMIN(.MPPADDR); DMPPINIT(.MPPADDR); DMPPHPQ(.MPPADDR); !! DMPPLOCK(.MPPADDR); DMPPIMMORTAL(.MPPADDR); END; OUTPUTCRLF END; COMMENT; ! ROUTINE DMPPNAME ! ======= ========= ! THIS ROUTINE DISPLAYS THE MPP NAME ROUTINE DMPPNAME(MPPADDR)= BEGIN MAP FORMAT MPPADDR; OUTPUT('MPPNAME: '); XOUTPUT(MPPADDR[M0NAME]); OUTPUTCRLF END; COMMENT; ! ROUTINE DMNAME ! ======= ========= ! THIS ROUTINE DISPLAYS THE MPP NAME WITHOUT LABEL GLOBAL ROUTINE DMNAME(MPPADDR)= BEGIN MAP FORMAT MPPADDR; XOUTPUT(MPPADDR[M0NAME]) END; FORWARD DEGO(1); COMMENT; ! ROUTINE DMPPFILE ! ======= ========= ! THIS ROUTINE DISPLAYS THE MPP'S PRIMARY FILE SPECIFICATION ROUTINE DMPPFILE(MPPADDR)= BEGIN REGISTER EGOPTR; MAP FORMAT EGOPTR; MAP FORMAT MPPADDR; EGOPTR _ .MPPADDR[M0FEGO]; OUTPUT('FILE DESIGNATION: '); DEGO( .EGOPTR ); END; ! ROUTINE DMPPBACKUPS ! ======= ========= ! THIS ROUTINE DISPLAYS THE MPP'S BACKUPS' SPECIFICATIONS ROUTINE DMPPBACKUPS(MPPADDR)= BEGIN REGISTER EGOPTR; MAP FORMAT EGOPTR; MAP FORMAT MPPADDR; EGOPTR _ .MPPADDR[M0FEGO]; OUTPUT('BACKUPS: '); IF .EGOPTR[E0FORE] EQL 0 THEN OUTPUT('?M?J') ELSE WHILE ( EGOPTR _ .EGOPTR[E0FORE] ) NEQ 0 DO BEGIN DEGO( .EGOPTR ); IF .EGOPTR[E0FORE] NEQ 0 THEN OUTPUT( ' ' ) END END; COMMENT; ! ROUTINE DEGO ! ======= ==== ! THIS ROUTINE DISPLAYS THE FILE SPEC OF AN ALTEREGO, GIVEN A POINTER ! TO THE ALTEREGO ROUTINE DEGO( EGOPTR ) = BEGIN MAP FORMAT EGOPTR; OUTPUTFSPEC( EGOPTR[E0SPECBLK] ); OUTPUT('?I( CORE: '); IF .EGOPTR[E0KCORE] EQL 0 THEN OUTPUT( ' ') ELSE BEGIN OUTPUTD( .EGOPTR[E0KCORE] ); OUTPUTC( IF .EGOPTR[E0KFLAG] THEN "K" ELSE "P" ); END; OUTPUTC( ")" ); OUTPUTCRLF END; COMMENT; ! ROUTINE DMPPMAX ! ======= ======== ! THIS ROUTINE DISPLAYS THE MAXIMUM NUMBER OF COPIES OF THE MPP TO RUN ROUTINE DMPPMAX(MPPADDR)= BEGIN MAP FORMAT MPPADDR; OUTPUT('MAXIMUM COPIES TO RUN: '); IF .MPPADDR[M0MAX] EQL BIGNUMBER THEN OUTPUT('') ELSE OUTPUTD( .MPPADDR[M0MAX] ); OUTPUTCRLF END; COMMENT; ! ROUTINE DMPPMIN ! ======= ======== ! THIS ROUTINE DISPLAYS THE MINIMUM NUMBER OF COPIES OF THE MPP TO RUN ROUTINE DMPPMIN(MPPADDR)= BEGIN MAP FORMAT MPPADDR; OUTPUT('MINIMUM COPIES TO RUN: '); OUTPUTD( .MPPADDR[M0MIN] ); OUTPUTCRLF END; COMMENT; ! ROUTINE DMPPINIT ! ======= ======== ! THIS ROUTINE DISPLAYS THE NUMBER OF COPIES OF THE MPP TO START INITIALLY ROUTINE DMPPINIT(MPPADDR)= BEGIN MAP FORMAT MPPADDR; OUTPUT('COPIES TO START INITIALLY: '); OUTPUTD( .MPPADDR[M0INITIAL] ); OUTPUTCRLF END; COMMENT; ! ROUTINE DMPPHPQ ! ======= ======= ! THIS ROUTINE DISPLAYS THE HPQ THAT THE MPP IS TO BE RUN IN ROUTINE DMPPHPQ( MPPADDR ) = BEGIN MAP FORMAT MPPADDR; OUTPUT('HPQ TO BE USED: '); IF .MPPADDR[M0HPQ] EQL 0 THEN OUTPUT('') ELSE OUTPUTD( .MPPADDR[M0HPQ] ); OUTPUTCRLF END; COMMENT; !!! ROUTINE DMPPLOCK !!! ======= ========= !!! THIS ROUTINE DISPLAYS THE LOCK CAPABILITY OF THE MPP !! !!ROUTINE DMPPLOCK(MPPADDR)= !! BEGIN !! MAP FORMAT MPPADDR; !! OUTPUT('LOCK JOB IN CORE: '); !! XOUTPUT(IF .MPPADDR[M0LOCK] THEN PLIT ASCII 'YES' ELSE PLIT ASCIZ 'NO'); !! OUTPUTCRLF !! END; COMMENT; ! ROUTINE DMPPIMMORTAL ! ======= ========= ! THIS ROUTINE DISPLAYS THE IMMORTAL CAPABILITY OF THE MPP ROUTINE DMPPIMMORTAL(MPPADDR)= BEGIN MAP FORMAT MPPADDR; OUTPUT('JOB KILLABLE BY MCS: '); XOUTPUT(IF NOT .MPPADDR[M0IMMORTAL] THEN PLIT ASCII 'YES' ELSE PLIT ASCIZ 'NO'); OUTPUTCRLF END; ! ROUTINE MODIMPP ! ======= =========== ! THIS ROUTINE HANDLES THE INDIVIDUAL CASES OF MODIFY MPP:... ! CASE 1: IF AN INDIVIDUAL MPP IS REQUESTED ( BY NAME ), MODMPP IS ! CALLED WITH THE ADDRESS OF THE MPP TABLE ENTRY ! CASE 2: IF /ALL WAS SPECIFIED, MODMPP IS CALLED FOR EACH ENTRY IN ! MPP TABLE ! CASE 3: IF NO NAME OR SWITCH WAS GIVEN, THE USER IS ASKED FOR THE ! NAMES OF THE MPPS TO BE MODIFIED GLOBAL ROUTINE MODIMPP(MPPNAME)= BEGIN REGISTER MPPADDR; MAP FORMAT MPPADDR; IF SUBQUEUES() OR .PERIODS NEQ 0 THEN RETURN( ERROR( 18 ) ); ! PERIODS IN A MPP NAME ARE NO NO'S IF NULLMPPNAME(.MPPNAME) AND NOT .ALLSWITCH THEN BEGIN ! ASK THE USER FOR MPP NAMES REPEAT ! UNTIL HE INPUTS A BY BEGIN ! ITSELF IF INMPP( PAZ '[MPPNAME]?R(,?R)[: ??') EQL 0 THEN IF NOT .ERRORFLG THEN RETURN ELSE BEGIN ! IF THE ANSWER WAS UNACCEPTABLE ERROR( 75 ); ! TELL THE USER IT WAS BAD WARN( 0 ); ! AND HAVE HIM TRY AGAIN ERRORFLG _ 0; END ELSE IF (MPPADDR _ GETMPPADDR(PRIM)) EQL 0 THEN RETURN(ERROR(16)) ELSE MODMPP(.MPPADDR); CRLF END END; IF .ALLSWITCH THEN BEGIN MPPADDR _ .MPPTAB; WHILE .MPPADDR NEQ 0 DO BEGIN MODMPP( .MPPADDR); MPPADDR _ .MPPADDR[M0FORE] END; RETURN END; IF (MPPADDR _ GETMPPADDR(.MPPNAME)) EQL 0 THEN RETURN(ERROR(16)) ELSE MODMPP(.MPPADDR); END; FORWARD MMPPNAME,MMPPFILE,MMPPBACKUPS,MMPPMAX,MMPPMIN, MMPPINITIAL,MMPPHPQ,MMPPIMMORTAL,MMPPALL,TELLMPPCHANGES; !!FORWARD MMPPLOCK; COMMENT; ! ROUTINE MODMPP ! ======= ======= ! THIS ROUTINE TYPES THE NAME OF THE MPP TO BE MODIFIED, AND THEN ! ASKS FOR THE CHANGES TO BE MADE. MODMPP DOES ONLY ONE MPP AT A ! TIME. ROUTINE MODMPP(MPPADDR)= BEGIN OWN DONE; MAP FORMAT MPPADDR; %LOCAL% ROUTINE SETDONE = DONE _ TRUE; PRINTMPPNAME( MPPADDR[M0NAME] ); ! TYPE THE NAME OF THE MPP TO BE MODIFIED IF .MPPADDR[M0TOBEDEFINED] THEN ! IF UNDEFINED THEN BEGIN MAKMPP(.MPPADDR) ! MAKE IT END ELSE BEGIN DONE _ FALSE; WHILE NOT .DONE DO ! OTHERWISE, UNTIL THE USER GIVES US A LONE DO BEGIN ASKSTR( '[CHANGE: ??]', ! ASK WHAT CHANGES PLIT( ASCII '??', TELLMPPCHANGES, ASCII 'NAME', MMPPNAME, ASCII 'FILE', MMPPFILE, ASCII 'BACKU', MMPPBACKUPS, ASCII 'MAX', MMPPMAX, ASCII 'MIN', MMPPMIN, ASCII 'INITI', MMPPINITIAL, ASCII 'HPQ', MMPPHPQ, !! ASCII 'LOCK', MMPPLOCK, ASCII 'KILLA', MMPPIMMORTAL, ASCII 'ALL', MMPPALL, 0, SETDONE), .MPPADDR); CRLF END END END; COMMENT; ! ROUTINE TELLMPPCHANGES ! ======= =============== ! THIS ROUTINE TELLS ( WITH LOTS OF WIND ) WHAT CHANGES CAN BE MADE ON ! AN MPP ROUTINE TELLMPPCHANGES = BEGIN TYPE( 'TYPE [NAME] TO CHANGE THE NAME OF THE MPP[,]?J ?MTYPE [FILE] TO CHANGE THE FILE SPECIFICATION OF THE MPP[,]?J ?MTYPE [BACKUPS] TO CHANGE THE BACKUPS TO THE MPP[,]?J ?MTYPE [MAX] TO CHANGE THE MAXIMUM NUMBER OF COPIES OF THE MPP TO RUN[,]?J ?MTYPE [MIN] TO CHANGE THE MINIMUM NUMBER OF COPIES OF THE MPP TO RUN[,]?J ?MTYPE [INITIAL] TO CHANGE THE NUMBER OF COPIES OF THE MPP TO START INITIALLY[,]?J ?MTYPE [HPQ] TO CHANGE THE HPQ TO RUN THE MPP IN[,]?M?J' ); !! TYPE( 'TYPE [LOCK] TO CHANGE THE LOCKING ABILITY OF THE MPP[,]?M?J' ); TYPE( 'TYPE [KILLABLE] TO CHANGE THE KILLABILITY OF THE MPP[,]?J ?MTYPE [ALL] TO CHANGE ALL OF THE ABOVE[,]?J ?MTYPE A CARRIAGE RETURN TO FINISH CHANGING THIS MPP[(?R( WHEN DONE?R))]'); CRLF; END; COMMENT; ! ROUTINE MMPPALL ! ======= ======== ! THIS ROUTINE ASKS ALL THE QUESTIONS TO CHANGE AN MPP ROUTINE MMPPALL(MPPADDR) = BEGIN MMPPNAME( .MPPADDR); MMPPFILE( .MPPADDR); MMPPBACKUPS( .MPPADDR); MMPPMAX( .MPPADDR); MMPPMIN( .MPPADDR); MMPPINITIAL( .MPPADDR); MMPPHPQ( .MPPADDR); !! MMPPLOCK( .MPPADDR); MMPPIMMORTAL( .MPPADDR) END; COMMENT; ! ROUTINE MMPPNAME ! ======= ========= ! THIS ROUTINE ASKS THE QUESTION TO CHANGE AN MPP'S NAME ROUTINE MMPPNAME(MPPADDR)= BEGIN MAP FORMAT MPPADDR; LABEL LOOP; IF .SHOW THEN DMPPNAME(.MPPADDR); LOOP: REPEAT BEGIN IF INMPP( PAZ 'NEW [MPPNAME]?R(,?R)[: ??]') EQL 0 THEN BEGIN IF .ERRORFLG THEN BEGIN ERROR ( 75 ); WARN ( 0 ); ERRORFLG _ 0 END ELSE RETURN END ELSE LEAVE LOOP; END; IF GETMPPADDR(PRIM) NEQ 0 THEN RETURN (ERROR(17)); MOVE(PRIM, MPPADDR[M0NAME], M0NAMELEN) END; COMMENT; ! ROUTINE MMPPFILE ! ======= ========= ! THIS ROUTINE ASKS THE QUESTIONS NECESSARY TO CHANGE THE FILE ! SPECIFICATION OF THE MPP ROUTINE MMPPFILE(MPPADDR)= BEGIN OWN SPECBLK[ SPECBLKLEN]; REGISTER OLDCORE, EGOPTR; MAP FORMAT EGOPTR; MAP FORMAT MPPADDR; EGOPTR _ .MPPADDR[M0FEGO]; OLDCORE _ .EGOPTR[E0CORE]; IF .SHOW THEN DMPPFILE(.MPPADDR); IF ( ASKFSPEC( '[NEW FILE] DESIGNATION ?R(,?R)[: ??]', SPECBLK) ) NEQ CRONLY THEN MOVE( %FROM% SPECBLK, %TO% EGOPTR[E0SPECBLK], SPECBLKLEN ); EGOPTR[ E0CORE ] _ NEWASKSIZE( '[NEW CORE]?R(, , "" ?R)[: ??]', PLIT( 0, ASCIZ '' ), .OLDCORE ); END; COMMENT; ! ROUTINE MMPPBACKUPS ! ======= ======== ! THIS ROUTINE ASKS THE QUESTION ABOUT CHANGING THE BACKUPS TO THE MPP ROUTINE MMPPBACKUPS(MPPADDR)= BEGIN REGISTER EGOPTR, NEXTEGO; OWN SPECBLK[SPECBLKLEN]; MAP FORMAT EGOPTR; MAP FORMAT MPPADDR; IF .SHOW THEN DMPPBACKUPS(.MPPADDR); IF ( NEWASKFSPEC( '[NEW BACKUPS]?R(,"",?R)[: ??]', SPECBLK, PLIT( PLIT( SPECBLKLEN : 0 ), ASCIZ '' ), EGOPTR[ E0SPECBLK ] ) ) EQL CRONLY THEN RETURN %?? CHANGE CORE ONLY%; ! ELSE ! EGOPTR _ .MPPADDR[M0FEGO]; EGOPTR _ .EGOPTR[E0FORE]; ! SKIP THE PRIMARY EGO WHILE .EGOPTR NEQ 0 DO ! THE DELETE THE ALTEREGOS BEGIN NEXTEGO _ .EGOPTR[E0FORE]; UNLINK( %FROM% MPPADDR[M0EGOS], .EGOPTR ); PMEM( .EGOPTR, E0SIZE ); EGOPTR _ .NEXTEGO END; IF NULL( SPECBLK, SPECBLKLEN ) THEN RETURN; ! IF THEN DONE MAKEEGO( SPECBLK, .MPPADDR ); WHILE NOT (ASKFSPEC('[ ??]', SPECBLK) EQL CRONLY) DO BEGIN MAKEEGO( SPECBLK, .MPPADDR ) END END; COMMENT; ! ROUTINE MMPPMAX ! ======= ========= ! THIS ROUTINE ASKS THE QUESTION ABOUT CHANGING THE MAXIMUM COPIES ! OF THE MPP TO RUN ROUTINE MMPPMAX(MPPADDR)= BEGIN MAP FORMAT MPPADDR; IF .SHOW THEN DMPPMAX(.MPPADDR); MPPADDR[M0MAX] _ NEWASKDNUM( 'NEW [MAX]IMUM[ COPIES] THAT CAN RUN?R(,"", ?R)[: ??]', DEFAULTOK, .MPPADDR[ M0MAX ], PLIT( BIGNUMBER, ASCIZ '' ), 0, .MAXSLOTS); END; COMMENT; ! ROUTINE MMPPMIN ! ======= ========= ! THIS ROUTINE ASKS THE QUESTION TO CHANGE THE MINIMUM NUMBER OF COPIES OF THE MPP TO RUN ROUTINE MMPPMIN(MPPADDR)= BEGIN REGISTER CHANGE; MAP FORMAT MPPADDR; IF .SHOW THEN DMPPMIN(.MPPADDR); IF (CHANGE _ ASKDNUM( 'NEW [MIN]IMUM[ COPIES] THAT MUST RUN?R(,?R)[: ??]', DEFAULTOK, -1, 0, .MPPADDR[ M0MAX ]) ) NEQ -1 THEN MPPADDR[M0MIN] _ .CHANGE; END; COMMENT; ! ROUTINE MMPPINITIAL ! ======= ========= ! THIS ROUTINE ASKS THE QUESTION TO CHANGE THE NUMBER OF COPIES OF THE MPP TO START INITIALLY ROUTINE MMPPINITIAL(MPPADDR)= BEGIN REGISTER CHANGE; MAP FORMAT MPPADDR; IF .SHOW THEN DMPPINIT(.MPPADDR); IF (CHANGE _ ASKDNUM( 'NEW [COPIES] TO START[ INITIALLY]?R(,?R)[: ??]', DEFAULTOK, -1, 0, .MPPADDR[ M0MAX ]) ) NEQ -1 THEN MPPADDR[M0INITIAL] _ .CHANGE; END; COMMENT; ! ROUTINE MMPPHPQ ! ======= ========= ! THIS ROUTINE ASKS THE QUESTION TO CHANGE THE HPQ TO RUN THE MPP IN ROUTINE MMPPHPQ(MPPADDR)= BEGIN MAP FORMAT MPPADDR; IF .SHOW THEN DMPPHPQ(.MPPADDR); MPPADDR[ M0HPQ ] _ NEWASKDNUM( 'NEW [HPQ] TO USE?R(,"",?R)[: ??]', DEFAULTOK, .MPPADDR[ M0HPQ ], PLIT( 0, ASCIZ '' ), 1, 15); END; COMMENT; !!! ROUTINE MMPPLOCK !!! ======= ========= !!! THIS ROUTINE ASKS THE QUESTION ABOUT CHANGING THE LOCK CAPABILITY !!! OF THE MPP !! !!ROUTINE MMPPLOCK(MPPADDR)= !! BEGIN !! IF .SHOW THEN DMPPLOCK(.MPPADDR); !! ASKSTR('NEW [LOCK] JOB IN CORE?R(,NO,YES?R)[: ??]', !! PLIT( ASCII 'YES', SETLOCK, !! ASCII 'NO', CLEARLOCK, !! 0, IGNORE), !! .MPPADDR); !! !! END; COMMENT; ! ROUTINE MMPPIMMORTAL ! ======= ========= ! THIS ROUTINE ASKS THE QUESTION ABOUT CHANGING THE IMMORTAL CAPABILITY ! OF THE MPP ROUTINE MMPPIMMORTAL(MPPADDR)= BEGIN IF .SHOW THEN DMPPIMMORTAL(.MPPADDR); ASKSTR('IS THE MPP NOW [KILLABLE] BY MCS?R(,NO,YES?R)[: ??]', PLIT( ASCII 'YES', CLEARIMMORTAL, ASCII 'NO', SETIMMORTAL, 0, IGNORE), .MPPADDR); END; FORWARD DELMPP(1),KILLMPPS(); COMMENT; ! ROUTINE DELEMPP ! ======= =========== ! THIS ROUTINE HANDLES THE INDIVIDUAL CASES OF DELETE MPP:... ! CASE 1: IF AN INDIVIDUAL MPP IS REQUESTED ( BY NAME ), DELMPP IS ! CALLED WITH THE ADDRESS OF THE MPP TABLE ENTRY ! CASE 2: IF /ALL WAS SPECIFIED, DELMPP IS CALLED FOR EACH ENTRY IN ! MPP TABLE ! CASE 3: IF NO NAME OR SWITCH WAS GIVEN, THE USER IS ASKED FOR THE ! NAMES OF THE MPPS TO BE DELETED GLOBAL ROUTINE DELEMPP(MPPNAME)= BEGIN REGISTER MPPADDR; MAP FORMAT MPPADDR; IF SUBQUEUES() OR .PERIODS NEQ 0 THEN RETURN( ERROR( 18 ) ); ! PERIODS IN A MPP NAME ARE NO NO'S IF NULLMPPNAME(.MPPNAME) AND NOT .ALLSWITCH THEN BEGIN ! ASK THE USER FOR MPP NAMES REPEAT ! UNTIL HE INPUTS A BY BEGIN ! ITSELF IF INMPP( PAZ '[MPPNAME]?R(,?R)[: ??') EQL 0 THEN IF NOT .ERRORFLG THEN RETURN ELSE BEGIN ! IF THE ANSWER WAS UNACCEPTABLE ERROR( 75 ); ! TELL THE USER IT WAS BAD WARN( 0 ); ! AND HAVE HIM TRY AGAIN ERRORFLG _ 0; END ELSE IF (MPPADDR _ GETMPPADDR(PRIM)) EQL 0 THEN RETURN(ERROR(16)) ELSE DELMPP(.MPPADDR); CRLF END END; IF .DELTYPEFLAG THEN TYPE( 'MPPS DELETED[?M?J]'); IF .ALLSWITCH THEN BEGIN IF NOT(CONFIRMED()) THEN RETURN; KILLMPPS(); RETURN END; IF (MPPADDR _ GETMPPADDR(.MPPNAME)) EQL 0 THEN RETURN(ERROR(16)) ELSE DELMPP(.MPPADDR); END; COMMENT; ! ROUTINE KILLMPPS ! ======= ========== ! THIS ROUTINE KILLS ALL MPP SPECS GLOBAL ROUTINE KILLMPPS = BEGIN REGISTER MPPADDR; MAP FORMAT MPPADDR; MPPADDR _ .MPPTAB; WHILE .MPPADDR NEQ 0 DO MPPADDR _ DELMPP(.MPPADDR) END; COMMENT; ! ROUTINE DELMPP ! ======= ======= ! THIS ROUTINE DELETES THE MPP SPECIFIED FROM THE MPP TABLE ! RETURNS THE ADDRESS OF THE NEXT MPP IN THE MPP TABLE GLOBAL ROUTINE DELMPP(MPPADDR)= BEGIN OWN NEXT; REGISTER NEXTNODE, NODEPTR, EGOPTR, NEXTEGO; MAP FORMAT EGOPTR; MAP FORMAT MPPADDR; MAP FORMAT NODEPTR; XTYPE( MPPADDR[M0NAME] ); ! TYPE THE NAME OF THE MPP DELETED, IF MSGLEVEL EQL LONG TYPECRLF; NEXT _ .MPPADDR[M0FORE]; ! ZAP ALTEREGOS EGOPTR _ .MPPADDR[M0FEGO]; WHILE .EGOPTR NEQ 0 DO BEGIN NEXTEGO _ .EGOPTR[E0FORE]; PMEM( .EGOPTR, E0SIZE ); EGOPTR _ .NEXTEGO END; NOTE - HOW DO WE WANT TO HANDLE POINTERS IN THE TREE? NOW I DELETE THEM IF .MPPADDR[M0LISTPTRS] NEQ 0 THEN ! DELETE THE POINTERS TO THIS MPP IN THE TREE BEGIN NODEPTR _ .MPPADDR[M0FLIST]; ! GET FIRST NODE ADDR WHILE .NODEPTR NEQ 0 DO BEGIN NODEPTR[N0MPPPTR] _ 0; NEXTNODE _ .NODEPTR[N0MPPFORE]; NODEPTR[N0MPPLINKS] _ 0; NODEPTR _ .NEXTNODE END; MPPADDR[M0LISTPTRS] _ 0 END; UNLINK(%FROM% MPPTAB, .MPPADDR); PMEM(.MPPADDR,M0SIZE); .NEXT END; FORWARD WCMPPNAME(1), OUTPUTMPPNO, OUTPUTMPPEGO, OUTPUTMM, OUTPUTMPR; COMMENT; ! ROUTINE WCMPP ! ======= ====== ! THIS ROUTINE WRITES THE MPP SECTION OF THE COMPILE FILE GLOBAL ROUTINE WCMPP= BEGIN ! IT IS ASSUMED THAT THE MPPS AND LEAVES HAVE BEEN NUMBERED ! THEN FOR EACH MPP REGISTER MPR, J, THISEGO, MPPADDR; MAP FORMAT MPPADDR; %LOCAL% ROUTINE OUTPUTPAIR( WHICH ) = BEGIN OUTPUT( ' XWD ' ); OUTPUTMPPNO( .WHICH ); OUTPUTCOMMA; OUTPUTMPPNO( .WHICH ); OUTPUTCRLF END; OUTPUT( '?L SUBTTL MPPS?M?J?M?J' ); OUTPUT('EXTERNAL SON,SOFF,DMR,DCR,ERR?M?J'); OUTPUT( '?M?JMPPTAB::?M?J' ); INCR I FROM 0 TO .LASTMPP DO OUTPUTPAIR( .I ); OUTPUT( ' M.ERR=.-MPPTAB?M?J' ); MPR _ .LASTMPP + 1; OUTPUTPAIR( .MPR ); OUTPUT( ' M.SON=.-MPPTAB?M?J' ); MPR _ .MPR + 1; OUTPUTPAIR( .MPR ); OUTPUT( ' M.SOFF=.-MPPTAB?M?J' ); MPR _ .MPR + 1; OUTPUTPAIR( .MPR ); OUTPUT( ' M.RDM=.-MPPTAB?M?J' ); MPR _ .MPR + 1; OUTPUTPAIR( .MPR ); OUTPUT( ' M.RDMC=.-MPPTAB?M?J' ); MPR _ .MPR + 1; OUTPUTPAIR( .MPR ); OUTPUT( '?M?JFMPPS==: 10?M?J?IBLOCK FMPPS?M?J?M?JMPPS==:' ); OUTPUTD( .MPR + 1 ); OUTPUTCRLF; OUTPUTCRLF; MPPADDR _ .MPPTAB; J _ 0; INCR I FROM 0 TO .LASTMPP DO BEGIN THISEGO _ .MPPADDR[M0FEGO]; WHILE .THISEGO NEQ 0 DO BEGIN THISEGO _ OUTPUTMPPEGO( .I, .J, .THISEGO, .MPPADDR ); J _ .J + 1 END; OUTPUTCRLF; J _ 0; MPPADDR _ .MPPADDR[M0FORE] END; OUTPUTCRLF; MPR _ .LASTMPP + 1; OUTPUTMPR( .MPR, PAZ 'ERR' ); MPR _ .MPR + 1; OUTPUTMPR( .MPR, PAZ 'SON' ); MPR _ .MPR + 1; OUTPUTMPR( .MPR, PAZ 'SOFF' ); MPR _ .MPR + 1; OUTPUTMPR( .MPR, PAZ 'DMR' ); MPR _ .MPR + 1; OUTPUTMPR( .MPR, PAZ 'DCR' ); END; COMMENT; ! ROUTINE WCMPPNAME ! ======= ======== ! THIS ROUTINE WRITES THE MPP NAME TO THE COMPILE FILE ROUTINE WCMPPNAME(MPPADDR)= BEGIN MAP FORMAT MPPADDR; XPUT(MPPADDR[M0NAME]) END; COMMENT; ! ROUTINE WCMPPNO ! ======= ======== ! THIS ROUTINE WRITES THE MPP NAME TO THE COMPILE FILE ROUTINE WCMPPNO( MPPADDR ) = BEGIN MAP FORMAT MPPADDR; OUTPUTMPPNO( .MPPADDR[M0MPPNO] ) END; COMMENT; ! ROUTINE WCMPPNUMBER ! ======= ======== ! THIS ROUTINE WRITES THE MPP NUMBER TO THE COMPILE FILE GLOBAL ROUTINE WCMPPNUMBER( MPPADDR ) = BEGIN MAP FORMAT MPPADDR; OUTPUTD( .MPPADDR[M0MPPNO] ) END; COMMENT; ! ROUTINE OUTPUTMPPNO ! ======= =========== ! THIS ROUTINE WRITES AN MPP NAME OF THE FORM "M"NUMBER.0 ROUTINE OUTPUTMPPNO( MAJOR ) = BEGIN OUTPUTMM( .MAJOR, 0 ) END; COMMENT; ! ROUTINE OUTPUTMM ! ======= ======== ! THIS ROUTINE WRITES AN MPPNAME OF THE FORM: "M"NUMBER1.NUMBER2 ROUTINE OUTPUTMM( MAJOR, MINOR ) = BEGIN OUTPUTC( "M" ); OUTPUTD( .MAJOR ); OUTPUTC( "." ); OUTPUTD( .MINOR ); END; COMMENT; ! ROUTINE OUTPUTMPPEGO ! ======= ============ ! THIS ROUTINE WRITES AN MPP MACRO CALL FOR AN EGO AND RETURNS ! A POINTER TO THE NEXT EGO ROUTINE OUTPUTMPPEGO( MAJOR, MINOR, EGO, MPPADDR ) = BEGIN MAP FORMAT EGO; MAP FORMAT MPPADDR; OUTPUTMM( .MAJOR, .MINOR ); OUTPUT( ': %MPP(' ); OUTPUTD( .MAJOR ); OUTPUTCOMMA; IF .EGO[E0FORE] NEQ 0 THEN OUTPUTMM( .MAJOR, .MINOR + 1) ELSE OUTPUTC( "0" ); OUTPUTCOMMA; IF .EGO[ E0DEVICE ] EQL 0 THEN OUTPUT( 'DSK' ) ELSE OUTPUTSWORD( .EGO[E0DEVICE] ); OUTPUTCOMMA; OUTPUTSWORD( .EGO[E0FILENAME] ); OUTPUTCOMMA; OUTPUT( '<^O' ); OUTPUTO( .EGO[E0PROJ] ); OUTPUT( ', ^O' ); OUTPUTO( .EGO[E0PROG] ); OUTPUTC( ">" ); OUTPUTCOMMA; OUTPUTD( IF .EGO[E0KFLAG] THEN .EGO[E0KCORE] * 2 ELSE .EGO[E0KCORE] ); OUTPUTCOMMA; OUTPUTD( .MPPADDR[M0MIN] ); OUTPUTCOMMA; OUTPUTD( .MPPADDR[M0MAX] ); OUTPUTCOMMA; OUTPUTD( .MPPADDR[M0INITIAL] ); OUTPUTCOMMA; OUTPUTD( .MPPADDR[M0HPQ] ); OUTPUTCOMMA; OUTPUTB( .MPPADDR[M0LOCK] ); OUTPUTCOMMA; OUTPUTB( FALSE ); ! NOT LOCAL OUTPUTCOMMA; OUTPUTB( .MPPADDR[M0IMMORTAL] ); OUTPUT( ')?M?J' ); .EGO[E0FORE] END; COMMENT; ! ROUTINE OUTPUTMPR ! ======= ============ ! THIS ROUTINE WRITES AN MPP MACRO CALL FOR AN MPR ROUTINE OUTPUTMPR( MAJOR, MPR ) = BEGIN OUTPUTMM( .MAJOR, 0 ); OUTPUT( ': %MPP(' ); OUTPUTD( .MAJOR ); OUTPUTCOMMA; OUTPUT( '0,COR,' ); XOUTPUT( .MPR ); OUTPUTCOMMA; OUTPUT( '<0,0>,0,0,0,0,0,0,TRUE,TRUE)?M?J' ); END; FORWARD MPPATTACH(1); COMMENT; ! ROUTINE WHATMPPS ! ======= ========= ! THIS ROUTINE CHECKS THE MPP TABLE FOR UNDEFINED MPPS AND MPPS ! WHICH DON'T BELONG TO LEAVES ! WHATMPPS RETURNS GOOD IF EVERYTHING IS OK, ELSE BAD GLOBAL ROUTINE WHATMPPS(TELL)= BEGIN ! IF TELL THEN ONLY TELL THE USER WHAT IS UNDEFINED, ELSE REQUEST UNDEFINED INFO !TWO POSSIBLE PROBLEMS ! 1. IF MPP TOBEDEFINED FLAG IS ON ! 2. IF THE MPP DOES NOT BELONG TO A LEAF REGISTER NEXT, STATUS, MPPADDR; MAP FORMAT MPPADDR; STATUS _ GOOD; IF ( MPPADDR _ .MPPTAB ) EQL 0 THEN RETURN GOOD; ! IF THERE ARN'T ANY THEN THEY MUST BE GOOD! IF .TELL THEN BEGIN DO BEGIN IF .MPPADDR[M0TOBEDEFINED] THEN BEGIN ERROR( 49 ); OUTSA(MPPADDR[M0NAME]); TYPE('[ TO BE DEFINED?M?J]'); STATUS _ BAD END ELSE BEGIN IF .MPPADDR[M0LISTPTRS] EQL 0 THEN BEGIN WARN( 28 ); OUTSA(MPPADDR[M0NAME]); TYPE('[ HAS NO NODE ASSOCIATED WITH IT?M?J]' ); ! NO STATUS CHANGE / ONLY WARNING END END END WHILE (MPPADDR _ .MPPADDR[M0FORE]) NEQ 0 END ELSE BEGIN DO BEGIN NEXT _ .MPPADDR[ M0FORE ]; IF .MPPADDR[M0TOBEDEFINED] THEN BEGIN ERROR( 49 ); OUTSA(MPPADDR[M0NAME]); TYPE('[ TO BE DEFINED?M?J?M?J]'); PRINTMPPNAME( MPPADDR[ M0NAME ] ); MAKMPP(.MPPADDR) END ELSE BEGIN IF .MPPADDR[M0LISTPTRS] EQL 0 THEN BEGIN WARN( 28 ); OUTSA(MPPADDR[M0NAME]); TYPE('[ HAS NO NODE ASSOCIATED WITH IT?M?J?M?J]' ); PRINTMPPNAME( MPPADDR[ M0NAME ] ); ASKSTR( 'DO YOU WISH TO [DELETE THIS MPP OR ATTACH IT TO A NODE]?R(,DELETE,ATTACH?R)[: ??]', PLIT( ASCII 'DELET', DELMPP, ASCII 'ATTAC', MPPATTACH, 0, IGNORE ), .MPPADDR ) END END END WHILE (MPPADDR _ .NEXT) NEQ 0 END; .STATUS END; COMMENT; ! ROUTINE MPPATTACH ! ======= ========= ! THIS ROUTINE ATTACHES THE MPP TO A NODE ROUTINE MPPATTACH( MPPADDR ) = BEGIN REGISTER NODEPTR; LABEL LOOP; MAP FORMAT MPPADDR; TYPE( '[ATTACH TO WHAT NODE: ??]' ); LOOP: REPEAT ! UNTIL WE GET A GOOD ANSWER BEGIN WHILE ( ACHAR _ INPUT( ALINE, ALINELENGTH ) ) EQL CRONLY DO ! GET AN INPUT, MUST HAVE ONE BEGIN ERROR( 32 ); WARN( 0 ); TYPE( '[ ??]' ) END; IF ( NODEPTR _ GETNODEPTR( PRIM<0,0> ) ) NEQ 0 THEN ! FIND THE NODE'S ADDRESS BEGIN IF NOT HASMPP( .NODEPTR ) THEN LEAVE LOOP ELSE ERROR( 91 ); NOTE - COULD MAKE THIS ASK REPLACE OR IGNORE ? END ELSE BEGIN ERROR( 33 ) END; RETURN END; ATTACH( %TO% MPPADDR[M0LISTPTRS], .NODEPTR, N0MPPOFFSETT ) END; END; ! END OF MGNMPP.BLI