!***COPYRIGHT (C) 1974, 1975, 1976, 1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.*** ! MGNPT.BLI ! ========= ! PORT MANIPULATION ROUTINES FOR THE MCS CONFIGURATION GENERATOR ! **** LAST MODIFIED 29-JUN-76 ILG MODULE PORT(SREG = #17, FREG = #16, VREG = #15, MLIST,TIMER=EXTERNAL(SIX12),FSAVE)= BEGIN ! THIS MODULE CONTAINS THOSE ROUTINES REQUIRED TO HANDLE PORT GENERATIONS GLOBAL BIND PT = 1; REQUIRE MGNMAC.BLI; REQ(MGNEXT); REQ(MGNMC2); EXTERNAL MOVE, LINK, UNLINK, COMPARE, MAKUTERM, DTERMCNAME, WCTNM; COMMENT; ! ROUTINE PTUNHOOK ! ======= ======== ! THIS ROUTINE BREAKS THE CONNECTION BETWEEN A PORT AND A TERMINAL ! USED WHEN DELETEING PORT OR ! TERMINAL GLOBAL ROUTINE PTUNHOOK( PORTADDR ) = BEGIN REGISTER TERMADDR; MAP FORMAT PORTADDR; MAP FORMAT TERMADDR; TERMADDR _ .PORTADDR[PT0SRCPTR]; PORTADDR[PT0SRCPTR] _ 0; TERMADDR[T0PORTPTR] _ 0 NOTE; MIGHT IT BE NICE TO INFORM THE USER OF THE BREAK? END; COMMENT; ! ROUTINE PRINTPORTNAME ! ======= ============= ! OUTPUTS PORTNAME TO CONTROLLING TTY ROUTINE PRINTPORTNAME( PORTNAME ) = BEGIN TYPE( 'FOR [PORT ]'); OUTSA( .PORTNAME ); TYPE( '[:?M?J]' ) END; COMMENT; ! ROUTINE INPORT ! ======= ====== ! THIS ROUTINE ASKS FOR AND ACCEPTS A PORT NAME FROM THE USER ROUTINE INPORT(A)= BEGIN LOCAL NONEFLG; NONEFLG _ FALSE; 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 ! FUDGE TO ACCEPT "" AS AN ANSWER IF .ACHAR EQL "<" THEN BEGIN NONEFLG _ TRUE; ADV(ABUFF,ABPTR,ACOUNT,ACHAR); END; IF NOT .ERRORFLG THEN GETNAME(ALINE,ACHAR); ! IF NO ERROR ACCEPTING THE LINE THEN GATHER A NAME IF .ACHAR EQL ">" AND .PRIM[0] EQL 'NONE' AND .NONEFLG THEN BEGIN ADV(ABUFF,ABPTR,ACOUNT,ACHAR); !EAT THE TRAILING ">" PRIM[0] _ NONETOKEN; !SET TOKEN TO NONE END; IF NOT .ERRORFLG THEN TOOMUCHINPUT(); ! IF NOT END OF LINE THEN ERROR IF NOT .ERRORFLG THEN IF SUBQUEUES() OR .PERIODS NEQ 0 THEN ERROR( 15 ); ! IF STILL NO ERRORS, SEE IF THE USER ! PUT PERIODS IN THE PORT NAME IF NOT .ERRORFLG THEN IF HYPHENIN( %IN% PRIM<0,0>, PT0NAMESIZE ) THEN ERROR( 110 ); ! IF HYPHEN ! IN THE PORT NAME THEN ERROR IF .ERRORFLG THEN 0 ELSE 1 ! IF ERROR IN ANY PART, RETURN 0 ELSE 1 END; COMMENT; ! ROUTINE NUMPT ! ======= ===== ! THIS ROUTINE NUMBERS ALL THE PORTS GLOBAL ROUTINE NUMPT = BEGIN REGISTER I, PORTADDR; MAP FORMAT PORTADDR; PORTADDR _ .PORTTAB; ! GET FIRST PORT I _ 0; WHILE .PORTADDR NEQ 0 DO ! FOR EACH PORT BEGIN PORTADDR[PT0PORTNO] _ I _ .I + 1; ! INCREMENT OUT PORT COUNTER AND STORE IN THE PORT NUMBER FIELD PORTADDR _ .PORTADDR[PT0FORE] ! GET NEXT PORT END END; COMMENT; ! ROUTINE CREATEPORT ! ======= ========== ! THIS ROUTINE STUFFS A NEW PORT IN THE PORTTAB ! INPUT POINTER TO PORTNAME ! OUTPUT POINTER TO PORT TABLE ENTRY ROUTINE CREATEPORT( PORTNAME ) = BEGIN REGISTER PORTADDR; MAP FORMAT PORTADDR; PORTADDR _ GMEM(PT0SIZE); PORTADDR[PT0LINKS] _ 0; MOVE( %FROM% .PORTNAME, %TO% PORTADDR[PT0NAME], PT0NAMELEN %WORDS%); LINK( %TO% PORTTAB, PORTADDR[PT0LINKS]); .PORTADDR END; COMMENT; ! ROUTINE NULLPORTNAME ! ======= ============ ! THIS ROUTINE RETURNS TRUE IF THE PORTNAME IS NULL ROUTINE NULLPORTNAME(LOC) = BEGIN RETURN IF ..LOC EQL 0 THEN TRUE ELSE FALSE END; FORWARD GETPORTADDR(1); COMMENT; ! ROUTINE MAKUPORT ! ======= ======== ! THIS ROUTINE MAKES A PORT TO ATTACH TO A TERMINAL GLOBAL ROUTINE MAKUPORT( TERMADDR, UTYPE ) = BEGIN OWN DONE, PORTADDR; MAP FORMAT PORTADDR; MAP FORMAT TERMADDR; %LOCAL% ROUTINE TRYANOTHER = BEGIN WARN( 0 ) END; %LOCAL% ROUTINE SETSRC( TERMADDR ) = BEGIN PORTADDR[PT0SRCPTR] _ .TERMADDR; DONE _ TRUE END; %LOCAL% ROUTINE FIXUP( TERMADDR ) = BEGIN PTUNHOOK( .PORTADDR ); SETSRC( .TERMADDR ) END; LABEL LOOP1, LOOP2; DONE _ FALSE; LOOP1: REPEAT ! UNTIL WE GET AN ACCEPTABLE ANSWER BEGIN LOOP2: REPEAT ! UNTIL WE GET A GOOD PORT NAME BEGIN IF .UTYPE EQL MODTYPE THEN TYPE( '[NEW ]' ); TYPE( 'ATTACHED [PORT]?R(' ); IF .UTYPE EQL MODTYPE THEN TYPE( ',' ); IF INPORT( PAZ '"",?R)[: ??]') EQL 0 THEN IF NOT .ERRORFLG THEN BEGIN IF .UTYPE EQL MODTYPE THEN RETURN -1; !ELSE! ERROR( 89 ); WARN( 0 ) END ELSE BEGIN ! IF THE ANSWER WAS UNACCEPTABLE ERROR( 86 ); ! TELL THE USER AND ASK AGAIN WARN( 0 ) END ELSE LEAVE LOOP2 END; ! WE GOT A PORT NAME IF .PRIM[0] EQL NONETOKEN THEN RETURN 0; !IF SAID "" IF (PORTADDR _ GETPORTADDR( PRIM<36,7> )) EQL 0 THEN BEGIN PORTADDR _ CREATEPORT( PRIM<36,7> ); SETSRC( .TERMADDR ); LEAVE LOOP1 END ELSE BEGIN IF .PORTADDR[PT0SRCPTR] EQL 0 THEN BEGIN SETSRC(.TERMADDR); IF .DONE THEN LEAVE LOOP1 END ELSE ERROR(130) END END; .PORTADDR END; FORWARD ACCEPTPORT(1); COMMENT; ! ROUTINE MAKEPORT ! ======= ======== ! GIVEN THE ADDRESS OF A PORTNAME, THIS ROUTINE CAUSE THE APPROPRIATE ! CHECKS ON THE NAME AND ACTUALLY CREATES THE SPACE GLOBAL ROUTINE MAKEPORT(PORTNAME)= BEGIN REGISTER PORTADDR; MAP FORMAT PORTADDR; IF .ALLSWITCH THEN RETURN(ERROR(25)); IF SUBQUEUES() OR .PERIODS NEQ 0 THEN RETURN( ERROR( 15 ) ); ! PERIODS IN A PORT NAME ARE NO NO'S IF HYPHENIN( .PORTNAME, PT0NAMESIZE ) THEN RETURN ERROR( 110 ); ! IF HYPHEN IN PORTNAME RETURN ERROR IF NULLPORTNAME(.PORTNAME) THEN ! IF NO PORT SPECIFIED BEGIN ! ASK THE USER FOR PORT NAMES REPEAT ! UNTIL HE INPUTS A BY BEGIN ! ITSELF IF INPORT( PAZ '[PORTNAME]?R(,?R)[: ??') EQL 0 THEN IF NOT .ERRORFLG THEN RETURN ELSE BEGIN ! IF THE ANSWER WAS UNACCEPTABLE ERROR( 86 ); ! TELL THE USER AND ASK AGAIN WARN( 0 ) END ELSE ACCEPTPORT(PRIM<36,7>); ! IF OK NAME EXECUTE THE FUNCTION CRLF END END; ACCEPTPORT(.PORTNAME) ! IF A PORT WAS SPECIFIED, USE IT END; COMMENT; ! ROUTINE GETPORTADDR ! ======= =========== ! SEARCHES THE PORTTAB FOR THE PORTNAME CONTAINED AT THE CONTENTS OF PORTNAME ! IF FOUND, RETURNS THE ADDRESS OF THE PORT TABLE ENTRY ! OTHERWISE RETURNS 0 ROUTINE GETPORTADDR(PORTNAME) = BEGIN REGISTER PORTADDR; MAP FORMAT PORTADDR; IF TOOLONG(.PORTNAME,PT0NAMESIZE, PT0NAMELEN * 5) THEN BEGIN WARN( 3 ); TRUNCATE(.PORTNAME, PT0NAMESIZE, PT0NAMELEN * 5) END; IF ( PORTADDR _ .PORTTAB ) EQL 0 THEN RETURN 0; ! START AT THE BEGINNING ! WHILE THE NAME AT PORTNAME ISN'T THE NAME IN THE TABLE DO WHILE NOT COMPARE(.PORTNAME,PORTADDR[PT0NAME],PT0NAMELEN) DO ! IF END OF TABLE RETURN 0 IF (PORTADDR _ .PORTADDR[PT0FORE]) EQL 0 THEN RETURN 0; .PORTADDR ! A MATCH! SO RETURN THE ADDRESS END; COMMENT; ! ROUTINE ACCEPTPORT ! ======= ========== ! THIS ROUTINE CREATES A PORT TABLE ENTRY IF ONE DOES NOT EXIST ! RETURNS ERROR OTHERWISE ROUTINE ACCEPTPORT(PORTNAME)= BEGIN ! SEE IF ALREADY DEFINED IF GETPORTADDR(.PORTNAME) EQL 0 THEN BEGIN CREATEPORT( .PORTNAME ); ! MAKE A PORT TABLE ENTRY OUTS('PORT '); OUTSA(.PORTNAME); OUTS(' CREATED?M?J') END ELSE ERROR(14); !DUPLICATE PORTNAME END; FORWARD DISPORT(1); COMMENT; ! ROUTINE DISPPORT ! ======= =========== ! THIS ROUTINE HANDLES THE INDIVIDUAL CASES OF DISPLAY PORT:... ! CASE 1: IF AN INDIVIDUAL PORT IS REQUESTED ( BY NAME ), DISPORT IS ! CALLED WITH THE ADDRESS OF THE PORT TABLE ENTRY ! CASE 2: IF /ALL WAS SPECIFIED, DISPORT IS CALLED FOR EACH ENTRY IN ! PORT TABLE ! CASE 3: IF NO NAME OR SWITCH WAS GIVEN, THE USER IS ASKED FOR THE ! NAMES OF THE PORTS TO BE DISPLAYED GLOBAL ROUTINE DISPPORT(PORTNAME)= BEGIN REGISTER PORTADDR; MAP FORMAT PORTADDR; IF SUBQUEUES() OR .PERIODS NEQ 0 THEN RETURN( ERROR( 15 ) ); ! PERIODS IN A PORT NAME ARE NO NO'S IF HYPHENIN( .PORTNAME, PT0NAMESIZE ) THEN RETURN ERROR( 110 ); ! IF HYPHEN IN PORTNAME RETURN ERROR IF NULLPORTNAME(.PORTNAME) AND NOT .ALLSWITCH THEN BEGIN ! ASK THE USER FOR PORT NAMES REPEAT ! UNTIL HE INPUTS A BY BEGIN ! ITSELF IF INPORT( PAZ '[PORTNAME]?R(,?R)[: ??') EQL 0 THEN IF NOT .ERRORFLG THEN RETURN ELSE BEGIN ! IF THE ANSWER WAS UNACCEPTABLE ERROR( 86 ); ! TELL THE USER AND ASK AGAIN WARN( 0 ) END ELSE IF (PORTADDR _ GETPORTADDR(PRIM)) EQL 0 THEN RETURN(ERROR(13)) ELSE DISPORT(.PORTADDR); CRLF END END; IF .ALLSWITCH THEN BEGIN PORTADDR _ .PORTTAB; WHILE .PORTADDR NEQ 0 DO BEGIN DISPORT( .PORTADDR); PORTADDR _ .PORTADDR[PT0FORE] END; RETURN END; IF (PORTADDR _ GETPORTADDR(.PORTNAME)) EQL 0 THEN RETURN(ERROR(13)) ELSE DISPORT(.PORTADDR) END; FORWARD DPORTNAME(1), DPORTATTACHEDTERM(1); COMMENT; ! ROUTINE DISPORT ! ======= ======= ! THIS ROUTINE DISPLAYS THE PORT'S NAME, ! AND PARAMETERS ROUTINE DISPORT(PORTADDR)= BEGIN MAP FORMAT PORTADDR; DPORTNAME(.PORTADDR); DPORTATTACHEDTERM(.PORTADDR); OUTPUTCRLF END; COMMENT; ! ROUTINE DPORTNAME ! ======= ========= ! THIS ROUTINE DISPLAYS THE PORT NAME ROUTINE DPORTNAME(PORTADDR)= BEGIN MAP FORMAT PORTADDR; OUTPUT('PORTNAME: '); XOUTPUT(PORTADDR[PT0NAME]); OUTPUTCRLF END; COMMENT; ! ROUTINE DPNAME ! ======= ========= ! THIS ROUTINE DISPLAYS THE PORT NAME WITHOUT LABEL GLOBAL ROUTINE DPNAME(PORTADDR)= BEGIN MAP FORMAT PORTADDR; XOUTPUT(PORTADDR[PT0NAME]) END; COMMENT; ! ROUTINE DPORTATTACHEDTERM ! ======= ========= ! THIS ROUTINE DISPLAYS THE PORT'S ATTACHED TERMINAL ROUTINE DPORTATTACHEDTERM(PORTADDR)= BEGIN MAP FORMAT PORTADDR; OUTPUT( 'ATTACHED TERMINAL: '); IF .PORTADDR[PT0SRCPTR] NEQ 0 THEN DTERMCNAME( .PORTADDR[PT0SRCPTR]) ELSE OUTPUT( ''); OUTPUTCRLF END; COMMENT; COMMENT; ! ROUTINE DPTNAMES ! ======= =========== ! THIS ROUTINE DISPLAYS THE NAMES OF ALL PORTS IN THE PORTTAB GLOBAL ROUTINE DPTNAMES = BEGIN REGISTER PORTADDR; MAP FORMAT PORTADDR; PORTADDR _ .PORTTAB; WHILE .PORTADDR NEQ 0 DO BEGIN XOUTPUT(PORTADDR[PT0NAME]); PORTADDR _ .PORTADDR[PT0FORE]; OUTPUTCRLF END END; COMMENT; ! ROUTINE MODIPORT ! ======= ======== ! ! THIS ROUTINE TRAPS THE "MODIFY PORT:" COMMAND AND RETURNS AN ! ERROR GLOBAL ROUTINE MODIPORT(PORTNAME) = BEGIN OWN HIST33; !HIST:WAS "DONE" IN MODPORT ERROR(129) END; FORWARD DELPORT(1),KILLPORTS(); COMMENT; ! ROUTINE DELEPORT ! ======= =========== ! THIS ROUTINE HANDLES THE INDIVIDUAL CASES OF DELETE PORT:... ! CASE 1: IF AN INDIVIDUAL PORT IS REQUESTED ( BY NAME ), DELPORT IS ! CALLED WITH THE ADDRESS OF THE PORT TABLE ENTRY ! CASE 2: IF /ALL WAS SPECIFIED, DELPORT IS CALLED FOR EACH ENTRY IN ! PORT TABLE ! CASE 3: IF NO NAME OR SWITCH WAS GIVEN, THE USER IS ASKED FOR THE ! NAMES OF THE PORTS TO BE DELETED GLOBAL ROUTINE DELEPORT(PORTNAME)= BEGIN REGISTER PORTADDR; MAP FORMAT PORTADDR; IF SUBQUEUES() OR .PERIODS NEQ 0 THEN RETURN( ERROR( 15 ) ); ! PERIODS IN A PORT NAME ARE NO NO'S IF HYPHENIN( .PORTNAME, PT0NAMESIZE ) THEN RETURN ERROR( 110 ); ! IF HYPHEN IN PORTNAME RETURN ERROR IF NULLPORTNAME(.PORTNAME) AND NOT .ALLSWITCH THEN BEGIN ! ASK THE USER FOR PORT NAMES REPEAT ! UNTIL HE INPUTS A BY BEGIN ! ITSELF IF INPORT( PAZ '[PORTNAME]?R(,?R)[: ??') EQL 0 THEN IF NOT .ERRORFLG THEN RETURN ELSE BEGIN ! IF THE ANSWER WAS UNACCEPTABLE ERROR( 86 ); ! TELL THE USER AND ASK AGAIN WARN( 0 ) END ELSE IF (PORTADDR _ GETPORTADDR(PRIM)) EQL 0 THEN RETURN(ERROR(13)) ELSE DELPORT(.PORTADDR); CRLF END END; IF .DELTYPEFLAG THEN TYPE( 'PORTS DELETED:[?M?J]' ); IF .ALLSWITCH THEN BEGIN IF NOT(CONFIRMED()) THEN RETURN; KILLPORTS(); RETURN END; IF (PORTADDR _ GETPORTADDR(.PORTNAME)) EQL 0 THEN RETURN(ERROR(13)) ELSE DELPORT(.PORTADDR); END; COMMENT; ! ROUTINE KILLPORTS ! ======= =========== ! THIS ROUTINE DELETES ALL PORTS FROM THE PORTTAB GLOBAL ROUTINE KILLPORTS = BEGIN REGISTER PORTADDR; MAP FORMAT PORTADDR; PORTADDR _ .PORTTAB; WHILE .PORTADDR NEQ 0 DO PORTADDR _ DELPORT(.PORTADDR) END; COMMENT; ! ROUTINE DELPORT ! ======= ======= ! THIS ROUTINE DELETES THE PORT SPECIFIED FROM THE PORT TABLE ! RETURNS THE ADDRESS OF THE NEXT PORT IN THE PORT TABLE ROUTINE DELPORT(PORTADDR)= BEGIN OWN NEXT; MAP FORMAT PORTADDR; XTYPE( PORTADDR[PT0NAME] ); ! TYPE THE NAME OF THE PORT DELETED, IF MSGLEVEL EQL LONG TYPECRLF; NEXT _ .PORTADDR[PT0FORE]; UNLINK(%FROM% PORTTAB, .PORTADDR); IF .PORTADDR[PT0SRCPTR] NEQ 0 THEN !IF THERE'S A TERMINAL,UNHOOK IT PTUNHOOK( .PORTADDR ); ! CLEAR PORTPTR IN THE TERMTAB ENTRY POINTED TO PMEM(.PORTADDR,PT0SIZE); .NEXT END; FORWARD WCPTNAME, WCPTNM; COMMENT; ! ROUTINE WCPORT ! ======= ====== ! THIS ROUTINE WRITES THE PORT SECTION OF THE COMPILE FILE GLOBAL ROUTINE WCPORT= BEGIN ! IT IS ASSUMED THAT THE TERMINALS HAVE BEEN NUMBERED 0 THROUGH NNNNN ! THEN FOR EACH PORT ! OUTPUT PTnnnn: PORT(NAME, MODE, IF CONV THEN T# ELSE 0, SIGNON, SIGNOFF, TYPE, STATUS) REGISTER PORTADDR; MAP FORMAT PORTADDR; OUTPUT( '?L SUBTTL PORTS?M?J?M?JFREEPORTS==0?M?J?M?JPORTTAB::EXP .+1?M?J' ); PORTADDR _ .PORTTAB; WHILE .PORTADDR NEQ 0 DO BEGIN WCPTNM( .PORTADDR ); OUTPUTC( ":" ); OUTPUT(' %PORT'); XOUTPUT(PLIT ASCIZ '('); ! OUTPUT NAME, WCPTNAME(.PORTADDR); OUTPUTCOMMA; ! OUTPUT TERMINAL LABEL, OR BLANK IF NON-ASSOCIATED IF .PORTADDR[PT0SRCPTR] EQL 0 THEN OUTPUT(' ') ELSE WCTNM(.PORTADDR[PT0SRCPTR]); OUTPUT(')?M?J'); PORTADDR _ .PORTADDR[PT0FORE] END; OUTPUT( ' EXP 0 ; MUST BE LAST ENTRY IN PORT TAB?M?J' ); END; COMMENT; ! ROUTINE WCPTNAME ! ======= ======== ! THIS ROUTINE WRITES THE PORT NAME TO THE COMPILE FILE ROUTINE WCPTNAME(PORTADDR)= BEGIN MAP FORMAT PORTADDR; XOUTPUT(PORTADDR[PT0NAME]) END; COMMENT; ! ROUTINE WCPTNM ! ======= ====== ! THIS ROUTINE WRITES THE PORT NUMBER GLOBAL ROUTINE WCPTNM( PORTADDR ) = BEGIN MAP FORMAT PORTADDR; OUTPUT( 'PP' ); OUTPUTD( .PORTADDR[PT0PORTNO] ) END; COMMENT; ! ROUTINE WHATPORTS ! ======= ========= ! RETURNS GOOD IF PORTS EXIST, ELSE RETURNS BAD GLOBAL ROUTINE WHATPORTS(TELL)= BEGIN IF .PORTTAB EQL 0 THEN BEGIN ERROR(37); RETURN BAD END; GOOD END;