SECTION"STR" GET "AHDR" MANIFEST $( maxint.div.10 = maxint/10 maxint.rem.10 = maxint REM 10 $) LET START(PARM) BE $( LET sco = createco(startc, 650) TEST sco=0 DO writes("*NNot enough store to create *'startc*'*N") OR $( callco(sco, 0) deleteco(sco) $) $) AND startc(parm) BE $( LET V1=VEC 20 // PGM AND V2=VEC 20 // TTL AND V3=VEC 72 // P.CODEV AND V4=VEC 72 // P.CODET AND V5=VEC 80 // PROG.NAME AND V6=VEC 2 // FSYM AND V7=VEC 80 // LINE AND V8=VEC 8 // DUMPV AND V9=VEC 39 // BIN AND V10=VEC 8 // RELBITS AND V11=VEC 7 //NUMBERCHARS AND V12=VEC 72 //PARMV AND pv = ? AND ACNT,RCNT=0,0 // ABS AND REL COUNTERS AND mainco = ? // coroutine for MAIN AND vecsize = ? // size for APTOVEC PGM:=V1; TTL:=V2 P.CODEV:=V3; P.CODET:=V4 PROG.NAME:=V5 FSYM:=V6 LINE:=V7 DUMPV:=V8; BIN:=V9; RELBITS:=V10 NUMBERCHARS:=V11 pv := v12 ABSC:=@ACNT; RELC:=@RCNT VERSIONNUMBER:=2 //SETUP FILE NAMES listfile := "NIL:" //SETUP SIZE OF WORK SPACES DICTSIZE:=1000 //CHARACTERS LISTSIZE:=2000 //WORDS termstr := output() cdsize := 500 // words rvsize := 100 // words NAMESIZE:=512 //WORDS (A POWER OF TWO!!!) INANALSIZE:=500 IF rdargs("from/A,to/A/K,list/K,prof/S,cross/S,short/S,* *dicts/K,lists/K,cds/K,rvs/K,names/K,inanals/K", pv, 72)=0 DO $( writes("*NBad args*N") stop(5) $) assfile := pv!0; lgo := pv!1 UNLESS pv!2=0 DO listfile := pv!2 profil := pv!3; crossref := pv!4; shortcrossref := pv!5 UNLESS pv!6=0 DO $( UNLESS strnum(pv!6) GOTO badn; dictsize := result2 $) UNLESS pv!7=0 DO $( UNLESS strnum(pv!7) GOTO badn; listsize := result2 $) UNLESS pv!8=0 DO $( UNLESS strnum(pv!8) GOTO badn; cdsize := result2 $) UNLESS pv!9=0 DO $( UNLESS strnum(pv!9) GOTO badn; rvsize := result2 $) UNLESS pv!10=0 DO $( UNLESS strnum(pv!10) GOTO badn; namesize :=result2 $) UNLESS pv!11=0 DO $( UNLESS strnum(pv!11) GOTO badn; inanalsize := result2 $) ASSFILESTR:=FINDINPUT(ASSFILE) PENDINGLINE:=FALSE vecsize := listsize+1+ 4*namesize+4+ dictsize/bytesperword+1+ inanalsize+1+ cdsize+1+ rvsize+1+ 72+4*(72/bytesperword) // safety factors mainco := createco(mainc, vecsize+650) TEST mainco=0 DO writes("*NNot enough store to create *'mainco*'*N") OR $( callco(mainco, vecsize) deleteco(mainco) $) RETURN badn: writes("*NBad number in argument*N") stop(6) $) AND strnum(string) = VALOF // Convert string to number routine // Returns TRUE if STRING represents a valid number // (number in RESULT2), FALSE otherwise $( LET len = string%0 LET pos = TRUE LET ch = ? IF len=0 RESULTIS FALSE result2 := 0 FOR i = 1 TO len DO $( LET ch = string%i IF ch='-' | ch='+' DO $( IF i\=1 | len=1 RESULTIS FALSE pos := ch='+' LOOP $) UNLESS '0'<=ch<='9' RESULTIS FALSE IF result2>maxint.div.10 | (result2=maxint.div.10 & [ch-'0']>[maxint.rem.10 + (pos -> 0, 1)]) THEN RESULTIS FALSE result2 := result2*10 + ch - '0' $) UNLESS pos DO result2 := -result2 RESULTIS TRUE $) AND mainc(n) BE aptovec(main, n) AND MAIN(V,S) BE $( LET PART=0 AND KLINE=VEC 72 AND VVV=VEC 80 AND KLAB,KARG,KOP=0,0,0 //NUMBERS IN BRACKETS ARE SAFETY FACTORS USUALLY ONE LINE OF 72 CHARS VX:=VVV // GLOB VECTOR FOR OBJECT MODULE TEXT v := v+72 DICT:=V; V:=V+DICTSIZE/BYTESPERWORD+1 DICTMAX:=V*BYTESPERWORD-1; V:=V+(72/BYTESPERWORD) LISTSPACE:=V; V:=V+LISTSIZE+1 LSPACEMAX:=V-1 v := v+(72/bytesperword) NAMEP:=V; V:=V+2*NAMESIZE+2 SNAME:=V; V:=V+NAMESIZE+1 ONAME:=V; V:=V+NAMESIZE+1 V:=V+(72/BYTESPERWORD) INANAL:=V INTOP:=V+INANALSIZE codevec := intop+1+(72/bytesperword) relvecc := codevec+cdsize+1 rsym := rstream inparform := FALSE INSTR:=ASSFILESTR SELECTINPUT(INSTR) $( //START OF BIG LOOP PASS:=1 // CLEAR OUT SYMBOL TABLES & DICTIONARY FOR J=0 TO INANALSIZE DO INANAL!J:=0 FOR J=0 TO DICTSIZE/BYTESPERWORD DO DICT!J:=0 FOR J=0 TO NAMESIZE*2 DO NAMEP!J:=0 FOR J=0 TO NAMESIZE DO SNAME!J,ONAME!J:=-1,-1 FOR J=0 TO LISTSIZE DO LISTSPACE!J:=0 !ABSC:=0; !RELC:=0; CNT:=RELC TOPRELCNT:=0; TOPABSCNT:=0 // PROGRAM NAME, TITLE, ETC. !PROG.NAME:=0; FOR I=1 TO 6 DO PROG.NAME!I:=' ' !PGM:=0 !TTL:=0 SCW:=FALSE // DICTIONARY POINTERS DP:=DICT*BYTESPERWORD // LISTS LSP:=LISTSPACE // SYMBOL TABLE POINTERS + DFF ENTRY IN SYMBOL TABLE $( LET V=VEC 4 LET A=V+1 UNPACKSTRING("DFF ",V) NAMEP!GETOPN(@A):=LIST(1,T.DIR+D.DFF) $) FAULTS:=0 INITLISTCONTROL() // BINARY OUTPUT BINOUT:=FINDOUTPUT(LGO) PAGE:=0 // STREAMS ERRSTR:=FINDOUTPUT("OUTPUT") SELECTOUTPUT(ERRSTR) INSTR:=FINDINPUT("M80P") IF INSTR=0 THEN $( FAULTS:=1 SELECTOUTPUT(FINDOUTPUT(LISTFILE)) WRITES(" ****** FAILURE TO ATTACH M8OP ******") WRITETOLOG(" ****** FAILURE TO ATTACH M8OP ******") endwrite() selectoutput(errstr) endwrite() selectoutput(binout) endwrite() selectinput(assfilestr) endread() FINISH $) SELECTINPUT(INSTR) /**/ DEBUG("Before first PASS1 ... *N") PASS1() ENDREAD() /**/ DEBUG(" PASS1 ,INSTR=%X8 *N",INSTR) INSTR:=ASSFILESTR SELECTINPUT(INSTR) /**/ DEBUG(" PASSS1 *N") IF INSTR=0 THEN $( FAULTS:=1 SELECTOUTPUT(FINDOUTPUT(LISTFILE)) WRITEF(" ****** NO INPUT FILE CALLED *"%S*"",ASSFILE) WRITETOLOG(" ****** NO INPUT FILE") endwrite() selectoutput(errstr) endwrite() selectoutput(binout) endwrite() selectinput(assfilestr) endread() FINISH $) UNLESS PART=0 THEN $( PENDINGLINE:=TRUE LAB,ARG,OP:=KLAB,KARG,KOP FOR I=0 TO 72 DO LINE!I:=KLINE!I $) NUMBERED:=TRUE ENDREC.P:=LEVEL(); ENDREC.L:=PASS1.RETURN /**/ DEBUG(" CALLING PASS1 FOR THE SECOND TIME*N") PASS1() PASS1.RETURN: PASS:=2 /**/ DEBUG(" AFTER PASS1.RETURN") SELECTINPUT(INSTR); ENDREAD() INSTR := FINDINPUT(ASSFILE); SELECTINPUT(INSTR) ASSFILESTR := INSTR // UPDATE CAUSE 'REWIND' CHANGES rsym := rstream inparform := false FOR I=1 TO PART DO $( LET J,T=0,0 $( J:=READLINE() REPEATUNTIL J&(!LINE NE '**')&(OP NE 0) T:=GETOPN(@OP) IF NAMEP!T=0 THEN LOOP J:=!(NAMEP!T) UNLESS (Jﰀ)=T.DIR DO LOOP J:=JϿ IF J=D.END THEN BREAK $) REPEAT J:=READLINE() REPEATUNTIL J&(!LINE NE '**')&(OP NE 0) PENDINGLINE:=TRUE $) SELECTOUTPUT(FINDOUTPUT(LISTFILE)) SELECTINPUT(INSTR) rsym := rstream LINES:=LINESPERPAGE; LISTINGCONTROL:=L.ALL; LINENO:=1 !ABSC:=0; !RELC:=0; CNT:=RELC //INITIALISATION FOR LOADER NOW SET UP DUMPINIT() REC.P,REC.L:=LEVEL(),NO.END.DIR ENDREC.P:=REC.P; ENDREC.L:=PASS2.RETURN /**/ DEBUG(" JUST BEFORE PASS2*N") PASS2() /**/ DEBUG(" JUST AFTER PASS2*N") PASS2.RETURN: NEWLINE() TEST FAULTS=0 THEN WRITES(" NO ERRORS IN ASSEMBLY") ELSE WRITEF(" %N ERROR%S IN ASSEMBLY",FAULTS,(FAULTS=1)->"", "S") NEWLINE() WRITES(" ASSEMBLY COMPLETE") NEWLINE() UNLESS PROFIL=0 THEN PRINTPROFIL() IF CROSSREF THEN PRINTCROSSREFS() WRITETOLOG((FAULTS=0)->"NO ERRORS IN ASSEMBLY", (FAULTS=1)->"ERROR IN ASSEMBLY", "ERRORS IN ASSEMBLY") WRITETOLOG("ASSEMBLY COMPLETE") REC.P,REC.L:=LEVEL(),STOP.IT rsym := rstream endwrite() // list stream SELECTINPUT(INSTR) SELECTOUTPUT(ERRSTR) $( LET J=0 J:=READLINE() REPEATUNTIL J&(!LINE NE '**')&(OP NE 0) $) PART:=PART+1 KLAB,KARG,KOP:=LAB,ARG,OP FOR I=0 TO 72 DO KLINE!I:=LINE!I $) REPEAT STOP.IT: endwrite() // error stream selectoutput(binout) endwrite() endread() // input stop(0) NO.END.DIR: FAULTS:=FAULTS+1 WRITES(" ****** NO END TERMINATOR ******") WRITETOLOG(" ****** NO END TERMINATOR ******") GOTO PASS2.RETURN $) AND PRINTCROSSREFS() BE $( WRITES("*P CROSS REFERENCE*N *N *N") $( LET P,Q,R=-1,0,0 FOR T=0 TO NAMESIZE DO $( UNLESS SNAME!T<0 THEN $( P:=T; BREAK $) $) IF P=-1 THEN RETURN FOR T=P+1 TO NAMESIZE DO $( UNLESS SNAME!T<0 THEN $( P:=VALOF $( LET LP,LT=GETBYTE(0,SNAME!P),GETBYTE(0,SNAME!T) LET L=(LP<LT)->LP,LT FOR I=1 TO L DO $( LET CP,CT=GETBYTE(0,SNAME!P+I),GETBYTE(0,SNAME!T+I) IF CP<CT THEN RESULTIS P IF CT<CP THEN RESULTIS T $) IF LT<LP THEN RESULTIS T RESULTIS P $) $) $) IF SHORTCROSSREF THEN $( R:=NAMEP!P IF (R=0) LOGOR (R!3=0) THEN $( SNAME!P:=-1 //REMOVE ENTRY LOOP $) $) $( //PRINT NAME LET L=GETBYTE(0,SNAME!P) WRCH(' ') FOR I=SNAME!P+1 TO SNAME!P+L DO WRCH(GETBYTE(0,I)) SNAME!P:=-1 //REMOVE ENTRY SPACES(14-L) $) R:=NAMEP!P UNLESS R=0 THEN $( UNLESS (!R&T.REDEF)=0 THEN WRITES("FINAL VALUE ") WRCH(SYMTYPE(!Rﰀ)); WRCH(' ') WRITEHEX(1!R,4) R:=R!2 $) Q:=-1 UNTIL R=0 DO $( Q:=Q+1 IF (Q REM 10)=0 THEN $( WRCH('*N'); SPACES(15) $) WRITEF(" **%X4",REFVALUE(R)) R:=REFPOINTER(R) $) R:=NAMEP!P; UNLESS R=0 THEN R:=R!3 UNTIL R=0 DO $( Q:=Q+1 IF (Q REM 10)=0 THEN $( WRCH('*N'); SPACES(15) $) WRITEF(" %X4",REFVALUE(R)) R:=REFPOINTER(R) $) WRCH('*N') $) REPEAT $) AND DEBUG(X,X1,X2,X3,X4,X5,X6,X7,X8,X9) BE $( LET A=OUTPUT() SELECTOUTPUT(ERRSTR) WRITEF(X,X1,X2,X3,X4,X5,X6,X7,X8,X9) SELECTOUTPUT(A) $) AND PRINTPROFIL() BE $( WRITES("*P ASSEMBLER OPTIONS*N *N *N") WRITES(" FILE NAMES*N *N") WRITEF(" B=%S BINARY OUTPUT*N",LGO) WRITEF(" I=%S INPUT FILE*N",ASSFILE) WRITEF(" L=%S LISTING FILE*N *N *N",LISTFILE) WRITES(" EXTRA OPTIONS*N *N") WRITEF(" P %S PROFILE OF SPACE AND OPTIONS*N", PROFIL>0->"SET BY PROGRAM","SET") WRITEF(" S %S SHORT CROSS REFERENCE*N", SHORTCROSSREF->"SET","UNSET") WRITEF(" X %S CROSS REFERENCE (MAY BE SET BY 'S' OPTION)*N *N *N", CROSSREF->"SET","UNSET") WRITES(" SPACE AND ITS UTILISATION*N *N") WRITEF(" D%N CHARACTERS DICTIONARY, AMOUNT USED = %N*N", DICTSIZE,DP-DICT*BYTESPERWORD) WRITEF(" L%N WORDS LIST SPACE, AMOUNT USED = %N*N", LISTSIZE,LSP-LISTSPACE) WRITEF(" N%N WORDS SYMBOL TABLES ",NAMESIZE) WRITEF(" (%N WORDS, HASH CODED, A POWER OF TWO)",4*NAMESIZE) $( LET S1,S2=0,0 FOR P=0 TO NAMESIZE-1 DO $( UNLESS ONAME!P=-1 THEN S1:=S1+1 UNLESS SNAME!P=-1 THEN S2:=S2+1 $) WRITEF(", AMOUNT USED = %N*N",S1>S2->S1,S2) $) $) AND ADDREF(P,N,V) BE $( IF P=0 THEN RETURN P:=P+N UNTIL !P=0 DO P:=!P !P:=LIST(2,0,V) $) AND REFPOINTER(R) = !R AND REFVALUE(R) = 1!R AND SPACES(M) BE FOR N=1 TO M DO WRCH(' ') AND ASKII(C) = C AND CAN2WORDS(NAME,P) BE $( LET V=VEC 6 AND L=GETBYTE(0,NAME) IF L>6 THEN L:=6 //TRUNCATE TO 6 CHARACTERS FOR I=1 TO L DO V!I:=GETBYTE(0,NAME+I) FOR I=L+1 TO 6 DO V!I:=' ' P!0:=(CANVALUE(V!1)*40+CANVALUE(V!2))*40+CANVALUE(V!3) P!1:=(CANVALUE(V!4)*40+CANVALUE(V!5))*40+CANVALUE(V!6) $) .