!***COPYRIGHT (C) 1974, 1975, 1976, 1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.*** ! *** LAST MODIFIED BY ILG ON 30-DEC-76 COMMENT; ! MGNND.BLI ! ===== === ! THIS FILE CONTAINS THOSE ROUTINES REQUIRED TO HANDLE NODE GENERATIONS GLOBAL BIND ND = 1; FORWARD PRNODENAME; COMMENT; ! ROUTINE PRINTNODENAME ! ======= ============= ! OUTPUTS NODENAME TO CONTROLLING TTY ROUTINE PRINTNODENAME( NODENAME ) = BEGIN TYPE( 'FOR [NODE ]'); PRNODENAME( .NODENAME ); TYPE( '[:?M?J]' ) END; COMMENT; ! ROUTINE INNODE ! ======= ====== ! THIS ROUTINE ASKS FOR AND ACCEPTS A NODE NAME FROM THE USER ROUTINE INNODE(A)= BEGIN XTYPE(.A); ! TYPE THE QUESTION IF (ACHAR _ INPUT(ALINE,ALINELENGTH)) EQL CRCHAR 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 .ERRORFLG THEN 0 ELSE 1 ! IF ERROR IN ANY PART, RETURN 0 ELSE 1 END; COMMENT; ! ROUTINE PRNODENAME ! ======= ========== ! THIS ROUTINE TYPES A NODENAME GLOBAL ROUTINE PRNODENAME( NODENAME ) = BEGIN LABEL LOOP; XOUTPUT( .NODENAME ); LOOP: INCR I FROM N0NAMELEN TO N0NAMELEN * 3 BY N0NAMELEN DO BEGIN IF .(.NODENAME)[.I] EQL 0 THEN LEAVE LOOP; ! ELSE ! OUTPUTC("."); XOUTPUT( (.NODENAME)[.I] ) END END; COMMENT; ! ROUTINE CREATENODE ! ======= ========== ! CREATE A NEW NODE WHICH WILL BE ATTACHED TO THE TREE (BY SOMEONE ! ELSE ROUTINE CREATENODE( NODENAME ) = BEGIN REGISTER NODEPTR; MAP FORMAT NODEPTR; LABEL LOOP; NODEPTR _ GMEM(N0SIZE); ZERO( .NODEPTR, N0SIZE ); LOOP: DECR I FROM N0NAMELEN * ( MAXLEVEL - 1 ) TO 0 BY N0NAMELEN DO IF .(.NODENAME)[.I] NEQ 0 THEN BEGIN MOVE( %FROM% (.NODENAME)[.I], %TO% NODEPTR[N0NAME], N0NAMELEN %WORDS%); LEAVE LOOP END; NODEPTR[ N0TOBEDEFINED ] _ TRUE; .NODEPTR END; COMMENT; ! ROUTINE NULLNODENAME ! ======= ============ ! RETURNS TRUE IF THE PRIMARY QUEUE AND SUBQUEUES ARE NULL, ELSE FALSE GLOBAL ROUTINE NULLNODENAME(LOC)= BEGIN DECR I FROM N0NAMELEN * ( MAXLEVEL - 1 ) TO 0 BY N0NAMELEN DO IF .(.LOC)[.I] NEQ 0 THEN RETURN FALSE; TRUE END; FORWARD ACCEPTNODE(1); COMMENT; ! ROUTINE MAKENODE ! ======= ======== ! GIVEN THE ADDRESS OF A NODENAME, THIS ROUTINE CAUSE THE APPROPRIATE ! QUESTIONS TO BE ASKED TO GENERATE ONE OR MORE NODES ( MORE IF ! THE NODE NAME WAS NULL) GLOBAL ROUTINE MAKENODE(NODENAME)= BEGIN IF .TRCLEN LEQ 0 THEN RETURN( ERROR( 35 ) ); ! CAN'T MAKE NODE WITHOUT TRCODE SIZE IF NULLNODENAME(.NODENAME) THEN ! IF NO NODE SPECIFIED BEGIN ! ASK THE USER FOR NODE NAMES REPEAT ! UNTIL HE INPUTS A BY BEGIN ! ITSELF IF INNODE( PAZ '[NODENAME]?R(,?R)[: ??') EQL 0 THEN IF NOT .ERRORFLG THEN RETURN ELSE BEGIN ERRORFLG _ 0; ! IF THE ANSWER WAS UNACCEPTABLE ERROR( 88 ); ! TELL THE USER AND ASK AGAIN WARN( 0 ) END ELSE ACCEPTNODE(PRIM<36,7>); ! IF OK NAME EXECUTE THE FUNCTION CRLF END END; ACCEPTNODE(.NODENAME) ! IF A NODE WAS SPECIFIED, USE IT END; COMMENT; ! ROUTINE GETNODEPTR ! ======= =========== ! SEARCHES THE TREE FOR THE NODENAME CONTAINED AT THE CONTENTS OF NODENAME ! IF FOUND, RETURNS THE ADDRESS OF THE TREE ENTRY ! OTHERWISE RETURNS 0 GLOBAL ROUTINE GETNODEPTR(NODENAME) = BEGIN REGISTER NODE, NODEPTR; MAP FORMAT NODEPTR; MAP ROOTFORMAT ROOT; LABEL LOOP; INCR I FROM 0 TO (MAXLEVEL - 1) * N0NAMELEN BY N0NAMELEN DO BEGIN IF TOOLONG((.NODENAME)[.I],N0NAMESIZE, N0NAMELEN * 5) THEN BEGIN WARN( 1 ); TRUNCATE((.NODENAME)[.I], N0NAMESIZE, N0NAMELEN * 5) END END; NODEPTR _ ROOT<0,0>; NODE _ .ROOT[N0FIRSTCHILD]; ! SET STARTING POINT OF SEARCH TO ! THE FIRST CHILD OF THE ROOT OF THE TREE INCR I FROM 0 TO (MAXLEVEL - 1) * N0NAMELEN BY N0NAMELEN DO ! LOOK AT THE QUEUENAMES ONE AT A TIME LOOP: BEGIN IF .(.NODENAME)[.I] EQL 0 THEN ! IF THE QUEUE NAME IS NULL THEN RETURN .NODEPTR; ! ALL DONE WHILE .NODE NEQ 0 DO ! IF NOT NULL THEN SEARCH THE TREE FOR THE NAME BEGIN NODEPTR _ .NODE; IF COMPARE(NODEPTR[N0NAMEW],(.NODENAME)[.I],N0NAMELEN) THEN ! SEE IF THE NAME OF THIS NODE IS THE ONE WE WANT BEGIN NODE _ .NODEPTR[N0FIRSTCHILD]; ! GOT ONE ON THIS LEVEL ! SO TRY NEXT NAME & LEVEL LEAVE LOOP END ELSE NODE _ .NODEPTR[N0RSIB]; ! NOT IT SO TRY NEXT ! ON THIS LEVEL END; RETURN 0 ! NO MATCH SO ERROR OUT END; .NODEPTR END; FORWARD MAKNODE(1), MODNODE(1), REPNODE(1); COMMENT; ! ROUTINE ACCEPTNODE ! ======= ========== ! THIS ROUTINE CREATES A NODE TABLE ENTRY IF ONE DOES NOT EXIST ! THEN CALLS MAKNODE TO ASK THE QUESTIONS TO FILL THE ENTRY ! IF THE NODE ALREADY EXISTS, THE USER IS ASKED HOW HE WANTS TO ! HANDLE IT ROUTINE ACCEPTNODE(NODENAME)= BEGIN REGISTER PARENT, NODEPTR; LABEL LOOP; MAP FORMAT NODEPTR; PRINTNODENAME( .NODENAME ); ! SEE IF ALREADY DEFINED IF (NODEPTR _ GETNODEPTR(.NODENAME)) EQL 0 THEN BEGIN NODEPTR _ CREATENODE( .NODENAME ); ! MAKE A NODE TABLE ENTRY LOOP: DECR I FROM ( MAXLEVEL - 1 ) * N0NAMELEN TO 0 BY N0NAMELEN DO ! ZAP LAST NODE NAME IF .(.NODENAME)[ .I ] NEQ 0 THEN BEGIN ZERO( (.NODENAME)[ .I ], (.NODENAME)[ .I ] + N0NAMELEN ); LEAVE LOOP END; IF (PARENT _ GETNODEPTR( PRIM<36,7> )) EQL 0 THEN BEGIN ERROR( 42 ); ! BAD PARENT PMEM( .NODEPTR, N0SIZE ); ! UNCREATE THE NODE RETURN END ELSE BEGIN NODEPTR[N0PARENT] _ .PARENT; ! STORE THE PARENT END END ELSE BEGIN IF NOT .NODEPTR[N0TOBEDEFINED] THEN BEGIN ASKSTR( 'NODE [ALREADY EXISTS]?R(IGNORE, MODIFY, REPLACE?R)[: ??]', PLIT( ASCII 'REPLA', REPNODE, ASCII 'MODIF', MODNODE, 0, IGNORE, ASCII 'IGNOR', IGNORE), .NODEPTR); RETURN END END; MAKNODE(.NODEPTR) END; FORWARD ASKCHILDREN, ASKCHKPNT, DFULL, KILLNODES, ASKCHILD; COMMENT; ! ROUTINE MAKNODE ! ======= ======= ! THIS ROUTINE ASKS THE QUESTIONS TO MAKE ONE (AND ONLY ONE) NODE ! AND RECORDS THE RESPONSES IN THE APPROPRIATE NODE ENTRY ROUTINE MAKNODE( NODEPTR ) = BEGIN REGISTER LEAF; MAP FORMAT NODEPTR; ASKSIBS( .NODEPTR, .NODEPTR[ N0PARENT ] ); ASKMPP( .NODEPTR ); IF .NODEPTR[ N0LEVEL ] GEQ MAXLEVEL - 1 THEN BEGIN LEAF _ TRUE; TYPE( '[THIS IS A LEAF?M?J]' ) END ELSE LEAF _ ASKYESORNO( '[IS THIS TO BE A LEAF]?R(YES,NO?R)[: ??]', YES ); IF NOT .LEAF THEN BEGIN ASKCHILDREN( .NODEPTR ) END ELSE BEGIN ASKQUOTA( .NODEPTR ); ASKISTAT( .NODEPTR ); ASKTRCODE( .NODEPTR ); ASKOPDST( .NODEPTR ); ASKCHKPNT( .NODEPTR ) END; CRLF; NODEPTR[N0TOBEDEFINED] _ FALSE END; COMMENT; ! ROUTINE ASKCHILDREN ! ======= =========== ! THIS ROUTINE ASKS FOR THE CHILDREN OF A NODE THEN ASKS ABOUT EACH CHILD ! NOTE: ASKCHILDREN CAN CALL ASKCHILD WHICH CAN CALL ASKCHILDREN ETC. ROUTINE ASKCHILDREN( NODEPTR ) = BEGIN REGISTER NEXTLEVEL, SIB, CHILD; LABEL LOOP; MAP FORMAT NODEPTR; MAP FORMAT SIB; MAP FORMAT CHILD; TYPE( '[CHILDREN]?R(,?R)[: ??]' ); NODEPTR[ N0CHILDREN ] _ 0; FIRST _ TRUE; NEXTLEVEL _ .NODEPTR[ N0LEVEL ] + 1; LOOP: REPEAT BEGIN IF .FIRST THEN FIRST _ FALSE ELSE TYPE( '[?I?I?I??' ); ACHAR _ INPUT( ALINE, ALINELENGTH ); SKIPBLANKS( ABUFF, ABPTR, ACOUNT, ACHAR ); IF EOL( ACHAR ) THEN LEAVE LOOP; WHILE NOT EOL( ACHAR ) DO BEGIN GETNAME( ABUFF, ABPTR, ACOUNT, ACHAR ); IF SUBQUEUES( PRIM ) THEN BEGIN ACHAR _ CRCHAR; ! FAKE AN EOL ERROR( 97 ); WARN( 0 ) END ELSE BEGIN IF SIBSAMENAME( .NODEPTR, PRIM ) THEN BEGIN ACHAR _ CRCHAR; ! FAKE AN EOL ERROR( 84 ); WARN( 0 ) END ELSE BEGIN SKIPBLANKS( ABUFF, ABPTR, ACOUNT, ACHAR ); IF .ACHAR EQL "," OR EOL( ACHAR ) THEN BEGIN SIB _ .NODEPTR[ N0LASTCHILD ]; CHILD _ CREATENODE( PRIM ); IF .NODEPTR[ N0FIRSTCHILD ] EQL 0 THEN NODEPTR[ N0FIRSTCHILD ] _ .CHILD; NODEPTR[ N0LASTCHILD ] _ SIB[ N0RSIB ] _ .CHILD; CHILD[ N0LSIB ] _ .SIB; CHILD[ N0PARENT ] _ .NODEPTR; CHILD[ N0LEVEL ] _ .NEXTLEVEL; IF .ACHAR EQL "," THEN ADV( ABUFF, ABPTR, ACOUNT, ACHAR ) END ELSE BEGIN ERROR( 46 ); ACHAR _ CRCHAR ! FAKE AN EOL END END END END END; SIB _ .NODEPTR[N0FIRSTCHILD ]; WHILE .SIB NEQ 0 DO BEGIN ASKCHILD( .SIB ); SIB _ .SIB[ N0RSIB ] END END; COMMENT; ! ROUTINE ASKCHILD ! ======= ======== ! THIS ROUTINE ASKS FOR THE INFO ABOUT A CHILD ! SEE ASKCHILDREN ABOUT RECURSION ROUTINE ASKCHILD( NODEPTR ) = BEGIN REGISTER LEAF; MAP FORMAT NODEPTR; TYPE( '[FOR NODE ]'); DFULL( .NODEPTR ); OUTC( ":" ); CRLF; ASKMPP( .NODEPTR ); IF .NODEPTR[ N0LEVEL ] GEQ MAXLEVEL - 1 THEN BEGIN LEAF _ TRUE; TYPE( '[THIS IS A LEAF?M?J]' ) END ELSE LEAF _ ASKYESORNO( '[IS THIS TO BE A LEAF]?R(YES,NO?R)[: ??]', YES ); IF NOT .LEAF THEN BEGIN ASKCHILDREN( .NODEPTR ) END ELSE BEGIN ASKQUOTA( .NODEPTR ); ASKISTAT( .NODEPTR ); ASKTRCODE( .NODEPTR ); ASKOPDST( .NODEPTR ); ASKCHKPNT( .NODEPTR ) END; CRLF; NODEPTR[N0TOBEDEFINED] _ FALSE END; COMMENT; ! ROUTINE REPNODE ! ======= ======= ! THIS ROUTINE ASKS THE QUESTIONS TO REPLACE ONE NODE ! AND RECORDS THE RESPONSES IN THE APPROPRIATE NODE ENTRY ROUTINE REPNODE(NODEPTR)= BEGIN MAP FORMAT NODEPTR; KILLNODES( .NODEPTR ); ! FIRST DELETE THE NODE TO BE REPLACED ! AND ALL ITS CHILDREN TOO. ACCEPTNODE( PRIM<36,7> ); !THEN RECREATE IT BY NAME END; FORWARD DISNODE, DALLNODES; COMMENT; ! ROUTINE DISPNODE ! ======= =========== ! THIS ROUTINE HANDLES THE INDIVIDUAL CASES OF DISPLAY NODE:... ! CASE 1: IF AN INDIVIDUAL NODE IS REQUESTED ( BY NAME ), DISNODE IS ! CALLED WITH THE ADDRESS OF THE NODE TABLE ENTRY ! CASE 2: IF /ALL WAS SPECIFIED, DISNODE IS CALLED FOR EACH ENTRY IN ! NODE TABLE ! CASE 3: IF NO NAME OR SWITCH WAS GIVEN, THE USER IS ASKED FOR THE ! NAMES OF THE NODES TO BE DISPLAYED GLOBAL ROUTINE DISPNODE(NODENAME)= BEGIN REGISTER NODEPTR; MAP FORMAT NODEPTR; MAP ROOTFORMAT ROOT; IF .ROOT[ N0CHILDREN ] EQL 0 THEN RETURN ERROR( 38 ); IF NULLNODENAME(.NODENAME) AND NOT .ALLSWITCH THEN BEGIN ! ASK THE USER FOR NODE NAMES REPEAT ! UNTIL HE INPUTS A BY BEGIN ! ITSELF IF INNODE( PAZ '[NODENAME]?R(,?R)[: ??') EQL 0 THEN IF NOT .ERRORFLG THEN RETURN ELSE BEGIN ERRORFLG _ 0; ERROR( 88 ); ! TELL THE USER AND ASK AGAIN WARN( 0 ) END ELSE IF (NODEPTR _ GETNODEPTR(PRIM)) EQL 0 THEN RETURN(ERROR(33)) ELSE DISNODE(.NODEPTR); CRLF END END; IF .ALLSWITCH THEN BEGIN IF .ROOT[ N0CHILDREN] EQL 0 THEN RETURN ( ERROR( 68 ) ); DALLNODES( .ROOT[ N0FIRSTCHILD] ); RETURN END; IF (NODEPTR _ GETNODEPTR(.NODENAME)) EQL 0 THEN RETURN(ERROR(33)) ELSE DISNODE(.NODEPTR) END; COMMENT; ! ROUTINE DALLNODES ! ======= ========= ! THIS ROUTINE DISPLAYS ALL THE NODES IN THE TREE ROUTINE DALLNODES(ARG)= BEGIN REGISTER NODEPTR; MAP FORMAT NODEPTR; MACRO NAME = NODEPTR[N0NAME]$, NEXTTHIS = NODEPTR[N0RSIB]$, NEXTLEVEL = NODEPTR[N0FIRSTCHILD]$, LEAF = (.NEXTLEVEL EQL 0)$; LABEL B; NODEPTR_.ARG; B: REPEAT BEGIN DISNODE(.NODEPTR); IF NOT LEAF THEN DALLNODES(.NEXTLEVEL); WHILE .NEXTTHIS EQL 0 DO RETURN; IF(NODEPTR_.NEXTTHIS) EQL 0 THEN LEAVE B; END END; FORWARD DNFULLSPEC, DNNAME, DNLEVEL, DNTYPE, DNPARENT, DNSIBS, DNCHILDREN, DNMPP, DNTHRESH, DLQUOTA, DLISTAT, DLTRCODE, DLOSTAT,DLCHKPNT, DLONAME; COMMENT; ! ROUTINE DISNODE ! ======= ======= ! THIS ROUTINE DISPLAYS THE NODE'S NAME, AND IF THE NODE IS UNDEFINED, ! THEN "NOT YET DEFINED..." IS DISPLAYED, OTHERWISE THE NODE PARAMETERS ! ARE DISPLAYED ROUTINE DISNODE(NODEPTR)= BEGIN MAP FORMAT NODEPTR; DNFULLSPEC(.NODEPTR); DNNAME(.NODEPTR); DNLEVEL(.NODEPTR); DNTYPE(.NODEPTR); DNPARENT(.NODEPTR); DNSIBS(.NODEPTR); DNCHILDREN(.NODEPTR); IF .NODEPTR[N0TOBEDEFINED] THEN BEGIN OUTPUT('NOT YET DEFINED, PLEASE MAKE OR MODIFY IT') END ELSE BEGIN DNMPP(.NODEPTR); DNTHRESH(.NODEPTR); IF .NODEPTR[N0CHILDREN] EQL 0 THEN ! IF LEAF THEN BEGIN DLQUOTA(.NODEPTR); DLISTAT(.NODEPTR); DLTRCODE(.NODEPTR); DLOSTAT(.NODEPTR); DLONAME(.NODEPTR); DLCHKPNT(.NODEPTR) END END; OUTPUTCRLF END; COMMENT; ! ROUTINE DNAME ! ======= ===== ! THIS ROUTINE DISPLAYS THE NAME OF A NODE GLOBAL ROUTINE DNAME( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; XOUTPUT( NODEPTR[N0NAME] ) END; COMMENT; ! ROUTINE DFULL ! ======= ===== ! THIS ROUTINE DISPLAYS THE FULL NAME OF A NODE ROUTINE DFULL( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; IF .NODEPTR[N0PARENT] NEQ ROOT<0,0> THEN DFULL( .NODEPTR[N0PARENT] ) ELSE BEGIN DNAME( .NODEPTR ); RETURN END; OUTPUTC( "." ); DNAME( .NODEPTR ) END; COMMENT; ! ROUTINE DNFULLSPEC ! ======= ====== ! THIS ROUTINE DISPLAYS THE FULL SPECIFICATION OF A NODE WITH SOME ! OTHER GARBAGE ROUTINE DNFULLSPEC( NODEPTR ) = BEGIN OUTPUT( 'FULL SPECIFICATION: '); DFULL( .NODEPTR ); OUTPUTCRLF END; COMMENT; ! ROUTINE DNNAME ! ======= ====== ! THIS ROUTINE DISPLAYS THE NAME OF A NODE WITH SOME OTHER GARBAGE ROUTINE DNNAME( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; OUTPUT( 'INDIVIDUAL NAME: '); XOUTPUT( NODEPTR[N0NAME] ); OUTPUTCRLF END; COMMENT; ! ROUTINE DNLEVEL ! ======= ======= ! THIS ROUTINE TYPES THE LEVEL OF THE NODE ROUTINE DNLEVEL( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; OUTPUT('LEVEL: '); XOUTPUT( CASE .NODEPTR[N0LEVEL] OF SET %0% PAZ 'PRIM'; %1% PAZ 'SQ1'; %2% PAZ 'SQ2'; %3% PAZ 'SQ3'; TES ); OUTPUTCRLF END; COMMENT; ! ROUTINE DNTYPE ! ======= ========= ! THIS ROUTINE DISPLAYS THE NODE'S TYPE ROUTINE DNTYPE(NODEPTR)= BEGIN MAP FORMAT NODEPTR; OUTPUT('TYPE: '); XOUTPUT(IF .NODEPTR[N0CHILDREN] EQL 0 THEN PAZ 'LEAF' ELSE PAZ 'NODE'); OUTPUTCRLF END; COMMENT; ! ROUTINE DNPARENT ! ======= ======== ! THIS ROUTINE DISPLAYS THE PARENT OF A NODE ROUTINE DNPARENT( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; OUTPUT('PARENT: '); IF .NODEPTR[N0PARENT] EQL ROOT<0,0> THEN OUTPUT( '' ) ELSE DFULL( .NODEPTR[N0PARENT] ); OUTPUTCRLF END; COMMENT; ! ROUTINE DNSIBS ! ======= ====== ! THIS ROUTINE TYPES THE SIBS OF A NODE GLOBAL ROUTINE DNSIBS( NODEPTR ) = BEGIN REGISTER PARENT, SIB; MAP FORMAT NODEPTR; MAP FORMAT PARENT; MAP FORMAT SIB; PARENT _ .NODEPTR[N0PARENT]; SIB _ .PARENT[N0FIRSTCHILD]; OUTPUT('SIBS: '); DO BEGIN IF .SIB EQL .NODEPTR THEN OUTPUT('') ELSE DNAME( .SIB ); SIB _ .SIB[N0RSIB]; IF .SIB NEQ 0 THEN OUTPUTC( "," ) END WHILE .SIB NEQ 0; OUTPUTCRLF END; COMMENT; ! ROUTINE DNCHILDREN ! ======= ========== ! THIS ROUTINE DISPLAYS THE CHILDREN OF THE SPECIFIED NODE GLOBAL ROUTINE DNCHILDREN( NODEPTR ) = BEGIN REGISTER CHILD; MAP FORMAT NODEPTR; MAP FORMAT CHILD; OUTPUT('CHILDREN: '); IF ( CHILD _ .NODEPTR[N0FIRSTCHILD] ) EQL 0 THEN BEGIN OUTPUT('?M?J'); RETURN END; DO BEGIN DNAME( .CHILD ); IF .CHILD[N0RSIB] NEQ 0 THEN OUTPUTC( "," ) END WHILE ( CHILD _ .CHILD[N0RSIB] ) NEQ 0; OUTPUTCRLF END; COMMENT; ! ROUTINE DNMPP ! ======= ===== ! THIS ROUTINE DISPLAYS THE MPP ASSOCIATED WITH THIS NODE ROUTINE DNMPP( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; OUTPUT('MPP: '); IF .NODEPTR[N0MPPPTR] NEQ 0 THEN DMNAME( .NODEPTR[N0MPPPTR] ) ELSE OUTPUT(''); OUTPUTCRLF END; COMMENT; ! ROUTINE DNTHRESH ! ======= ======== ! THIS ROUTINE DISPLAYS THE STARTING CRITERION ( THRESHOLD ) FOR THE ! SPECIFIED MPP ROUTINE DNTHRESH( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; IF .NODEPTR[N0MPPPTR] EQL 0 THEN RETURN; OUTPUT( 'STARTING CRITERION: '); OUTPUTD( .NODEPTR[N0THRESH] ); OUTPUTCRLF END; COMMENT; ! ROUTINE DLQUOTA ! ======= ======= ! THIS ROUTINE DISPLAYS THE TRANSACTION QUOTA OF A LEAF ROUTINE DLQUOTA( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; IF .NODEPTR[N0CHILDREN] NEQ 0 THEN RETURN; ! IF NOT LEAF LEAVE NOW OUTPUT( 'QUOTA: '); OUTPUTD( .NODEPTR[N0QUOTA] ); OUTPUTCRLF END; COMMENT; ! ROUTINE DLISTAT ! ======= ======= ! THIS ROUTINE DISPLAYS THE INITIAL INPUT STATUS OF THE LEAF ROUTINE DLISTAT( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; IF .NODEPTR[N0CHILDREN] NEQ 0 THEN RETURN; ! IF NOT LEAF LEAVE NOW OUTPUT('INITIAL INPUT STATUS: '); XOUTPUT( IF .NODEPTR[N0STATUS] EQL ENABLED THEN PAZ 'ENABLED' ELSE PAZ 'DISABLED' ); OUTPUTCRLF END; COMMENT; ! ROUTINE DLTRCODE ! ======= ======== ! THIS ROUTINE DISPLAYS THE TRANSACTION CODE ASSOCIATED WITH THIS LEAF ROUTINE DLTRCODE( NODEPTR ) = BEGIN REGISTER TRCODE; MAP FORMAT TRCODE; MAP FORMAT NODEPTR; IF .NODEPTR[N0CHILDREN] NEQ 0 THEN RETURN; ! IF NOT LEAF LEAVE NOW OUTPUT('TRCODE: '); TRCODE _ .NODEPTR[N0TRCODE]; OUTPUTBITS( TRCODE[TR0CODE], .TRCLEN ); OUTPUTCRLF END; COMMENT; ! ROUTINE DLOSTAT ! ======= ======= ! THIS ROUTINE DISPLAYS THE INITIAL OUTPUT STATUS OF THIS LEAF ROUTINE DLOSTAT( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; IF .NODEPTR[N0CHILDREN] NEQ 0 THEN RETURN; ! IF NOT LEAF LEAVE NOW IF .NODEPTR[N0OPNAME] EQL 0 THEN OUTPUT('THIS LEAF IS NOT USED FOR OUTPUT') ELSE BEGIN OUTPUT('INITIAL OUTPUT STATUS: '); XOUTPUT( IF .NODEPTR[N0OPSTATUS] EQL ENABLED THEN PAZ 'ENABLED' ELSE PAZ 'DISABLED' ) END; OUTPUTCRLF END; COMMENT; ! ROUTINE DLONAME ! ======= ======= ! THIS ROUTINE DISPLAYS THE NAME FOR OUTPUT OF THIS LEAF ROUTINE DLONAME( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; IF .NODEPTR[N0OPNAME] EQL 0 OR .NODEPTR[N0CHILDREN] NEQ 0 THEN RETURN ELSE BEGIN OUTPUT('NAME FOR OUTPUT: '); XOUTPUT( NODEPTR[N0OPNAME] ); END; OUTPUTCRLF END; COMMENT; ! ROUTINE DLCHKPNT ! ======= ======== ! THIS ROUTINE DISPLAYS WHETHER TRANSACTIONS TO THIS LEAF ARE CHECKPOINTED ROUTINE DLCHKPNT( NODEPTR ) = BEGIN MAP FORMAT NODEPTR; IF .NODEPTR[N0CHILDREN] NEQ 0 THEN % IF NOT A LEAF % RETURN ELSE BEGIN OUTPUT('TRANSACTIONS TO THIS LEAF ARE '); IF NOT .NODEPTR[ N0CHKPNT ] THEN OUTPUT('NOT '); OUTPUT('CHECKPOINTED?M?J') END END; ! ROUTINE MODINODE ! ======= =========== ! THIS ROUTINE HANDLES THE INDIVIDUAL CASES OF MODIFY NODE:... ! CASE 1: IF AN INDIVIDUAL NODE IS REQUESTED ( BY NAME ), MODNODE IS ! CALLED WITH THE ADDRESS OF THE NODE TABLE ENTRY ! CASE 2: IF /ALL WAS SPECIFIED, MODNODE IS CALLED FOR EACH ENTRY IN ! NODE TABLE ! CASE 3: IF NO NAME OR SWITCH WAS GIVEN, THE USER IS ASKED FOR THE ! NAMES OF THE NODES TO BE MODIFIED GLOBAL ROUTINE MODINODE(NODENAME)= BEGIN REGISTER NODEPTR; MAP ROOTFORMAT ROOT; MAP FORMAT NODEPTR; IF .ROOT[ N0CHILDREN ] EQL 0 THEN RETURN ERROR( 38 ); IF NULLNODENAME(.NODENAME) AND NOT .ALLSWITCH THEN BEGIN ! ASK THE USER FOR NODE NAMES REPEAT ! UNTIL HE INPUTS A BY BEGIN ! ITSELF IF INNODE( PAZ '[NODENAME]?R(,?R)[: ??') EQL 0 THEN IF NOT .ERRORFLG THEN RETURN ELSE BEGIN ERRORFLG _ 0; ERROR( 88 ); ! TELL THE USER AND ASK AGAIN WARN( 0 ) END ELSE IF (NODEPTR _ GETNODEPTR(PRIM)) EQL 0 THEN RETURN(ERROR(33)) ELSE MODNODE(.NODEPTR); CRLF END END; IF .ALLSWITCH THEN BEGIN ERROR( 8 ); RETURN END; IF (NODEPTR _ GETNODEPTR(.NODENAME)) EQL 0 THEN RETURN(ERROR(33)) ELSE MODNODE(.NODEPTR); END; FORWARD MNNAME(1), MNPARENT, MNSIBS, MNCHILDREN, MNMPP, MNTHRESH, MLQUOTA, MLISTAT, MLCHKPNT, MLTRCODE, MLONAME, MLOSTAT, MNALL, TELLNODECHANGES; COMMENT; ! ROUTINE MODNODE ! ======= ======= ! THIS ROUTINE TYPES THE NAME OF THE NODE TO BE MODIFIED, AND THEN ! ASKS FOR THE CHANGES TO BE MADE. MODNODE DOES ONLY ONE NODE AT A ! TIME. ROUTINE MODNODE(NODEPTR)= BEGIN OWN DONE; MAP FORMAT NODEPTR; %LOCAL% ROUTINE SETDONE = DONE _ TRUE; TYPE( 'FOR [NODE ]' ); DFULL( .NODEPTR ); TYPE( '[:?M?J]' ); IF .NODEPTR[N0TOBEDEFINED] THEN ! IF UNDEFINED THEN BEGIN MAKNODE() ! 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 '??', TELLNODECHANGES, ASCII 'NAME', MNNAME, ASCII 'PAREN', MNPARENT, ASCII 'SIBS', MNSIBS, ASCII 'CHILD', MNCHILDREN, ASCII 'MPP', MNMPP, ASCII 'START', MNTHRESH, ASCII 'QUOTA', MLQUOTA, ASCII 'ISTAT', MLISTAT, ASCII 'TRCOD', MLTRCODE, ASCII 'ONAME', MLONAME, ASCII 'OSTAT', MLOSTAT, ASCII 'CHKPT', MLCHKPNT, ASCII 'ALL', MNALL, 0, SETDONE), .NODEPTR); CRLF END END END; COMMENT; ! ROUTINE TELLNODECHANGES ! ======= =============== ! THIS ROUTINE TELLS ( WITH LOTS OF WIND ) WHAT CHANGES CAN BE MADE ON ! A NODE ROUTINE TELLNODECHANGES = BEGIN TYPE( 'TYPE [NAME] TO CHANGE THE NAME OF THE NODE[(,)]?J ?MTYPE [PARENT] TO CHANGE THE PARENT OF THE NODE[(,)]?J ?MTYPE [SIBS] TO CHANGE THE SIBLINGS OF THE NODE[(,)]?J ?MTYPE [CHILDREN] TO CHANGE THE CHILDREN OF THE NODE[(,)]?J ?MTYPE [MPP] TO CHANGE THE MPP TO START FOR THE NODE[(,)]?J ?MTYPE [START] TO CHANGE THE STARTING CRITERION FOR THE NODE[(,)]?J ?MTYPE [QUOTA] TO CHANGE THE IN CORE QUOTA FOR THE LEAF[(,)]?J ?MTYPE [ISTAT] TO CHANGE THE INITIAL INPUT STATUS FOR THE LEAF[(,)]?J ?MTYPE [TRCODE] TO CHANGE THE TRANSACTION CODE FOR THE LEAF[(,)]?J ?MTYPE [ONAME] TO CHANGE THE NAME FOR OUTPUT FOR THE LEAF[(,)]?J ?MTYPE [OSTAT] TO CHANGE THE INITIAL OUTPUT STATUS FOR THE LEAF[(,)]?J ?MTYPE [CHKPT] TO CHANGE CHECKPOINT FLAG FOR THE LEAF[(,)]?J ?MTYPE [ALL] TO CHANGE ALL OF THE ABOVE[(,)]?J ?MTYPE A CARRIAGE RETURN TO FINISH CHANGING THIS NODE[(?R( WHEN DONE?R))]'); CRLF; END; COMMENT; ! ROUTINE MNALL ! ======= ======== ! THIS ROUTINE ASKS ALL THE QUESTIONS TO CHANGE A NODE ROUTINE MNALL(NODEPTR) = BEGIN MAP FORMAT NODEPTR; MNNAME( .NODEPTR); MNPARENT( .NODEPTR ); MNSIBS( .NODEPTR ); MNCHILDREN( .NODEPTR ); IF NOT MNMPP( .NODEPTR ) THEN ! IF THE STARTING CRITERIA ! QUESTION IS ASKED IN MNMPP ! THEN DON'T DO MNTHRESH MNTHRESH( .NODEPTR ); IF .NODEPTR[ N0CHILDREN ] EQL 0 THEN BEGIN MLQUOTA( .NODEPTR ); MLISTAT( .NODEPTR ); MLTRCODE( .NODEPTR ); MLONAME( .NODEPTR ); MLOSTAT( .NODEPTR ); MLCHKPNT( .NODEPTR ) END END; COMMENT; ! ROUTINE MNNAME ! ======= ========= ! THIS ROUTINE ASKS THE QUESTION TO CHANGE A NODE'S NAME ROUTINE MNNAME(NODEPTR)= BEGIN MAP FORMAT NODEPTR; LABEL LOOP; IF .SHOW THEN BEGIN DNFULLSPEC( .NODEPTR ); DNNAME(.NODEPTR) END; LOOP: REPEAT BEGIN IF INNODE( PAZ 'NEW [NODENAME]?R(,?R)[: ??]') EQL 0 THEN RETURN; IF SIBSAMENAME( .NODEPTR[ N0PARENT ], PRIM ) THEN ERROR( 84 ) ELSE IF SUBQUEUES( PRIM ) THEN ERROR( 97 ) ELSE LEAVE LOOP; WARN( 0 ) END; MOVE(PRIM, NODEPTR[N0NAME], N0NAMELEN) END; COMMENT; ! ROUTINE MNPARENT ! ======= ======== ! THIS ROUTINE ASKS THE QUESTIONS TO MODIFY THE PARENT OF A NODE ROUTINE MNPARENT( NODEPTR ) = BEGIN OWN PARENT, NODE, PARENTUP, NODEDOWN; MAP FORMAT NODEPTR; MAP FORMAT NODE; LABEL LOOP; DNLEVEL( .NODEPTR ); DNTYPE( .NODEPTR ); DNPARENT( .NODEPTR ); LOOP: REPEAT BEGIN IF ( ASKLINE( '[NEW PARENT]?R(, "", ?R)[: ??]' ) ) THEN RETURN; ! NO CHANGE ! ELSE ! IF MATCHALINE( NONE ) THEN BEGIN PARENT _ ROOT<0,0>; LEAVE LOOP END; ! ELSE ! GETNAME( ALINE, ACHAR ); IF NOT .ERRORFLG THEN BEGIN IF TOOMUCHINPUT() THEN %CONTINUE% ELSE IF ( PARENT _ GETNODEPTR( PRIM ) ) EQL 0 THEN ERROR( 42 ) ELSE BEGIN IF .PARENT EQL .NODEPTR THEN ERROR( 121 ) ELSE BEGIN NODE _ .PARENT; WHILE .NODE NEQ ROOT<0,0> DO BEGIN IF .NODE EQL .NODEPTR THEN ERROR( 121 ); NODE _ .NODE[ N0PARENT ] END; IF NOT .ERRORFLG THEN IF SIBSAMENAME( .PARENT, NODEPTR[ N0NAME ] ) THEN ERROR( 84 ) ! SIB OF SAME NAME ELSE BEGIN PARENTUP _ MPPUP( .PARENT ); NODEDOWN _ MPPDOWN( .NODEPTR ); IF NOT ( .PARENTUP EQL .NODEDOWN OR .NODEDOWN EQL 0 OR .PARENTUP EQL 0 ) THEN ERROR( 99 ) ELSE LEAVE LOOP END END END END; WARN( 0 ) ! AND TRY AGAIN END; DETACHNODE( .NODEPTR ); ASKSIBS( .NODEPTR, .PARENT ) ! ATTACH NODE TO NEW PARENT END; COMMENT; ! ROUTINE MNSIBS ! ======= ====== ! THIS ROUTINE ASKS THE QUESTIONS TO MODIFY A NODES SIBLINGS ROUTINE MNSIBS( NODEPTR ) = BEGIN OWN PARENT, NODE; %LOCAL% ROUTINE GETSIBNAME = BEGIN MAP FORMAT NODE; LABEL LOOP; REPEAT BEGIN LOOP: REPEAT BEGIN IF EOL( ACHAR ) THEN BEGIN ASKLINE( '[?I?I?I??]' ); IF EOL( ACHAR ) THEN RETURN TRUE END; ! IN EITHER CASE ! ZEROARGLIST; IF MATCHALINE( (PAZ '' )<36,7> ) THEN BEGIN MOVE( NODE[ N0NAME ], PRIM, N0NAMELEN ) END ELSE GETNAME( ALINE, ACHAR ); IF NOT ( .ACHAR EQL "," OR EOL( ACHAR ) ) THEN LEAVE LOOP WITH ERROR( 31 ); IF .ACHAR EQL "," THEN ADV( ABUFF, ABPTR, ACOUNT, ACHAR ); ! SKIP THE COMMA IF .ARGTYPE NEQ 0 OR .SUB1 NEQ 0 OR .SUB2 NEQ 0 OR .SUB3 NEQ 0 THEN LEAVE LOOP WITH ERROR( 97 ); IF .PRIM EQL 0 THEN LEAVE LOOP WITH ERROR( 32 ); RETURN FALSE; END; ACHAR _ CRCHAR; WARN( 0 ) END END; %LOCAL% ROUTINE ASKEACH( SIB ) = BEGIN REGISTER NEXT; MAP FORMAT SIB; DO BEGIN NEXT _ .SIB[ N0RSIB ]; TYPE( '[DO YOU WISH TO KEEP SIB:]' ); DNAME( .SIB ); IF ( ASKYESORNO( ' ?R(YES, NO?R)[: ??]', YES ) ) THEN BEGIN DETACHNODE( .SIB ); ASKSIBS( .SIB, .PARENT ) END END WHILE ( SIB _ .NEXT ) NEQ 0 END; REGISTER SIB, FAKENODEPTR, NEXT; LOCAL FAKENODE[ N0SIZE ]; LABEL LOOP, LOOP2, LOOP3, LOOP4; MAP FORMAT NODEPTR; MAP FORMAT PARENT; MAP FORMAT FAKENODEPTR; MAP FORMAT SIB; ! BEGIN ! IF .SHOW THEN DNSIBS( .NODEPTR ); ! SHOW THE SIBS TO THE USER IF HE WANTS THEM PARENT _ .NODEPTR[ N0PARENT ]; NODE _ .NODEPTR; LOOP: REPEAT BEGIN IF ASKLINE( '[NEW SIBS]?R(, "", ?R)[: ??]' ) THEN RETURN; ! ELSE ! IF MATCHALINE( NONE ) THEN ! IF THEN DELETE ALL SIBS BEGIN IF CONFIRMED() THEN BEGIN SIB _ .PARENT[ N0FIRSTCHILD ]; TYPE( 'NODES DELETED:?M?J' ); DO BEGIN NEXT _ .SIB[ N0RSIB ]; IF .SIB NEQ .NODEPTR THEN KILLNODES( .SIB ); END WHILE ( SIB _ .NEXT ); RETURN END END ELSE LEAVE LOOP; WARN( 0 ) END; ! ELSE ! ! DETACH ALL SIBS ! FAKENODEPTR _ FAKENODE<0,0>; FAKENODEPTR[ N0CHILDREN ] _ .PARENT[ N0CHILDREN ]; MOVE( PARENT[ N0NAME ], FAKENODEPTR[ N0NAME ], N0NAMELEN ); ! GIVE THE FAKE NODE CHARACTERISTICS OF THE REAL FAKENODEPTR[ N0PARENT ] _ .PARENT[ N0PARENT ]; ! PARENT FOR KILLNODE TO TYPE NAME SIB _ .PARENT[ N0FIRSTCHILD ]; DO ! CHANGE THE PARENT OF EACH SIB TO FAKENODE BEGIN SIB[ N0PARENT ] _ .FAKENODEPTR END WHILE ( SIB _ .SIB[ N0RSIB ] ) NEQ 0; PARENT[ N0CHILDREN ] _ 0; LOOP2: REPEAT BEGIN IF GETSIBNAME() THEN LEAVE LOOP2; ! ELSE ! IF SIBSAMENAME( .PARENT, PRIM ) THEN ! IF SIB OF THE SAME NAME THEN ERROR BEGIN ERROR( 84 ); WARN( 0 ) END ELSE ! OTHERWIISE BEGIN SIB _ .FAKENODEPTR[ N0FIRSTCHILD ]; ! SEE IF THE SIB GIVEN IS AN OLD ONE LOOP3: WHILE .SIB NEQ 0 DO BEGIN IF COMPARE( SIB[ N0NAME ], PRIM, N0NAMELEN ) THEN LEAVE LOOP3; SIB _ .SIB[ N0RSIB ] END; IF .SIB NEQ 0 THEN ! IF WE HAVE AN OLD ONE THEN BEGIN DETACHNODE( .SIB ) ! DETACH IT FROM THE FAKE NODE END ELSE BEGIN SIB _ CREATENODE( PRIM ) ! OTHERWISE MAKE A NEW ONE END; ATTACHNODE( .SIB, .PARENT, AFTER, 0 ) ! ATTACH THE SIB TO THE END OF THE LINE END END; IF .FAKENODEPTR[ N0CHILDREN ] NEQ 0 THEN ! ANY SIBS LEFT IN THE FAKE NODE ? BEGIN ! YES THEN SIB _ .FAKENODEPTR[ N0FIRSTCHILD ]; ! DON'T LET THE USER ! DELETE THE NODE WE'RE WORKING ! ON!!! LOOP4: DO BEGIN IF .SIB EQL .NODEPTR THEN BEGIN WARN( 24 ); DETACHNODE( .SIB ); ASKSIB( .SIB, .PARENT ); LEAVE LOOP4 END END WHILE ( SIB _ .SIB[ N0RSIB ] ) NEQ 0; IF .FAKENODEPTR[ N0CHILDREN ] NEQ 0 THEN ! ANY SIBS LEFT IN THE FAKE NODE ? BEGIN ! YES THEN TYPE( '[THE FOLLOWING PREVIOUS SIBS WILL BE DELETED:?M?J]' ); ! INFORM THE USER THAT THEY WILL BE ZAPPED SIB _ .FAKENODEPTR[ N0FIRSTCHILD ]; DO BEGIN DNAME( .SIB ); CRLF END WHILE ( SIB _ .SIB[ N0RSIB ] ) NEQ 0; ! THEN ASK IF HE REALLY WANTS THEM ZAPPED ASKSTR( '[DO YOU WISH TO DELETE THEM OR BE ASKED ABOUT EACH INDIVIDUALLY]?R(ASK, DELETE?R)[: ??]', PLIT( ASCII 'ASK', ASKEACH, ASCII 'DELET', IGNORE, 0, ASKEACH ), .FAKENODEPTR[ N0FIRSTCHILD ] ); SIB _ .FAKENODEPTR[ N0FIRSTCHILD ]; ! IF HE STILL DIDN'T WANT THEM KILL TYPE( 'NODES DELETED:?M?J' ); WHILE .SIB NEQ 0 DO BEGIN NEXT _ .SIB[ N0RSIB ]; DETACHNODE( .SIB ); ! ATTACH NODE TO REAL PARENT ATTACHNODE( .SIB, .PARENT, BEFORE, 0 ); ! SO WHEN KILLNODE TRYS TO TYPE THE NAME ! IT DOESN'T BARF KILLNODES( .SIB ); SIB _ .NEXT END END END; SIB _ .PARENT[ N0FIRSTCHILD ]; ! NOW ASK ALL ABOUT THE NEW ONES DO IF .SIB[ N0TOBEDEFINED ] THEN ASKCHILD( .SIB ) WHILE ( SIB _ .SIB[ N0RSIB ] ) NEQ 0 END; COMMENT; ! ROUTINE MNCHILDREN ! ======= ========== ! THIS ROUTINE ASKS THE QUESTIONS TO MODIFY A NODES CHLDREN ROUTINE MNCHILDREN( NODEPTR ) = BEGIN OWN PARENT; %LOCAL% ROUTINE GETCHILDNAME = BEGIN LABEL LOOP; REPEAT BEGIN LOOP: REPEAT BEGIN IF EOL( ACHAR ) THEN BEGIN ASKLINE( '[?I?I?I??]' ); IF EOL( ACHAR ) THEN RETURN TRUE END; ! IN EITHER CASE ! ZEROARGLIST; GETNAME( ALINE, ACHAR ); IF NOT ( .ACHAR EQL "," OR EOL( ACHAR ) ) THEN LEAVE LOOP WITH ERROR( 31 ); IF .ACHAR EQL "," THEN ADV( ABUFF, ABPTR, ACOUNT, ACHAR ); ! SKIP THE COMMA IF .ARGTYPE NEQ 0 OR .SUB1 NEQ 0 OR .SUB2 NEQ 0 OR .SUB3 NEQ 0 THEN LEAVE LOOP WITH ERROR( 97 ); IF .PRIM EQL 0 THEN LEAVE LOOP WITH ERROR( 32 ); RETURN FALSE; END; ACHAR _ CRCHAR; WARN( 0 ) END END; %LOCAL% ROUTINE ASKEACH( CHILD ) = BEGIN REGISTER NEXT; MAP FORMAT CHILD; DO BEGIN NEXT _ .CHILD[ N0RSIB ]; TYPE( '[DO YOU WISH TO KEEP CHILD:]' ); DNAME( .CHILD ); IF ( ASKYESORNO( ' ?R(YES, NO?R)[: ??]', YES ) ) THEN BEGIN DETACHNODE( .CHILD ); ASKSIBS( .CHILD, .PARENT ) END END WHILE ( CHILD _ .NEXT ) NEQ 0 END; REGISTER CHILD, FAKENODEPTR, NEXT; LOCAL FAKENODE[ N0SIZE ]; LABEL LOOP, LOOP2, LOOP3; MAP FORMAT NODEPTR; MAP FORMAT PARENT; MAP FORMAT FAKENODEPTR; MAP FORMAT CHILD; ! BEGIN ! IF .SHOW THEN DNCHILDREN( .NODEPTR ); ! SHOW THE CHILDREN TO THE USER IF HE WANTS THEM PARENT _ .NODEPTR; LOOP: REPEAT BEGIN IF ASKLINE( '[NEW CHILDREN]?R(, "", ?R)[: ??]' ) THEN RETURN; ! ELSE ! IF MATCHALINE( NONE ) THEN ! IF THEN DELETE ALL CHILDREN BEGIN IF CONFIRMED() THEN BEGIN CHILD _ .PARENT[ N0FIRSTCHILD ]; TYPE( 'NODES DELETED:?M?J' ); DO BEGIN NEXT _ .CHILD[ N0RSIB ]; KILLNODES( .CHILD ); END WHILE ( CHILD _ .NEXT ); RETURN END END ELSE LEAVE LOOP; WARN( 0 ) END; ! ELSE ! ! DETACH ALL CHILDREN ! FAKENODEPTR _ FAKENODE<0,0>; FAKENODEPTR[ N0CHILDREN ] _ .PARENT[ N0CHILDREN ]; MOVE( PARENT[ N0NAME ], FAKENODEPTR[ N0NAME ], N0NAMELEN ); ! GIVE THE FAKE NODE CHARACTERISTICS OF THE REAL FAKENODEPTR[ N0PARENT ] _ .PARENT[ N0PARENT ]; ! PARENT FOR KILLNODE TO TYPE NAME CHILD _ .PARENT[ N0FIRSTCHILD ]; WHILE .CHILD NEQ 0 DO ! CHANGE THE PARENT OF EACH CHILD TO FAKENODE BEGIN CHILD[ N0PARENT ] _ .FAKENODEPTR; CHILD _ .CHILD[ N0RSIB ] END; PARENT[ N0CHILDREN ] _ 0; LOOP2: REPEAT BEGIN IF GETCHILDNAME() THEN LEAVE LOOP2; ! ELSE ! IF SIBSAMENAME( .PARENT, PRIM ) THEN ! IF CHILD OF THE SAME NAME THEN ERROR BEGIN ERROR( 96 ); WARN( 0 ) END ELSE ! OTHERWIISE BEGIN CHILD _ .FAKENODEPTR[ N0FIRSTCHILD ]; ! SEE IF THE CHILD GIVEN IS AN OLD ONE LOOP3: WHILE .CHILD NEQ 0 DO BEGIN IF COMPARE( CHILD[ N0NAME ], PRIM, N0NAMELEN ) THEN LEAVE LOOP3; CHILD _ .CHILD[ N0RSIB ] END; IF .CHILD NEQ 0 THEN ! IF WE HAVE AN OLD ONE THEN BEGIN DETACHNODE( .CHILD ) ! DETACH IT FROM THE FAKE NODE END ELSE BEGIN CHILD _ CREATENODE( PRIM ) ! OTHERWISE MAKE A NEW ONE END; ATTACHNODE( .CHILD, .PARENT, AFTER, 0 ) ! ATTACH THE CHILD TO THE END OF THE LINE END END; IF .FAKENODEPTR[ N0CHILDREN ] NEQ 0 THEN ! ANY CHILDREN LEFT IN THE FAKE NODE ? BEGIN ! YES THEN TYPE( '[THE FOLLOWING PREVIOUS CHILDREN WILL BE DELETED:?M?J]' ); ! INFORM THE USER THAT THEY WILL BE ZAPPED CHILD _ .FAKENODEPTR[ N0FIRSTCHILD ]; DO BEGIN DNAME( .CHILD ); CRLF END WHILE ( CHILD _ .CHILD[ N0RSIB ] ) NEQ 0; ! THEN ASK IF HE REALLY WANTS THEM ZAPPED ASKSTR( '[DO YOU WISH TO DELETE THEM OR BE ASKED ABOUT EACH INDIVIDUALLY]?R(ASK, DELETE?R)[: ??]', PLIT( ASCII 'ASK', ASKEACH, ASCII 'DELET', IGNORE ), .FAKENODEPTR[ N0FIRSTCHILD ] ); CHILD _ .FAKENODEPTR[ N0FIRSTCHILD ]; ! IF HE STILL DIDN'T WANT THEM KILL TYPE( 'NODES DELETED:?M?J' ); WHILE .CHILD NEQ 0 DO BEGIN NEXT _ .CHILD[ N0RSIB ]; DETACHNODE( .CHILD ); ! ATTACH NODE TO REAL PARENT ATTACHNODE( .CHILD, .PARENT, BEFORE, 0 ); ! SO WHEN KILLNODE TRYS TO TYPE THE NAME ! IT DOESN'T BARF KILLNODES( .CHILD ); CHILD _ .NEXT END; END; CHILD _ .NODEPTR[ N0FIRSTCHILD ]; ! NOW ASK ALL ABOUT THE NEW ONES DO IF .CHILD[ N0TOBEDEFINED ] THEN ASKCHILD( .CHILD ) WHILE ( CHILD _ .CHILD[ N0RSIB ] ) NEQ 0 END; COMMENT; ! ROUTINE MNMPP ! ======= ===== ! THIS ROUTINE ASKS THE QUESTIONS NECESSARY TO MODIFY THE MPP ATTACHED ! TO THIS NODE ROUTINE MNMPP( NODEPTR ) = BEGIN OWN NEWMPP, MPPPTR; REGISTER CHILD, MPP1, MPP2; MAP FORMAT NODEPTR; MAP FORMAT MPPPTR; MAP FORMAT CHILD; IF .SHOW THEN DNMPP( .NODEPTR ); MPP1 _ MPPUP( .NODEPTR[ N0PARENT ] ); ! ANY MPPS STARTED ABOVE THIS? MPP2 _ 0; CHILD _ .NODEPTR[ N0FIRSTCHILD ]; WHILE .CHILD NEQ 0 DO ! OR BELOW ? BEGIN MPPPTR _ MPPDOWN( .CHILD ); IF .MPP1 EQL 0 THEN MPP1 _ .MPPPTR ELSE IF ( .MPP2 EQL 0 ) AND ( .MPPPTR NEQ .MPP1 ) THEN MPP2 _ .MPPPTR; CHILD _ .CHILD[ N0RSIB ] END; IF .MPP2 NEQ 0 THEN BEGIN WARN( 18 ); RETURN FALSE END; MPPPTR _ .MPP1; NEWMPP _ ASKYESORNO( 'DO YOU WISH AN [MPP TO START NOW]?R(, YES, NO?R)[: ??', -1 ); IF .NEWMPP EQL -1 THEN RETURN FALSE; ! NO CHANGE IF .NEWMPP EQL NO THEN BEGIN UNATTACH( MPPPTR[ M0LISTPTRS ], .NODEPTR, N0MPPOFFSETT ); NODEPTR[ N0MPPPTR ] _ 0; RETURN FALSE END; IF .MPPPTR NEQ 0 THEN BEGIN ATTACH( MPPPTR[ M0LISTPTRS ], .NODEPTR, N0MPPOFFSETT ); NODEPTR[ N0MPPPTR ] _ .MPPPTR END ELSE BEGIN IF ( MPPPTR _ MAKUMPP( .NODEPTR, PAZ '[NEW MPP] TO START?R(,?R)[: ??]' ) ) NEQ 0 THEN BEGIN NODEPTR[ N0MPPPTR ] _ .MPPPTR; ASKTHRESH( .NODEPTR ); RETURN TRUE END END; FALSE END; COMMENT; ! ROUTINE MNTHRESH ! ======= ======== ! THIS ROUTINE ALLOWS THE USER TO CHANGE THE STARTING CRITERION ON A ! NODE ROUTINE MNTHRESH( NODEPTR ) = BEGIN OWN NEWTHRESH; MAP FORMAT NODEPTR; IF .NODEPTR[ N0MPPPTR ] EQL 0 THEN RETURN(ERROR(131)); IF .SHOW THEN DNTHRESH( .NODEPTR ); NEWTHRESH _ ASKDNUM( '[NEW STARTING CRITERION]?R(, ?R)[: ??]', DEFAULTOK, -1, 1, BIGNUMBER ); IF .NEWTHRESH GEQ 0 THEN NODEPTR[ N0THRESH ] _ .NEWTHRESH END; COMMENT; ! ROUTINE MLQUOTA ! ======= ======= ! THIS ROUTINE ALLOWS THE USER TO CHANGE THE IN CORE QUOTA ON A LEAF ! ==== ROUTINE MLQUOTA( LEAFPTR ) = BEGIN OWN NEWQUOTA; MAP FORMAT LEAFPTR; IF .LEAFPTR[ N0CHILDREN ] NEQ 0 THEN BEGIN ERROR( 101 ); ! COMPLAIN THAT THIS ISN'T A LEAF RETURN END; ! ELSE ! IF .SHOW THEN DLQUOTA( .LEAFPTR ); !OTHERWISE SHOW CURRENT STATUS NEWQUOTA _ ASKDNUM( '[NEW QUOTA]?R(, ?R)[: ??]', DEFAULTOK, -1, 0, BIGNUMBER ); IF .NEWQUOTA GEQ 0 THEN LEAFPTR[ N0QUOTA ] _ .NEWQUOTA END; COMMENT; ! ROUTINE MLISTAT ! ======= ======= ! THIS ROUTINE ALLOWS THE USER TO CHANGE THE INITIAL INPUT STATUS ON A LEAF ! ==== ROUTINE MLISTAT( LEAFPTR ) = BEGIN OWN NEWISTAT; MAP FORMAT LEAFPTR; IF .LEAFPTR[ N0CHILDREN ] NEQ 0 THEN BEGIN ERROR( 101 ); ! COMPLAIN THAT THIS ISN'T A LEAF RETURN END; ! ELSE ! IF .SHOW THEN DLISTAT( .LEAFPTR ); !OTHERWISE SHOW CURRENT STATUS NEWISTAT _ ASKSTAT( PAZ '[NEW INITIAL INPUT STATUS]?R(, ENABLED, DISABLED?R)[: ??]', -1 ); IF .NEWISTAT GEQ 0 THEN LEAFPTR[ N0STATUS ] _ .NEWISTAT END; FORWARD ZAPTRCODE; COMMENT; ! ROUTINE MLTRCODE ! ======= ======== ! THIS ROUTINE ALLOWS THE USER TO CHANGE THE TRCODE ON A LEAF ! ==== ROUTINE MLTRCODE( LEAFPTR ) = BEGIN OWN NEWTRCODE; LABEL LOOP; MAP FORMAT NEWTRCODE; MAP FORMAT LEAFPTR; IF .LEAFPTR[ N0CHILDREN ] NEQ 0 THEN BEGIN ERROR( 101 ); ! COMPLAIN THAT THIS ISN'T A LEAF RETURN END; ! ELSE ! IF .SHOW THEN DLTRCODE( .LEAFPTR ); NEWTRCODE _ GMEM( .TRCSIZE ); NEWTRCODE[ TR0SIZE ] _ .TRCSIZE; NEWTRCODE[ TR0CHAR ] _ .TRCLEN; LOOP: REPEAT BEGIN IF ASKBITS( '[NEW TR]ANSACTION [CODE]?R(, ?R)[: ??]', NEWTRCODE[ TR0CODE], .TRCLEN ) EQL CRONLY THEN RETURN ZAPTRCODE( .NEWTRCODE ) ELSE BEGIN IF NOT TRCODESAME( .LEAFPTR, NEWTRCODE[ TR0CODE ] ) THEN BEGIN ZAPTRCODE( .LEAFPTR[ N0TRCODE ] ); LEAFPTR[ N0TRCODE ] _ .NEWTRCODE; RETURN END END; WARN( 0 ) END END; COMMENT; ! ROUTINE ZAPTRCODE ! ======= ========= ! THIS ROUTINE DELETES A TRCODE ENTRY GLOBAL ROUTINE ZAPTRCODE( TRCODEPTR ) = BEGIN MAP FORMAT TRCODEPTR; PMEM( .TRCODEPTR, .TRCODEPTR[ TR0SIZE ] ) END; COMMENT; ! ROUTINE MLONAME ! ======= ======= ! THIS ROUTINE ALLOWS THE USER TO CHANGE THE NAME FOR OUTPUT OF A LEAF ! ==== ROUTINE MLONAME( LEAFPTR ) = BEGIN OWN NEWNAME; MAP FORMAT LEAFPTR; IF .LEAFPTR[ N0CHILDREN ] NEQ 0 THEN BEGIN ERROR( 101 ); ! COMPLAIN THAT THIS ISN'T A LEAF RETURN END; IF .SHOW THEN DLONAME( .LEAFPTR ); NEWNAME _ ASKYESORNO( 'IS THIS LEAF TO BE USED FOR OUTPUT NOW?R(, YES, NO?R)[: ??]', -1 ); IF .NEWNAME GEQ 0 THEN LEAFPTR[ N0OPFLAG ] _ .NEWNAME; IF NOT .LEAFPTR[ N0OPFLAG ] THEN BEGIN ZERO( LEAFPTR[ N0OPNAME ], LEAFPTR[ N0OPNAME ] + N0NAMELEN ); RETURN END; ASKLINE( '[NEW NAME FOR OUTPUT]?R(, "", ?R)[: ??]' ); IF EOL( ACHAR ) THEN RETURN; ! NO CHANGE IF MATCHALINE( ( PAZ '')<36,7> ) THEN NEWNAME _ LEAFPTR[ N0NAME ] ELSE NEWNAME _ ABUFF; MOVE( %FROM% .NEWNAME, %TO% LEAFPTR[ N0OPNAME ], N0NAMELEN ) END; COMMENT; ! ROUTINE MLOSTAT ! ======= ======= ! THIS ROUTINE ALLOWS THE USER TO CHANGE THE INITIAL OUTPUT STATUS ON A LEAF ! ==== ROUTINE MLOSTAT( LEAFPTR ) = BEGIN OWN NEWOSTAT; MAP FORMAT LEAFPTR; IF .LEAFPTR[ N0OPNAME ] EQL 0 THEN RETURN; ! IF NO OPNAME THEN NO OPSTATUS IF .LEAFPTR[ N0CHILDREN ] NEQ 0 THEN BEGIN ERROR( 101 ); ! COMPLAIN THAT THIS ISN'T A LEAF RETURN END; ! ELSE ! IF .SHOW THEN DLOSTAT( .LEAFPTR ); !OTHERWISE SHOW CURRENT STATUS NEWOSTAT _ ASKSTAT( PAZ '[NEW INITIAL OUTPUT STATUS]?R(, ENABLED, DISABLED?R)[: ??]', -1 ); IF .NEWOSTAT GEQ 0 THEN LEAFPTR[ N0OPSTATUS ] _ .NEWOSTAT END; COMMENT; ! ROUTINE MLCHKPNT ! ======= ======== ! THIS ROUTINE MODIFIES THE VALUE OF THE CHECKPOINT-TRANSACTIONS-TO-THIS-LEAF FLAG ROUTINE MLCHKPNT( LEAFPTR ) = BEGIN MAP FORMAT LEAFPTR; LOCAL NEWCHKPNT; IF .LEAFPTR[N0CHILDREN] NEQ 0 THEN RETURN(ERROR(101)); %NOT A LEAF% IF .SHOW THEN DLCHKPNT( .LEAFPTR ); NEWCHKPNT _ ASKYESORNO('[ARE TRANSACTIONS TO THIS LEAF TO BE CHECKPOINTED NOW ?R(,YES,NO?R): ]',-1); IF NEWCHKPNT GEQ 0 THEN LEAFPTR[N0CHKPNT] _ NEWCHKPNT END; FORWARD DELNODE(1),KILLNODES(); ! ROUTINE DELENODE ! ======= =========== ! THIS ROUTINE HANDLES THE INDIVIDUAL CASES OF DELETE NODE:... ! CASE 1: IF AN INDIVIDUAL NODE IS REQUESTED ( BY NAME ), DELNODE IS ! CALLED WITH THE ADDRESS OF THE NODE TABLE ENTRY ! CASE 2: IF /ALL WAS SPECIFIED, DELNODE IS CALLED FOR EACH ENTRY IN ! NODE TABLE ! CASE 3: IF NO NAME OR SWITCH WAS GIVEN, THE USER IS ASKED FOR THE ! NAMES OF THE NODES TO BE DELETED GLOBAL ROUTINE DELENODE(NODENAME)= BEGIN REGISTER NODEPTR; MAP ROOTFORMAT ROOT; MAP FORMAT NODEPTR; IF .ROOT[ N0CHILDREN ] EQL 0 THEN RETURN ERROR( 38 ); IF NULLNODENAME(.NODENAME) AND NOT .ALLSWITCH THEN BEGIN ! ASK THE USER FOR NODE NAMES REPEAT ! UNTIL HE INPUTS A BY BEGIN ! ITSELF IF INNODE( PAZ '[NODENAME]?R(,?R)[: ??') EQL 0 THEN IF NOT .ERRORFLG THEN RETURN ELSE BEGIN ERRORFLG _ 0; ERROR( 88 ); ! TELL THE USER AND ASK AGAIN WARN( 0 ) END ELSE IF (NODEPTR _ GETNODEPTR(PRIM)) EQL 0 THEN RETURN(ERROR(33)) ELSE DELNODE(.NODEPTR); CRLF END END; IF .DELTYPEFLAG THEN TYPE( 'NODES DELETED:[?M?J]' ); IF .ALLSWITCH THEN BEGIN IF NOT(CONFIRMED()) THEN RETURN; KILLNODES( ROOT<0,0> ); RETURN END; IF (NODEPTR _ GETNODEPTR(.NODENAME)) EQL 0 THEN RETURN(ERROR(33)) ELSE DELNODE(.NODEPTR); END; COMMENT; ! ROUTINE KILLNODES ! ======= =========== ! THIS ROUTINE DELETES ALL NODES UNDER ( & INCLUDING ) THE NODE SPECIFIED ! TREE SEARCH KILL --- KILL LOWEST LEVELS ( LEAVES ) FIRST ! UNATTACH MPPLINKS ! PMEM( NODEPTR, N0SIZE ) ******* IF (WHEN) ROOT DON'T KILL ****** GLOBAL ROUTINE KILLNODES( NODEPTR ) = BEGIN %LOCAL% ROUTINE KILLER( NODE ) = BEGIN REGISTER MPPADDR, SIB; MAP FORMAT NODE; MAP FORMAT MPPADDR; IF .NODE[N0CHILDREN] NEQ 0 THEN BEGIN KILLER( .NODE[N0FIRSTCHILD] ); NODE[N0CHILDREN] _ 0; END; MPPADDR _ .NODE[N0MPPPTR]; IF .MPPADDR NEQ 0 THEN UNATTACH( %FROM% MPPADDR[M0LISTPTRS], .NODE, N0MPPOFFSETT ); SIB _ .NODE[N0RSIB]; IF .MSGLEVEL EQL 0 THEN BEGIN DFULL( .NODE ); TYPECRLF END; ZAPTRCODE( .NODE[ N0TRCODE ] ); ! FREE UP THE TRCODE'S STORE PMEM( .NODE, N0SIZE ); IF .SIB NEQ 0 THEN KILLER( .SIB ) END; REGISTER SIB, PARENT; MAP FORMAT NODEPTR; MAP FORMAT PARENT; MAP FORMAT SIB; IF .NODEPTR NEQ ROOT<0,0> THEN BEGIN DETACHNODE( .NODEPTR ) END ELSE BEGIN PARENT _ .NODEPTR; NODEPTR _ .NODEPTR[ N0FIRSTCHILD ]; PARENT[ N0CHILDREN ] _ 0 END; IF .NODEPTR EQL 0 THEN RETURN; ! NOTHING TO KILL KILLER( .NODEPTR ) END; COMMENT; ! ROUTINE DELNODE ! ======= ======= ! THIS ROUTINE DELETES THE NODE SPECIFIED FROM THE NODE TABLE ! RETURNS THE ADDRESS OF THE NEXT NODE IN THE NODE TABLE ROUTINE DELNODE(NODEPTR)= BEGIN REGISTER OLDMSGLEVEL, MPPADDR; OWN PARENT, LSIB, RSIB, LASTCHILD, FIRSTCHILD, NODE; MAP FORMAT NODEPTR; MAP FORMAT PARENT; MAP FORMAT LSIB; MAP FORMAT RSIB; MAP FORMAT LASTCHILD; MAP FORMAT FIRSTCHILD; MAP FORMAT NODE; MAP FORMAT MPPADDR; IF .NODEPTR EQL ROOT<0,0> THEN RETURN ERROR( 102 ); ! CAN'T KILL THE ROOT IF .MSGLEVEL EQL 0 THEN BEGIN DFULL( .NODEPTR ); TYPECRLF; END; PARENT _ .NODEPTR[N0PARENT]; LSIB _ .NODEPTR[N0LSIB]; RSIB _ .NODEPTR[N0RSIB]; IF .NODEPTR[N0CHILDREN] NEQ 0 THEN BEGIN NODE _ FIRSTCHILD _ .NODEPTR[N0FIRSTCHILD]; WHILE .NODE NEQ 0 DO BEGIN NODE[N0PARENT] _ .PARENT; NODE _ .NODE[N0RSIB] END; LASTCHILD _ .NODEPTR[N0LASTCHILD]; IF .LSIB NEQ 0 THEN LSIB[N0RSIB] _ .FIRSTCHILD ELSE PARENT[N0FIRSTCHILD] _ .FIRSTCHILD; IF .RSIB NEQ 0 THEN RSIB[N0LSIB] _ .LASTCHILD ELSE PARENT[N0LASTCHILD] _ .LASTCHILD; FIRSTCHILD[N0LSIB] _ .LSIB; LASTCHILD[N0RSIB] _ .RSIB END ELSE BEGIN IF .LSIB EQL 0 THEN PARENT[N0FIRSTCHILD] _ .RSIB ELSE LSIB[N0RSIB] _ .RSIB; IF .RSIB EQL 0 THEN PARENT[N0LASTCHILD] _ .LSIB ELSE RSIB[N0LSIB] _ .LSIB END; MPPADDR _ .NODEPTR[N0MPPPTR]; IF .MPPADDR NEQ 0 THEN UNATTACH( %FROM% MPPADDR[M0LISTPTRS], .NODEPTR, N0MPPOFFSETT ); IF .MPPADDR[ M0LISTPTRS ] EQL 0 AND .MPPADDR[ M0TOBEDEFINED ] THEN ! QUIETLY DELETE MPP IF NOT REFERENCE BEGIN OLDMSGLEVEL _ .MSGLEVEL; MSGLEVEL _ 1; ! SHORT OUTPUT DELMPP( .MPPADDR ); MSGLEVEL _ .OLDMSGLEVEL END; ZAPTRCODE( .NODEPTR[ N0TRCODE ] ); ! FREE UP THE TRCODE'S STORE PMEM(.NODEPTR,N0SIZE) END; COMMENT; ! ROUTINE NUMNODES ! ======= ======== ! THIS ROUTINE NUMBERS THE NODES GLOBAL ROUTINE NUMNODES = BEGIN OWN II[4]; MAP ROOTFORMAT ROOT; %LOCAL% ROUTINE NUMALLNODES(ARG, LVL)= BEGIN REGISTER NODEPTR; MAP FORMAT NODEPTR; MACRO NAME = NODEPTR[N0NAME]$, NEXTTHIS = NODEPTR[N0RSIB]$, NEXTLEVEL = NODEPTR[N0FIRSTCHILD]$, LEAF = (.NEXTLEVEL EQL 0)$; LABEL B; NODEPTR_.ARG; B: REPEAT BEGIN NODEPTR[N0NO] _ II[.LVL] _ .II[.LVL] + 1; IF LEAF THEN NODEPTR[N0LEAFNO] _ LL _ .LL + 1 ELSE NUMALLNODES(.NEXTLEVEL, .LVL + 1); WHILE .NEXTTHIS EQL 0 DO RETURN; IF(NODEPTR_.NEXTTHIS) EQL 0 THEN LEAVE B; END END; LL _ II[0] _ II[1] _ II[2] _ II[3] _ -1; NUMALLNODES( .ROOT[N0FIRSTCHILD] , 1 ) END; FORWARD WCNNAME(1), WNLVLNO, WCNOTHER; COMMENT; ! ROUTINE WCNODE ! ======= ====== ! THIS ROUTINE WRITES THE NODE SECTION OF THE COMPILE FILE GLOBAL ROUTINE WCNODE= BEGIN REGISTER NODEPTR; OWN COUNT; LABEL SEL1, SEL2, SEL3, SEL4; MAP FORMAT NODEPTR; MAP ROOTFORMAT ROOT; MACRO NAME = NODEPTR[N0NAME]$, NEXTTHIS = NODEPTR[N0RSIB]$, NEXTLEVEL = NODEPTR[N0FIRSTCHILD]$, LEAF = (.NEXTLEVEL EQL 0)$; %LOCAL% ROUTINE WNODE( NODEPTR, LVL ) = BEGIN MAP FORMAT NODEPTR; IF LEAF THEN ! IF LEAF THEN OUTPUT "Lnnnnn: BEGIN OUTPUTC( "L" ); OUTPUTD( .NODEPTR[N0LEAFNO] ); OUTPUT( ':?M?J' ) END; WNLVLNO( .LVL, .NODEPTR[N0NO] ); ! OUTPUT level.nnn: OUTPUT( ': ' ); IF LEAF THEN OUTPUT( 'LEAF(' ) ELSE OUTPUT( 'NODE(' ); ! OUTPUT type( WCNNAME( .NODEPTR ); ! OUTPUT name, OUTPUTCOMMA; IF .NODEPTR[N0PARENT] EQL ROOT<0,0> THEN OUTPUTC( "0" ) ELSE WCNOTHER( .LVL - 1, .NODEPTR[N0PARENT] ); ! OUTPUT parent, OUTPUTCOMMA; IF .NODEPTR[N0MPPPTR] EQL 0 THEN OUTPUT( '-1,-1' ) ELSE BEGIN WCMPPNUMBER( .NODEPTR[N0MPPPTR] ); ! OUTPUT mpp, OUTPUTCOMMA; OUTPUTD( .NODEPTR[N0THRESH] ) ! OUTPUT threshold, END; OUTPUTCOMMA; IF LEAF THEN OUTPUTC( "0" ) ELSE WCNOTHER( .LVL + 1, .NODEPTR[N0FIRSTCHILD] ); ! OUTPUT firstchild, OUTPUTCOMMA; IF .NODEPTR[N0RSIB] EQL 0 THEN IF .LVL EQL 1 THEN OUTPUT( 'ERLEAF' ) ELSE OUTPUTC( "0" ) ELSE WCNOTHER( .LVL, .NODEPTR[N0RSIB] ); ! OUTPUT next sib, OUTPUTCOMMA; OUTPUTD( .LVL - 1 ); ! OUTPUT level IF LEAF THEN ! IF LEAF THEN BEGIN OUTPUTCOMMA; ! OUTPUT "," OUTPUTD( .NODEPTR[N0QUOTA] ); ! OUTPUT leaf quota, OUTPUTCOMMA; IF .NODEPTR[N0STATUS]THEN OUTPUT( 'ENABLED,' ) ELSE OUTPUT( 'DISABLED,' ); ! OUTPUT status) IF NOT .NODEPTR[N0CHKPNT] THEN OUTPUT('NO'); OUTPUT('CHKPNT'); END; OUTPUT( ')?M?J?M?J' ); ! END THE MACRO CALL END; %LOCAL% ROUTINE WALLNODES( ARG, LVL )= BEGIN REGISTER NODEPTR; MAP FORMAT NODEPTR; LABEL B; NODEPTR_.ARG; B: REPEAT BEGIN WNODE( .NODEPTR, .LVL ); IF NOT LEAF THEN WALLNODES(.NEXTLEVEL, .LVL + 1 ); WHILE .NEXTTHIS EQL 0 DO RETURN; IF(NODEPTR_.NEXTTHIS) EQL 0 THEN LEAVE B; END END; %LOCAL% ROUTINE OUTPUTTRCODE( TRCODEPTR ) = BEGIN MAP FORMAT TRCODEPTR; REGISTER FILL; OUTPUT( ' GETSTR(<<' ); OUTPUTSTR( TRCODEPTR[ TR0CODE ], IF .TRCODEPTR[ TR0CHAR ] LEQ .TRCLEN THEN .TRCODEPTR[ TR0CHAR ] ELSE .TRCLEN ); IF ( FILL _ .TRCODEPTR[ TR0CHAR ] - .TRCLEN ) GTR 0 THEN DECR I FROM .FILL - 1 TO 0 DO OUTPUT( ',^O0' ); OUTPUT( '>>, TRCSIZ, TRANSACTION CODE)?M?J' ) END; %LOCAL% ROUTINE WTRCODE( ARG )= BEGIN REGISTER TRCODE, NODEPTR; MAP FORMAT NODEPTR; MAP FORMAT TRCODE; LABEL B; NODEPTR_.ARG; B: REPEAT BEGIN IF LEAF THEN BEGIN OUTPUTTRCODE( .NODEPTR[ N0TRCODE ] ) END ELSE WTRCODE( .NEXTLEVEL ); WHILE .NEXTTHIS EQL 0 DO RETURN; IF(NODEPTR_.NEXTTHIS) EQL 0 THEN LEAVE B; END END; %LOCAL% ROUTINE WLEAFNO( ARG )= BEGIN REGISTER NODEPTR; MAP FORMAT NODEPTR; LABEL B; NODEPTR_.ARG; B: REPEAT BEGIN IF LEAF THEN BEGIN OUTPUT( ' EXP L' ); OUTPUTD( .NODEPTR[N0LEAFNO] ); OUTPUTCRLF END ELSE WLEAFNO( .NEXTLEVEL ); WHILE .NEXTTHIS EQL 0 DO RETURN; IF(NODEPTR_.NEXTTHIS) EQL 0 THEN LEAVE B; END END; %LOCAL% ROUTINE WLFTAB( ARG )= BEGIN REGISTER NODEPTR; MAP FORMAT NODEPTR; LABEL B; NODEPTR_.ARG; B: REPEAT BEGIN IF ( LEAF ) AND ( .NODEPTR[N0OPFLAG] ) THEN BEGIN OUTPUT( '?I%LFTAB(' ); XOUTPUT( NODEPTR[N0OPNAME] ); OUTPUT( ', L' ); OUTPUTD( .NODEPTR[N0LEAFNO] ); OUTPUTCOMMA; IF .NODEPTR[N0OPSTATUS] THEN OUTPUT( 'ENABLED' ) ELSE OUTPUT( 'DISABLED' ); OUTPUT( ')?M?J' ) END; IF NOT LEAF THEN WLFTAB( .NEXTLEVEL ); WHILE .NEXTTHIS EQL 0 DO RETURN; IF(NODEPTR_.NEXTTHIS) EQL 0 THEN LEAVE B; END END; ! OUTPUT MACROS OUTPUT( '?L SUBTTL TREE?M?J' ); OUTPUT( 'IF1, ?M?J' ); OUTPUT( ' LEAFNO=-1?M?J' ); OUTPUTCRLF; OUTPUT( 'TREE:: .+1 ; NEXT WORD MUST BE # OF LEAVES?M?J'); OUTPUT(' EXP LFCNT ;NUMBER OF LEAVES IN THE TREE?M?J'); OUTPUT( ' ; FIRST NODE OF THE TREE?M?J?M?J?M?J' ); WALLNODES( .ROOT[N0FIRSTCHILD], 1 ); OUTPUT( ' LFCNT=LEAFNO+1 ; DON''T COUNT THE ERROR LEAF?M?J' ); OUTPUT( ' ; OR THE OTHER LOCAL MPP LEAVES?M?J' ); OUTPUTCRLF; COUNT _ .LL + 5; OUTPUT('ERLEAF:: LEAF(,0,M.ERR,1,0,SONLEAF,0,-1,ENABLED)?M?J?IERRLN==LEAFNO?M?J?M?J' ); OUTPUT( 'SONLEAF:: LEAF(,0,M.SON,1,0,SOFFLEAF,0,-1,ENABLED)?M?J?ISONLN==LEAFNO?M?J?M?J' ); OUTPUT( 'SOFFLEAF:: LEAF(,0,M.SOFF,1,0,DCRLEAF,0,-1,ENABLED)?M?J?ISOFFLN==LEAFNO?M?J?M?J' ); OUTPUT( 'DCRLEAF:: LEAF(,0,M.RDMC,1,0,DMRLEAF,0,-1,ENABLED)?M?J?IDCRLN==LEAFNO?M?J?M?J' ); OUTPUT( 'DMRLEAF:: LEAF(,0,M.RDM,1,0,0,0,-1,ENABLED)?M?J?IDMRLN==LEAFNO?M?J?M?J'); OUTPUT( 'ALLEAVES=LEAFNO?M?J' ); OUTPUTCRLF; OUTPUT( 'LEAFDSKADDR:: BLOCK ALLEAVES+1?M?J' ); OUTPUTCRLF; OUTPUT( 'LFPTRTAB::?M?J' ); WLEAFNO( .ROOT[N0FIRSTCHILD] ); OUTPUT( ' EXP ERLEAF?M?J' ); OUTPUT( ' EXP SONLEAF?M?J' ); OUTPUT( ' EXP SOFFLEAF?M?J' ); OUTPUT( ' EXP DCRLEAF?M?J' ); OUTPUT( ' EXP DMRLEAF?M?J' ); ! MAKE TRCODE TABLE OUTPUT( '?L?ISUBTTL TRCODE & LFADDR TABLES?M?J?M?J' ); OUTPUT( ';TRCODE TABLE::?M?J?I' ); OUTPUTD( .COUNT ); OUTPUT( '?M?JTRCODE::?M?J' ); WTRCODE( .ROOT[N0FIRSTCHILD] ); OUTPUTTRCODE( .SON ); OUTPUTTRCODE( .SOFF ); OUTPUTTRCODE( .RDM ); OUTPUTTRCODE( .RDMC ); OUTPUTCRLF; OUTPUTCRLF; OUTPUT( ';LFADDR TABLE?M?J?I' ); OUTPUTD( .COUNT ); OUTPUT( '?M?JLFADDR::?M?J' ); WLEAFNO( .ROOT[N0FIRSTCHILD] ); OUTPUT( ' EXP SONLEAF?M?J' ); OUTPUT( ' EXP SOFFLEAF?M?J' ); OUTPUT( ' EXP DMRLEAF?M?J' ); OUTPUT( ' EXP DCRLEAF?M?J' ); ! MAKE LFTAB OUTPUT( '?L?ISUBTTL LEAF TABLE?M?J?M?J?M?JLFTAB::EXP .?M?J' ); WLFTAB( .ROOT[N0FIRSTCHILD] ); OUTPUT( '?M?J?I%LFTAB() ; THIS MUST BE THE LAST ENTRY IN LFTAB' ); OUTPUTCRLF; END; COMMENT; ! ROUTINE WCNNAME ! ======= ======== ! THIS ROUTINE WRITES THE NODE NAME TO THE COMPILE FILE ROUTINE WCNNAME(NODEPTR)= BEGIN MAP FORMAT NODEPTR; XOUTPUT(NODEPTR[N0NAME]) END; ROUTINE WNLVLNO( LVL, NO ) = BEGIN CASE .LVL - 1 OF SET %0% OUTPUT( 'P.' ); %1% OUTPUT( 'S1.' ); %2% OUTPUT( 'S2.' ); %3% OUTPUT( 'S3.' ); TES; OUTPUTD( .NO ) END; ROUTINE WCNOTHER( LVL, NODEPTR ) = BEGIN MAP FORMAT NODEPTR; BIND ENDOFMGNND=1; WNLVLNO( .LVL, .NODEPTR[N0NO] ); END; ! END OF MGNND.BLI