! !******************************************** !* !* VAX/VMS NDIAG - IMP monitors and trapped errors !* come here. This routine cycles !* down the stack, calling a lang. !* dept. routine to analyse each frame !* !************************************************* %CONST %INTEGER extramon=1 %ROUTINE %SPEC Indiag(%INTEGER LNB,GP,ADIAGS,ADIDIA,mode,diag,asize,first, %INTEGER %NAME flag) %EXTERNAL %ROUTINE %SPEC Fdiag(%INTEGER LNB,gla,PC,ADIAGS,first, %INTEGER %NAME next) !%EXTERNAL %INTEGER %MAP %SPEC COMREG %ALIAS "S#COMREGMAP"(%INTEGER n) %EXTERNAL %ROUTINE %SPEC phex(%INTEGER n) %INTEGER %FN %SPEC validate(%INTEGER ad) %OWN %INTEGER ignore %OWN %INTEGER Topad,Bottomad %EXTERNAL %LONG %REAL %FN oncond(%INTEGER event,subevent,lnb) !*********************************************************************** !* This routine runs up the stack to see if there is any imp * !* routine with a handler for the program event that has occurred * !* if there is it exits to it returning 64 bits of On info * !* otherwise it returns with 0 * !* The exit is by frigging the link in the stack frame. It is for * !* this reason the routine is external since a change of gla * !* may be needed. The routine is fairly general until the exit * !* sequence is started then highly machine dependend * !*********************************************************************** %INTEGER lang,bit,onword,i,res1,res2,tabad,gla,btype,pc,prevlnb,mylnb,status,gla offset, base lnb %CONST %INTEGER glafromlnb=-8 %IF extramon#0 %START printstring("Ontrap:"); write(event,1) printstring("/"); write(subevent,1) space; phex(lnb); newline %FINISH bit=1<<(17+event) ! baselnb=comreg(36) baselnb=x'7ffffff0' prevlnb=lnb-128 %CYCLE %RESULT=0 %IF lnb>base lnb %OR validate(lnb)#0 gla=integer(lnb+glafromlnb) %RESULT=0 %IF validate(gla)#0 lang=integer(gla+16)>>24 %IF extramon#0 %START printstring("Language="); write(lang,2); newline %FINISH %RESULT=0 %UNLESS lang=1; ! Dont cross non imp routines %FOR i=lnb,-4,prev lnb %CYCLE ->fnd %IF integer(I)=X'49444941' %REPEAT %RESULT=0 fnd: tabad=integer(Gla+20)+short integer(i-2) %RESULT=0 %IF validate(tabad)#0 btype=byteinteger(tabad+12) onword=integer((tabad+btype+16)&(-4)) %IF onword&bit#0 %THEN %EXIT prev lnb=lnb lnb=integer(lnb+12) %REPEAT ! ! on event has been found. Set up result ! res2=shortinteger(i-4); ! Eventlione res1=event<<8!subevent pc=gla+onword&x'3ffff'; ! addres of exit pc %IF validate(pc)#0 %THEN %RESULT=0 pc=integer(pc) %IF validate(pc)#0 %THEN %RESULT=0 ! ! ! find my lnb using assembler ! *put_X'D05D'; *put_X'AC04'; ! movl fp,(ap)+4 mylnb=event status=integer(mylnb+4) ! ! ! find offset of stored r11 (&r10) ! glaoffset=20 %FOR i=0,1,10 %CYCLE %IF status&1<<(I+16)#0 %THEN gla offset=gla offset+4 %REPEAT integer(mylnb+gla offset)=gla; ! His gla will load into r11 i=integer(gla+60) integer(mylnb+glaoffset-4)=i; ! His ctable to r10 integer(mylnb+8)=integer(lnb-4); ! transfer his ap integer(mylnb+12)=lnb integer(mylnb+16)=pc; ! His pc&lnb will revert %RESULT=longreal(addr(res2)) %END !************************************************************* %EXTERNAL %ROUTINE NDIAG %ALIAS "s_ndiag"(%INTEGER PC,LNB,p3,p4) !*********************************************************************** !* LNB is LNB where ndiag called but there are sometimes * !* some redundant levels to be passed over. if p4 present and ** !* between lnb and stackbase it is taken as the failing lnb ** !* This simplifies contingencies which leave junk on the stack * !*********************************************************************** %INTEGER first,line,i,gla,adiags,flag,nextlnb,prevlnb,ad,bot %OWN %INTEGER onceonly=0, diagnosing=0 %LONG %REAL dummy %if extramon#0 %start printstring(" Ndiag Entered ") printstring(" LNB = ") phex(LNB) printstring(" p3 = ") phex(p3) newline %finish Topad=addr(Topad) { Max DATA address - presumed positive } onceonly=0 diagnosing=0 i=addr(First)+24 prevlnb=0 %if p4#0 %and P4>lnb %then prev lnb=lnb %and lnb=p4 dummy=oncond(p3>>8,p3&255,lnb) %unless p3>>8=0 %IF p3#0 %START { soft error } newline %IF p3=2049 %THEN printstring("** Unnassigned Variable ** ") %ELSE %IF %C p3=2050 %THEN printstring("** Switch Bounds Exceeded ** ") %ELSE %IF %C p3=513 %THEN printstring("** Top of Stack **") %ELSE %IF p3=1537 %THEN %C printstring("** Capacity Exceeded **") %ELSE %IF p3=21 %THEN %C printstring("** No %result **") %ELSE %IF p3=1281 %THEN %C printstring("** Invalid %FOR loop **") %ELSE %IF p3=1793 %THEN %C printstring("** Resolution error **") %ELSE %IF p3=1538 %THEN %C printstring("** Array bounds check **") %ELSE %IF p3=x'505' %THEN %C printstring("** Expontiation out of bounds **") newline %FINISH flag=1 first=2 %CYCLE { through the user frames } nextlnb=integer(lnb+12) %IF ignore#0 %THEN ignore=ignore-1 %AND ->nxtfr { ignore service rt } %EXIT %IF nextlnb=0 { check bottom stack } bot=prevlnb %IF prevlnb=0 %THEN bottomad=lnb-1000 %ELSE bottomad=prevlnb %IF lnb-40>bot %THEN bot=lnb-40 { limit search area} %IF integer(lnb-8)=m'FDIA' %THEN ->fortfnd %CYCLE i=lnb,-4,bot { IDIA means IMP } { display means posn unknown } ->impfnd %IF integer(i)=x'49444941' {m'IDIA'} %REPEAT ->nxtfr fortfnd: { In case we break in FDIAG avoid looping diagnostics by ensuring we } { only call FDIAG once for each stack frame } %IF onceonly=lnb %THEN %stop %ELSE onceonly=lnb GLA=integer(lnb-4) Adiags=shortinteger(lnb-10) %IF Adiags<=0 %START %IF Adiags=0 %START %IF diagnosing#0 %THEN printstring(" Fortran subprogram compiled without diagnostics ") %FINISH %FINISH %ELSE %START i=integer(gla+20) %IF i<0 %OR (i&3)#0 %THEN printstring(" Corrupt Data for Fortran subprogram ") %AND ->nxtfr diagnosing=1 Adiags=i+Adiags flag=-1 FDIAG(lnb,GLA,0,adiags,first,flag) %FINISH ->nxtfr impfnd: %IF integer(i-4)=x'49414944' %THEN i=i-4 { beware coincidence NS only } diagnosing=1 GLA=integer(lnb-8) Adiags=integer(GLA+20) flag=-1 INDIAG(lnb,gla,adiags,i,0,2,0,first,flag) nxtfr: %EXIT %IF flag=0 { stop at main program } %IF first=2 %THEN first=1 %ELSE first=0 prevlnb=lnb lnb=nextlnb %REPEAT %stop %UNLESS P3=0 %END !****************************************************************** { Called when wanting a monitor which hides 'levels' from the user } %EXTERNAL %ROUTINE CALLNDIAG(%INTEGER levels) ignore=levels+1 %MONITOR ! NDIAG(0,0,0,0) %END !* ! LAYOUT OF DIAGNOSTIC TABLES { THIS INFO EX_EMAS AND VERY OLD } !****** ** ********* ****** ! THE BOUND FIELD OF PLT DESCRIPTOR STORED AT (LNB+3 & LNB+4) IF ! USED TO CONTAIN A DISPLACEMENT RELATIVE TO THE START OF SST OF THE ! DIAGNOSTIC TABLES FOR THE BLOCK OR ROUTINE BEING EXECUTED. ! A ZERO BOUND MEANS NO DIAGNOSTIC REQUESTED.(NB THIS MAY MEAN A DUMMY ! FIRST WORD IN THE SST). ! THE ABSOLUTE ADDRESS OF THE SST FOR THE CURRENT CODE SEGMENT WILL ! ALWAYS BE FOUND IN THE STANDARD 10 WORDS OF THE GLA/PLT ! FORM OF THE TABLES:- ! WORD 0 = LINE OF RT IN SOURCE PROG <<16 ! LINE NO POSN(FROM LNB) ! WORD 1 = (12 LANG DEPENDENT BITS)<<20 ! ENVIRONMENT ! (TOP 2 BITS FOR ROUTINE TYPE.B'01'==SYSTEM ROUTINE) ! (NEXT BIT SET FOR EBCDIC CHARS&STRINGS(ALGOLE ONLY)) ! WORD 2 = DISPLAY POSN (FROM LNB)<<16 ! RT TYPE INFO ! WORD 3 = ZERO FOR BLKS OR STRING(<=11BYTES) BEING THE ! RT NAME. THIS WILL TAKE WORDS 4 AND 5 IF NEEDED ! WORD 6 = LANGUAGE DEPENDENT INFO . IMP ON CONDITIONS ETC ! THE REST IS MADE UP OF VARIABLE ENTRIES AND THE SECTION IS TERMINATED BY ! A WORD OF X'FFFFFFFF' ! EACH VARIABLE ENTRY CONSISTS OF THE VARIABLE WORD FOLLOWED BY ! THE VARIABLE NAME AS A STRING. THE WORD CONSISTS OF ! BITS 2**31 TO 2**20 TYPE INFORMATION (MAY BE LANGUAGE DEPENDENT ! BIT 2**19 =0 UNDER LNB =1 IN GLA ! BITS 2**18 TO 2**0 DISPLACEMENT FROM LNB(GLA) IN BYTES ! THE ENVIRONMENT IS A POINTER (RELATIVE TO SST) OF THE NEXT OUTERMOST ! BLOCK OR A POINTER TO GLOBAL OWNS, EXTERNAL OR COMMON AREAS ! A ZERO MEANS NO ENCLOSING BLOCK. WORD1=WORD3=0 IS AN ! IMP MAIN PROGRAM AND WILL TERMINATE THE DIAGNOSTICS. !! !! NOTE: ALL DISPLACEMENTS ARE BYTE WITHIN THE DIAGNOSTIC TABLES. !! %EXTERNAL %ROUTINE INDIAG(%INTEGER LP,GP,ADIAGS,ADIDIA,MODE,DIAG,ASIZE,FIRST, %INTEGER %NAME FLAG) !*********************************************************************** !* THE DIAGNOSTIC ROUTINE FOR IMP * !* MODE = 0 FOR JOBBER&EMAS2900, =1 FOR OPEH IN VMEB&VMEK * !* DIAG = DIAGNOSTIC LEVEL * !* 1 = ROUTE SUMMARY ONLY (ASIZE)=ADDR MODULE NAME FROM OPEH * !* 2 = DIAGNOSTICS AS TRADITIONALLY PERFORMED * !* ASIZE IS NO OF ELEMENTS OF EACH ARRAY TO BE PRINTED(DIAG>1) * !*********************************************************************** %RECORD %FORMAT VARF(%SHORT %INTEGER FLAGS,DISP, %STRING (11) VNAME) %ROUTINE %SPEC PLOCALS(%INTEGER ADATA, %STRING (15) LOC) %ROUTINE %SPEC PSCALAR(%RECORD (VARF) %NAME VAR) ! %ROUTINESPEC PARR(%RECORD(VARF)%NAME VAR, %INTEGER ASIZE) %ROUTINE %SPEC PVAR(%INTEGER TYPE,PREC,NAM,FORM, %INTEGER VADDR) %INTEGER %FN %SPEC CKREC(%STRING (255) NAME); ! CHECK RECURSION %RECORD %FORMAT RTHEADF(%SHORT %INTEGER RTLINE,LINENO POS,RTFLAGS,ENV,DISPLAY, RTTYPE,(%SHORT %INTEGER IDHEAD %OR %STRING (11) RTNAME)) !* FOLLOWED BY 32 BITS ONCOND WORD !* !* %RECORD (RTHEADF) %NAME RTHEAD %RECORD (VARF) %NAME VAR %INTEGER TYPE %INTEGER GLAAD,LINE,NAM,PREC,TSTART,I %OWN %INTEGER %ARRAY GLOBAD(0:20) %INTEGER INHIBIT %INTEGER refpt %INTEGER RLEN %INTEGER diagdisp %OWN %INTEGER GLOBPTR %STRING (10) STMNT %STRING (20) PROC %STRING (255) NAME %OWN %INTEGER COUNT; ! Used in checking for recursion. %IF FIRST=1 %THEN GLOBPTR=0 %AND COUNT=0 STMNT=" line" PROC=" routine/fn/map " DIAGDISP=shortINTEGER(ADIDIA-2) %CYCLE TStart=adiags+diagdisp %UNLESS Validate(Tstart)=0 %THEN %C printstring("Stack frame is corrupt") %AND %RETURN RTHEAD==RECORD(Tstart) %IF RTHEAD_LINENO POS=0 %THEN LINE=-1 %ELSE LINE=shortinteger(adidia-4) %IF RTHEAD_IDHEAD#0 %START NAME=RTHEAD_RTNAME %IF length(name)>32 %THEN %C printstring("Procedure name in Diagnostics Tables is corrupt ") %AND %RETURN INHIBIT=CKREC(NAME); ! CHECK RECURSION %FINISH %ELSE inhibit=0 %IF inhibit=0 %START NEWLINE %IF MODE=1 %THEN PRINTSTRING(" IMP ") %ELSE %START %IF FIRST=1 %THEN PRINTSTRING("Diagnostics ") %AND first=0 PRINTSTRING("Entered from") %FINISH %IF RTHEAD_RTLINE=0 %START %IF MODE=0 %THEN PRINTSTRING(" IMP ") PRINTSTRING("ENVIRONMENTAL BLOCK ") %RETURN ! %EXIT %FINISH %ELSE %START %IF LINE>=0 %AND LINE#RTHEAD_RTLINE %START PRINTSTRING(STMNT) WRITE(LINE,4) PRINTSTRING(" of") %FINISH %IF RTHEAD_IDHEAD=0 %THEN PRINTSTRING(" Block") %AND RLEN=20 %ELSE %C PRINTSTRING(PROC.NAME) %AND RLEN=(20+LENGTH(RTHEAD_RTNAME))>>2<<2 PRINTSTRING(" starting at".STMNT) WRITE(RTHEAD_RTLINE,2) NEWLINE %IF MODE=0 %OR DIAG>1 %START PLOCALS(TSTART+RLEN,"Local") %IF RTHEAD_RTFLAGS&X'C000'#0 %START; ! EXTERNAL(ETC) ROUTINE I=ADIAGS+(RTHEAD_ENV+20) PLOCALS(I,"Global") %FINISH %FINISH %FINISH %FINISH { inhibit } %IF RTHEAD_IDHEAD#0 %START FLAG=1; ! ROUTINE %UNLESS DIAG=1 %OR INHIBIT=1 %THEN NEWLINE %RETURN %FINISH DIAGDISP=RTHEAD_ENV %REPEAT %UNTIL DIAGDISP=0 FLAG=0; ! MAIN PROGRAM NEWLINE %RETURN !%ROUTINE QSORT(%RECORD(VARF)%ARRAYNAME A, %INTEGER I, J) !%RECORD (VARF)D !%INTEGER L, U ! %IF I>=J %THEN %RETURN ! L = I - 1; U = J; D = A(J) ! %CYCLE ! %CYCLE ! L = L+1 ! {%EXIT outer loop} %IF L=U %THEN -> FOUND ! %REPEAT %UNTIL A(L)_VNAME>D_VNAME ! A(U) = A(L) ! %CYCLE ! U = U-1 ! {%EXIT outer loop} %IF L=U %THEN -> FOUND ! %REPEAT %UNTIL D_VNAME>A(U)_VNAME ! A(L) = A(U) ! %REPEAT !FOUND: ! A(U) = D ! QSORT(A,I,L-1) ! QSORT(A,U+1,J) !%END !* %INTEGER %FN CKREC(%STRING (255) NAME); ! CHECK RECURSION !******************************************************** !* AVOID PRINTING TRACE OF RECURSING RTS * !******************************************************** %OWN %STRING (51) LASTNAME="" %IF LASTNAME=NAME %START COUNT=COUNT+1 %IF COUNT=6 %THEN PRINTSTRING(" **** ".NAME." CONTINUED TO RECURSE **** ") %RESULT=1 %IF COUNT>5 %FINISH %ELSE %START %IF COUNT>6 %THEN %START PRINTSTRING("**** (FOR A FURTHER ") WRITE(COUNT-6,1) PRINTSTRING(" LEVEL") %IF COUNT>7 %THEN PRINTSYMBOL('S') PRINTSTRING(") **** ") %FINISH COUNT=0 LASTNAME=NAME %FINISH %RESULT=0 %END %ROUTINE PLOCALS(%INTEGER ADATA, %STRING (15) LOC) !*********************************************************************** !* ADATA POINTS TO THE FIRST ENTRY FOR LOCALS IN THE SYMBOL TABLES* !*********************************************************************** %RECORD (VARF) %NAME VAR %INTEGER I,NRECS %INTEGER SADATA %IF loc="Global" %THEN %START I=0 %WHILE I0 %CYCLE VAR==RECORD(ADATA) NRECS=NRECS+1 ADATA=ADATA+((8+LENGTH(VAR_VNAME))>>2<<2) %REPEAT %RETURN %IF NRECS=0 %BEGIN %RECORD (VARF) %ARRAY VARS(1:NRECS) %INTEGER I ADATA=SADATA %FOR I=NRECS,-1,1 %CYCLE VAR==RECORD(ADATA) VARS(I)<-RECORD(ADATA) ADATA=ADATA+((8+LENGTH(VAR_VNAME))>>2<<2) %REPEAT ! QSORT(VARS,1,NRECS) refpt=lp+rthead_display { IMP vars disp not rel to lnb } %FOR I=1,1,NRECS %CYCLE %IF VARS(I)_FLAGS>>12&3=0 %THEN PSCALAR(VARS(I)) %REPEAT ! %IF ASIZE>0 %THEN %START ! %FOR I=1,1,NRECS %CYCLE ! %IF VARS(I)_FLAGS>>12&3#0 %THEN PARR(VARS(I), %C ! ASIZE) ! %REPEAT ! %FINISH %END %END %ROUTINE PSCALAR(%RECORD (VARF) %NAME VAR) !*********************************************************************** !* OUTPUT THE NEXT VARIABLE IN THE CURRENT BLOCK. * !* A VARIABLE ENTRY IN THE TABLES IS:- * !* FLAG<<20!VBREG<<18!DISP * !* WHERE:- * !* VBREG IS VARIABLE'S BASE REGISTER, DISP IS IT'S OFFSET * !* AND FLAGS=NAM<<6!PREC<<3!TYPE * !*********************************************************************** %INTEGER VADDR %INTEGER I,K %STRING (11) LNAME I=VAR_FLAGS ! printstring(" var_flags = "); !phex(var_flags); !newline K=I>>4 TYPE=K&7 PREC=K>>4&7 NAM=K>>10&1 LNAME<-VAR_VNAME." " PRINT STRING(LNAME."=") %IF I&4=0 %START { For non Owns } %if var_dispNOT ASS %IF VADDR=UNASSI %FINISH ->ILL ENT %IF PREC<3; ! BITS NOT IMPLEMENTED %IF TYPE=1 %THEN ->INTV(PREC) %IF TYPE=2 %THEN ->REALV(PREC) %IF TYPE=5 %THEN ->STR %IF type=3 %THEN ->REC INTV(4): ! 16 BIT INTEGER K=shortinteger(vadDR) WRITE(K,12*FORM+1) %RETURN INTV(6): ! 64 BIT INTEGER REALV(7): ! 128 BIT REAL INTV(7): ! 128 BIT INTEGER REALV(3): ! 8 BIT REAL REALV(4): ! 16 BIT REAL ILL ENT: ! SHOULD NOT OCCURR PRINTSTRING("UNKNOWN TYPE OF VARIABLE") %RETURN INTV(5): ! 32 BIT INTEGER i=integer(vaddr) ->NOT ASS %IF i=UN ASSI WRITE(i,1+12*FORM) %UNLESS FORM=1 %OR-255<=i<=255 %START PRINTSTRING(" (X'") PHEX(i); PRINTSTRING("')") %FINISH %RETURN INTV(3): ! 8 BIT INTEGER WRITE(BYTEINTEGER(VADDR),1+12*FORM); %RETURN REALV(5): ! 32 BIT REAL ->NOT ASS %IF INTEGER(vADDR)=UN ASSI %IF integer(vaddr)&x'7f800000'#x'7f800000' %THEN PRINT FL(REAL(vADDR),7) %ELSE %C printstring(" Invalid real ") printstring(" x'") phex(integer(vaddr)) printstring("'") %RETURN REALV(6): ! 64 BIT REAL ->NOT ASS %IF UNASSI=INTEGER(vADDR)=INTEGER(vADDR) %IF integer(vaddr)&x'7ff00000'#x'7ff00000' %THEN %C PRINT FL(LONG REAL(vADDR),14) %ELSE printstring(" Invalid real ") printstring(" x'") phex(integer(vaddr)) phex(integer(vaddr+4)) printstring("'") %RETURN REC: printstring(" Record(x'") %CYCLE i=0,4,20 { print hex contents of first six integers in a record } phex(integer(vaddr+i)) space %UNLESS i=20 %REPEAT printstring("')") %RETURN STR: SV==STRING(vADDR) I=LENGTH(SV) ! ->NOT ASS %IF BYTE INTEGER(SVADDR+1)=UNASSI&255=I SA==ARRAY(VADDR,SAFM) K=1 %WHILE K<=I %CYCLE ->NPRINT %UNLESS 32<=SA(K)<=126 %OR SA(K)=10 K=K+1 %REPEAT space; printsymbol('"') PRINTSTRING(SV); PRINT SYMBOL('"') %RETURN NPRINT: PRINT STRING(" CONTAINS UNPRINTABLE CHARS") %RETURN NOT ASS: PRINTSTRING(" NOT ASSIGNED") AIGN: %IF PREC>=6 %AND FORM=1 %THEN SPACES(7) %END; ! PVAR %END; ! OF RT IDIAGS !* %ROUTINE call monitor(%STRING (47) text) newlines(2) printstring(text) newline ignore=3 { hide top three levels as of no iterest to user } { ie. this, ON rt and trap rt } %MONITOR %stop { AS an ultimate diagnostic aid prodide a core dump } %END %EXTERNAL %INTEGER %FN validate(%INTEGER vaddr) %INTEGER j j=vaddr *put_x'0c03'; *put_x'04bc'; *put_x'0401'; ! prober 3,4,vaddr *put_X'dcac'; *put_x'0401'; ! MOVPSL vaddr %if extramon>0 %and vaddr&4#0 %Start printstring("Validate fails on "); phex(j) newline %finish %RESULT=vaddr&4; ! zero if access %END %externalroutine on Signal (%integer signal, subcode,contextAd) !*********************************************************************** !* A routine to catch one of the traps set by IMPENTRY * !*********************************************************************** !The traps expected are: ! %constinteger SIGQUIT= 3, SIGILL = 4, SIGIOT = 6, SIGEMT = 7, SIGFPE = 8, SIGBUS = 10, SIGSEGV= 11 %integer event %switch handle signal (SIGQUIT:SIGSEGV) %integer Br1,Br2,i,mylnb %if extramon=1 %then %start printstring("on signal"); write(signal,5); write(subcode,5) newline %finish BR2=integer(contextad+12); ! PC BR1=integer(contextad+8); ! SF %if extramon=1 %start %for i=0,1,4 %cycle phex(integer(contextad+4*i)) newline %repeat %finish %if signal>= SIGQUIT %and %c signal<= SIGSEGV %then -> handle signal (signal) handle signal (*) : event=X'F08' ; -> monitor handle signal (SIGBUS) : handle signal (SIGQUIT): event=X'F01'; -> monitor handle signal (SIGILL) : event=X'F02'; -> monitor handle signal (SIGIOT) : event=X'901'; -> monitor handle signal (SIGEMT) : event=X'F03'; -> monitor handle signal (SIGSEGV): event=X'F04'; -> monitor handle signal (SIGFPE ): ! ! Decode SIGFPE Signal ! event=X'103' monitor: *put_X'D05d'; *put_X'ac04' mylnb=signal ndiag(Br2,integer(mylnb+12),event,0) !call monitor (text) %end; !of on Signal %END %OF %FILE