commit 2c7099ee501923775c4c96079a6fe94da109b552 Author: memnoth Date: Sat Jan 27 22:35:41 2018 +0900 Add original unix v6 diff --git a/README.md b/README.md new file mode 100644 index 0000000..0a11b9d --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# UNIX 6th Edition Kernel Source Code + +from [www.tom-yam.or.jp/2238/src](http://www.tom-yam.or.jp/2238/src). + +# Documents +- [Commentary on the Sixth Edition UNIX Operating System](http://www.lemis.com/grog/Documentation/Lions/) +- [The Unix Tree (Minnie's Home Page)](http://minnie.tuhs.org/cgi-bin/utree.pl) + diff --git a/source/as/as11.s b/source/as/as11.s new file mode 100644 index 0000000..0ddf5d1 --- /dev/null +++ b/source/as/as11.s @@ -0,0 +1,106 @@ +/ +/ + +/ PDP-11 assembler pass 0 + +indir = 0 + + jmp start +go: + jsr pc,assem + movb pof,r0 + sys write; outbuf; 512. + movb pof,r0 + sys close + movb fbfil,r0 + sys close + tstb errflg + bne aexit + jsr r5,fcreat; a.tmp3 + mov r0,r1 + mov symend,0f + sub $usymtab,0f + sys indir; 9f + .data +9: sys write; usymtab; 0:.. + .text + mov r1,r0 + sys close + sys exec; 2f; 1f + mov $2f,r0 + jsr r5,filerr; "?\n + +aexit: + sys unlink; a.tmp1 + sys unlink; a.tmp2 + sys unlink; a.tmp3 + sys exit +.data +1: + 2f + a.tmp1 + a.tmp2 + a.tmp3 +unglob: + 3f + 0 + .text +2: +fpass2: + +3: + <-g\0> + .even + +filerr: + mov r4,-(sp) + mov r0,r4 + mov r4,0f + clr r0 +1: + tstb (r4)+ + beq 1f + inc r0 + br 1b +1: + mov r0,1f + mov $1,r0 + sys indir; 9f + .data +9: sys write; 0:0; 1:0 + .text + mov r5,0f + mov $1,r0 + sys indir; 9f + .data +9: sys write; 0:0; 2 + .text + tst (r5)+ + mov (sp)+,r4 + rts r5 + +fcreat: + mov r4,-(sp) + mov (r5)+,r4 + mov r4,0f +1: + sys indir; 9f + .data +9: sys stat; 0:..; outbuf + .text + bec 2f + mov r4,0f + sys indir; 9f + .data +9: sys creat; 0:..; 444 + .text + bes 2f + mov (sp)+,r4 + rts r5 +2: + incb 9.(r4) + cmpb 9.(r4),$'z + blos 1b + mov r4,r0 + jsr r5,filerr; "?\n + sys exit diff --git a/source/as/as12.s b/source/as/as12.s new file mode 100644 index 0000000..b1f4b4b --- /dev/null +++ b/source/as/as12.s @@ -0,0 +1,70 @@ +/ +/ + +/ a2 -- pdp-11 assembler pass 1 + +error: + incb errflg + mov r0,-(sp) + mov r1,-(sp) + mov (r5)+,r0 + tst *curarg + beq 1f + mov r0,-(sp) + mov *curarg,r0 + clr *curarg + jsr r5,filerr; '\n + mov (sp)+,r0 +1: + mov r2,-(sp) + mov r3,-(sp) + mov line,r3 + movb r0,1f + mov $1f+6,r0 + mov $4,r1 +2: + clr r2 + dvd $10.,r2 + add $'0,r3 + movb r3,-(r0) + mov r2,r3 + sob r1,2b + mov $1,r0 + sys write; 1f; 7 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r1 + mov (sp)+,r0 + rts r5 + + .data +1: + .even + .text + +betwen: + cmp r0,(r5)+ + blt 1f + cmp (r5)+,r0 + blt 2f +1: + tst (r5)+ +2: + rts r5 + +putw: + tst ifflg + beq 1f + cmp r4,$'\n + bne 2f +1: + mov r4,*obufp + add $2,obufp + cmp obufp,$outbuf+512. + blo 2f + mov $outbuf,obufp + movb pof,r0 + sys write; outbuf; 512. +2: + rts pc + diff --git a/source/as/as13.s b/source/as/as13.s new file mode 100644 index 0000000..2721f99 --- /dev/null +++ b/source/as/as13.s @@ -0,0 +1,131 @@ +/ +/ + +/ a3 -- pdp-11 assembler pass 1 + +assem: + jsr pc,readop + jsr pc,checkeos + br ealoop + tst ifflg + beq 3f + cmp r4,$200 + blos assem + cmpb (r4),$21 /if + bne 2f + inc ifflg +2: + cmpb (r4),$22 /endif + bne assem + dec ifflg + br assem +3: + mov r4,-(sp) + jsr pc,readop + cmp r4,$'= + beq 4f + cmp r4,$': + beq 1f + mov r4,savop + mov (sp)+,r4 + jsr pc,opline + br ealoop +1: + mov (sp)+,r4 + cmp r4,$200 + bhis 1f + cmp r4,$1 / digit + beq 3f + jsr r5,error; 'x + br assem +1: + bitb $37,(r4) + beq 1f + jsr r5,error; 'm +1: + bisb dot-2,(r4) + mov dot,2(r4) + br assem +3: + mov numval,r0 + jsr pc,fbcheck + movb dotrel,curfbr(r0) + asl r0 + movb dotrel,nxtfb + mov dot,nxtfb+2 + movb r0,nxtfb+1 + mov dot,curfb(r0) + movb fbfil,r0 + sys write; nxtfb; 4 + br assem +4: + jsr pc,readop + jsr pc,expres + mov (sp)+,r1 + cmp r1,$200 + bhis 1f + jsr r5,error; 'x + br ealoop +1: + cmp r1,$dotrel + bne 2f + bic $40,r3 + cmp r3,dotrel + bne 1f +2: + bicb $37,(r1) + bic $!37,r3 + bne 2f + clr r2 +2: + bisb r3,(r1) + mov r2,2(r1) + br ealoop +1: + jsr r5,error; '. + movb $2,dotrel +ealoop: + cmp r4,$'; + beq assem1 + cmp r4,$'\n + bne 1f + inc line + br assem1 +1: + cmp r4,$'\e + bne 2f + tst ifflg + beq 1f + jsr r5,error; 'x +1: + rts pc +2: + jsr r5,error; 'x +2: + jsr pc,checkeos + br assem1 + jsr pc,readop + br 2b +assem1: + jmp assem + +fbcheck: + cmp r0,$9. + bhi 1f + rts pc +1: + jsr r5,error; 'f + clr r0 + rts pc + +checkeos: + cmp r4,$'\n + beq 1f + cmp r4,$'; + beq 1f + cmp r4,$'\e + beq 1f + add $2,(sp) +1: + rts pc + diff --git a/source/as/as14.s b/source/as/as14.s new file mode 100644 index 0000000..7c72f33 --- /dev/null +++ b/source/as/as14.s @@ -0,0 +1,231 @@ +/ +/ + +/ a4 -- pdp-11 assembler pass1 + +rname: + mov r1,-(sp) + mov r2,-(sp) + mov r3,-(sp) + mov $8,r5 + mov $symbol+8.,r2 + clr -(r2) + clr -(r2) + clr -(r2) + clr -(r2) + clr -(sp) + clr -(sp) + cmp r0,$'~ / symbol not for hash table + bne 1f + inc 2(sp) + clr ch +1: + jsr pc,rch + movb chartab(r0),r3 + ble 1f + add r3,(sp) + swab (sp) + dec r5 + blt 1b + movb r3,(r2)+ + br 1b +1: + mov r0,ch + mov (sp)+,r1 + clr r0 + tst (sp)+ + beq 1f + mov symend,r4 + br 4f +1: + div $hshsiz,r0 + ashc $1,r0 + add $hshtab,r1 +1: + sub r0,r1 + cmp r1,$hshtab + bhi 2f + add $2*hshsiz,r1 +2: + mov $symbol,r2 + mov -(r1),r4 + beq 3f + cmp (r2)+,(r4)+ + bne 1b + cmp (r2)+,(r4)+ + bne 1b + cmp (r2)+,(r4)+ + bne 1b + cmp (r2)+,(r4)+ + bne 1b + br 1f +3: + mov symend,r4 + mov r4,(r1) +4: + mov $symbol,r2 + mov r4,-(sp) + add $20,r4 + cmp r4,0f + blos 4f + add $512.,0f + sys indir; 9f + .data +9: sys break; 0:end + .text +4: + mov (sp)+,r4 + mov (r2)+,(r4)+ + mov (r2)+,(r4)+ + mov (r2)+,(r4)+ + mov (r2)+,(r4)+ + clr (r4)+ + clr (r4)+ + mov r4,symend + sub $4,r4 +1: + mov r4,-(sp) + mov r4,r3 + sub $8,r3 + cmp r3,$usymtab + blo 1f + sub $usymtab,r3 + clr r2 + div $3,r2 + mov r2,r4 + add $4000,r4 / user symbol + br 2f +1: + sub $symtab,r3 + clr r2 + div $3,r2 + mov r2,r4 + add $1000,r4 / builtin symbol +2: + jsr pc,putw + mov (sp)+,r4 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r1 + tst (sp)+ + rts pc + +number: + mov r2,-(sp) + mov r3,-(sp) + mov r5,-(sp) + clr r1 + clr r5 +1: + jsr pc,rch + jsr r5,betwen; '0; '9 + br 1f + sub $'0,r0 + mpy $10.,r5 + add r0,r5 + als $3,r1 + add r0,r1 + br 1b +1: + cmp r0,$'b + beq 1f + cmp r0,$'f + beq 1f + cmp r0,$'. + bne 2f + mov r5,r1 + clr r0 +2: + movb r0,ch + mov r1,r0 + mov (sp)+,r5 + mov (sp)+,r3 + mov (sp)+,r2 + rts pc +1: + mov r0,r3 + mov r5,r0 + jsr pc,fbcheck + add $141,r0 + cmp r3,$'b + beq 1f + add $10.,r0 +1: + mov r0,r4 + mov (sp)+,r5 + mov (sp)+,r3 + mov (sp)+,r2 + add $2,(sp) + rts pc + +rch: + movb ch,r0 + beq 1f + clrb ch + rts pc +1: + dec inbfcnt + blt 2f + movb *inbfp,r0 + inc inbfp + bic $!177,r0 + beq 1b + rts pc +2: + movb fin,r0 + beq 3f + sys read; inbuf;512. + bcs 2f + tst r0 + beq 2f + mov r0,inbfcnt + mov $inbuf,inbfp + br 1b +2: + movb fin,r0 + clrb fin + sys close +3: + decb nargs + bgt 2f + mov $'\e,r0 + rts pc +2: + tst ifflg + beq 2f + jsr r5,error; 'i + jmp aexit +2: + mov curarg,r0 + tst (r0)+ + mov (r0),0f + mov r0,curarg + incb fileflg + sys indir; 9f + .data +9: sys open; 0:0; 0 + .text + bec 2f + mov 0b,r0 + jsr r5,filerr; + jmp aexit +2: + movb r0,fin + mov $1,line + mov r4,-(sp) + mov r1,-(sp) + mov $5,r4 + jsr pc,putw + mov *curarg,r1 +2: + movb (r1)+,r4 + beq 2f + jsr pc,putw + br 2b +2: + mov $-1,r4 + jsr pc,putw + mov (sp)+,r1 + mov (sp)+,r4 + br 1b + diff --git a/source/as/as15.s b/source/as/as15.s new file mode 100644 index 0000000..5d84842 --- /dev/null +++ b/source/as/as15.s @@ -0,0 +1,170 @@ +/ +/ + +/ a5 -- pdp-11 assembler pass 1 + +readop: + mov savop,r4 + beq 1f + clr savop + rts pc +1: + jsr pc,8f + jsr pc,putw + rts pc + +8: + jsr pc,rch +_readop: + mov r0,r4 + movb chartab(r0),r1 + bgt rdname + jmp *1f-2(r1) + + fixor + escp + 8b + retread + dquote + garb + squote + rdname + skip + rdnum + retread + string +1: + +escp: + jsr pc,rch + mov $esctab,r1 +1: + cmpb r0,(r1)+ + beq 1f + tstb (r1)+ + bne 1b + rts pc +1: + movb (r1),r4 + rts pc + +esctab: + .byte '/, '/ + .byte '\<, 035 + .byte '>, 036 + .byte '%, 037 + .byte 0, 0 + +fixor: + mov $037,r4 +retread: + rts pc + +rdname: + movb r0,ch + cmp r1,$'0 + blo 1f + cmp r1,$'9 + blos rdnum +1: + jmp rname + +rdnum: + jsr pc,number + br 1f + rts pc + +squote: + jsr pc,rsch + br 1f +dquote: + jsr pc,rsch + mov r0,-(sp) + jsr pc,rsch + swab r0 + bis (sp)+,r0 +1: + mov r0,numval + mov $1,r4 + jsr pc,putw + mov numval,r4 + jsr pc,putw + mov $1,r4 + tst (sp)+ + rts pc + +skip: + jsr pc,rch + mov r0,r4 + cmp r0,$'\e + beq 1f + cmp r0,$'\n + bne skip +1: + rts pc + +garb: + jsr r5,error; 'g + br 8b + +string: + mov $'<,r4 + jsr pc,putw + clr numval +1: + jsr pc,rsch + tst r1 + bne 1f + mov r0,r4 + bis $400,r4 + jsr pc,putw + inc numval + br 1b +1: + mov $-1,r4 + jsr pc,putw + mov $'<,r4 + tst (sp)+ + rts pc + +rsch: + jsr pc,rch + cmp r0,$'\e + beq 4f + cmp r0,$'\n + beq 4f + clr r1 + cmp r0,$'\\ + bne 3f + jsr pc,rch + mov $schar,r2 +1: + cmpb (r2)+,r0 + beq 2f + tstb (r2)+ + bpl 1b + rts pc +2: + movb (r2)+,r0 + clr r1 + rts pc +3: + cmp r0,$'> + bne 1f + inc r1 +1: + rts pc +4: + jsr r5,error; '< + jmp aexit + +schar: + .byte 'n, 012 + .byte 't, 011 + .byte 'e, 004 + .byte '0, 000 + .byte 'r, 015 + .byte 'a, 006 + .byte 'p, 033 + .byte 0, -1 + diff --git a/source/as/as16.s b/source/as/as16.s new file mode 100644 index 0000000..799c9fe --- /dev/null +++ b/source/as/as16.s @@ -0,0 +1,291 @@ +/ +/ + +/ a6 -- pdp-11 assembler pass 1 + +opline: + mov r4,r0 + jsr r5,betwen; 0; 200 + br 1f + cmp r0,$'< + bne xpr + jmp opl17 +xpr: + jsr pc,expres + add $2,dot + rts pc +1: + movb (r4),r0 + cmp r0,$24 + beq xpr + jsr r5,betwen; 5; 36 + br xpr + mov r0,-(sp) + jsr pc,readop + mov (sp)+,r0 + asl r0 + jmp *1f-12(r0) + +1: + opl13 / map fop freg,fdst to double + opl6 + opl7 + opl10 + opl11 + opl13 / map fld/fst to double + opl13 + opl13 / map fop fsrc,freg to double + opl15 + opl16 + opl17 + opl20 + opl21 + opl22 + opl23 + xpr + opl25 + opl26 + opl27 + opl13 / map mul s,r to double + opl31 + opl32 + xpr + xpr + opl35 + opl36 + +/ jbr +opl35: + mov $4,-(sp) + br 1f + +/ jeq, etc +opl36: + mov $6,-(sp) +1: + jsr pc,expres + cmp r3,dotrel + bne 1f + sub dot,r2 + bge 1f + cmp r2,$-376 + blt 1f + mov $2,(sp) +1: + add (sp)+,dot + rts pc + +/double +opl13: +opl7: + jsr pc,addres +op2: + cmp r4,$', + beq 1f + jsr pc,errora + rts pc +1: + jsr pc,readop +opl15: / single operand + jsr pc,addres + add $2,dot + rts pc + +opl31: / sob + jsr pc,expres + cmp r4,$', + beq 1f + jsr pc,errora +1: + jsr pc,readop + +/branch +opl6: +opl10: +opl11: + jsr pc,expres + add $2,dot + rts pc + +/ .byte +opl16: + jsr pc,expres + inc dot + cmp r4,$', + bne 1f + jsr pc,readop + br opl16 +1: + rts pc + +/ < (.ascii) +opl17: + add numval,dot + jsr pc,readop + rts pc + +/.even +opl20: + inc dot + bic $1,dot + rts pc + +/.if +opl21: + jsr pc,expres + tst r3 + bne 1f + jsr r5,error; 'U +1: + tst r2 + bne opl22 + inc ifflg +opl22: /endif + rts pc + +/.globl +opl23: + cmp r4,$200 + blo 1f + bisb $40,(r4) + jsr pc,readop + cmp r4,$', + bne 1f + jsr pc,readop + br opl23 +1: + rts pc + +opl25: +opl26: +opl27: + mov dotrel,r1 + asl r1 + mov dot,savdot-4(r1) + mov savdot-[2*25](r0),dot + asr r0 + sub $25-2,r0 + mov r0,dotrel + rts pc + +/ .common +opl32: + cmp r4,$200 + blo 1f + bis $40,(r4) + jsr pc,readop + cmp r4,$', + bne 1f + jsr pc,readop + jsr pc,expres + rts pc +1: + jsr r5,error; 'x + rts pc + +addres: + cmp r4,$'( + beq alp + cmp r4,$'- + beq amin + cmp r4,$'$ + beq adoll + cmp r4,$'* + beq astar +getx: + jsr pc,expres + cmp r4,$'( + bne 2f + jsr pc,readop + jsr pc,expres + jsr pc,checkreg + jsr pc,checkrp + add $2,dot + clr r0 + rts pc +2: + cmp r3,$24 / register type + bne 1f + jsr pc,checkreg + clr r0 + rts pc +1: + add $2,dot + clr r0 + rts pc + +alp: + jsr pc,readop + jsr pc,expres + jsr pc,checkrp + jsr pc,checkreg + cmp r4,$'+ + bne 1f + jsr pc,readop + clr r0 + rts pc +1: + mov $2,r0 + rts pc + +amin: + jsr pc,readop + cmp r4,$'( + beq 1f + mov r4,savop + mov $'-,r4 + br getx +1: + jsr pc,readop + jsr pc,expres + jsr pc,checkrp + jsr pc,checkreg + clr r0 + rts pc + +adoll: + jsr pc,readop + jsr pc,expres + add $2,dot + clr r0 + rts pc + +astar: + jsr pc,readop + cmp r4,$'* + bne 1f + jsr r5,error; '* +1: + jsr pc,addres + add r0,dot + rts pc + +errora: + jsr r5,error; 'a + rts pc + +checkreg: + cmp r2,$7 + bhi 1f + cmp r3,$1 + beq 2f + cmp r3,$4 + bhi 2f +1: + jsr pc,errora +2: + rts pc + +errore: + jsr r5,error; 'e + rts pc + +checkrp: + cmp r4,$') + beq 1f + jsr r5,error; ') + rts pc +1: + jsr pc,readop + rts pc + diff --git a/source/as/as17.s b/source/as/as17.s new file mode 100644 index 0000000..d7ee5d4 --- /dev/null +++ b/source/as/as17.s @@ -0,0 +1,220 @@ +/ +/ + +/ a7 -- pdp-11 assembler pass 1 + +expres: + mov r5,-(sp) + mov $'+,-(sp) + clr opfound + clr r2 + mov $1,r3 + br 1f +advanc: + jsr pc,readop +1: + mov r4,r0 + jsr r5,betwen; 0; 177 + br .+4 + br 7f + movb (r4),r0 + mov 2(r4),r1 + br oprand +7: + cmp r4,$141 + blo 1f + cmp r4,$141+10. + bhis 2f + movb curfbr-141(r4),r0 + asl r4 + mov curfb-[2*141](r4),r2 + bpl oprand + jsr r5,error; 'f + br oprand +2: + clr r3 + clr r2 + br oprand +1: + mov $esw1,r1 +1: + cmp (r1)+,r4 + beq 1f + tst (r1)+ + bne 1b + tst opfound + bne 2f + jsr pc,errore +2: + tst (sp)+ + mov (sp)+,r5 + rts pc +1: + jmp *(r1) + +esw1: + '+; binop + '-; binop + '*; binop + '/; binop + '&; binop + 037; binop + 035; binop + 036; binop + '%; binop + '[; brack + '^; binop + 1; exnum + '!; binop + 0; 0 + +binop: + cmpb (sp),$'+ + beq 1f + jsr pc,errore +1: + movb r4,(sp) + br advanc + +exnum: + mov numval,r1 + mov $1,r0 + br oprand + +brack: + mov r2,-(sp) + mov r3,-(sp) + jsr pc,readop + jsr pc,expres + cmp r4,$'] + beq 1f + jsr r5,error; '] +1: + mov r3,r0 + mov r2,r1 + mov (sp)+,r3 + mov (sp)+,r2 + +oprand: + inc opfound + mov $exsw2,r5 +1: + cmp (sp),(r5)+ + beq 1f + tst (r5)+ + bne 1b + br eoprnd +1: + jmp *(r5) + +exsw2: + '+; exadd + '-; exsub + '*; exmul + '/; exdiv + 037; exor + '&; exand + 035;exlsh + 036;exrsh + '%; exmod + '!; exnot + '^; excmbin + 0; 0 + +excmbin: + mov r0,r3 / give left flag of right + br eoprnd + +exrsh: + neg r1 + beq exlsh + inc r1 + clc + ror r2 +exlsh: + jsr r5,combin; 0 + als r1,r2 + br eoprnd + +exmod: + jsr r5,combin; 0 + mov r1,-(sp) + mov r2,r1 + clr r0 + dvd (sp)+,r0 + mov r1,r2 + br eoprnd + +exadd: + jsr r5,combin; 0 + add r1,r2 + br eoprnd + +exsub: + jsr r5,combin; 1 + sub r1,r2 + br eoprnd + +exand: + jsr r5,combin; 0 + com r1 + bic r1,r2 + br eoprnd + +exor: + jsr r5,combin; 0 + bis r1,r2 + br eoprnd + +exmul: + jsr r5,combin; 0 + mpy r2,r1 + mov r1,r2 + br eoprnd + +exdiv: + jsr r5,combin; 0 + mov r1,-(sp) + mov r2,r1 + clr r0 + dvd (sp)+,r0 + mov r0,r2 + br eoprnd + +exnot: + jsr r5,combin; 0 + com r1 + add r1,r2 + br eoprnd + +eoprnd: + mov $'+,(sp) + jmp advanc + +combin: + mov r0,-(sp) + bis r3,(sp) + bic $!40,(sp) + bic $!37,r0 + bic $!37,r3 + cmp r0,r3 + ble 1f + mov r0,-(sp) + mov r3,r0 + mov (sp)+,r3 +1: + tst r0 + beq 1f + tst (r5)+ + beq 2f + cmp r0,r3 + bne 2f + mov $1,r3 + br 2f +1: + tst (r5)+ + clr r3 +2: + bis (sp)+,r3 + rts r5 + diff --git a/source/as/as18.s b/source/as/as18.s new file mode 100644 index 0000000..76f0c75 --- /dev/null +++ b/source/as/as18.s @@ -0,0 +1,65 @@ +/ +/ + +/ a8 -- pdp-11 assembler pass 1 + +chartab: + .byte -14,-14,-14,-14,-02,-14,-14,-14 + .byte -14,-22, -2,-14,-14,-22,-14,-14 + .byte -14,-14,-14,-14,-14,-14,-14,-14 + .byte -14,-14,-14,-14,-14,-14,-14,-14 + .byte -22,-20,-16,-14,-20,-20,-20,-12 + .byte -20,-20,-20,-20,-20,-20,056,-06 + .byte 060,061,062,063,064,065,066,067 + .byte 070,071,-20,-02,-00,-20,-14,-14 + .byte -14,101,102,103,104,105,106,107 + .byte 110,111,112,113,114,115,116,117 + .byte 120,121,122,123,124,125,126,127 + .byte 130,131,132,-20,-24,-20,-20,137 + .byte -14,141,142,143,144,145,146,147 + .byte 150,151,152,153,154,155,156,157 + .byte 160,161,162,163,164,165,166,167 + .byte 170,171,172,-14,-26,-14,176,-14 + +.data + +namedone:.byte 0 +a.tmp1: +a.tmp2: +a.tmp3: + .even +curfb: + -1;-1;-1;-1;-1;-1;-1;-1;-1;-1 +obufp: outbuf +symend: usymtab + +.bss +curfbr: .=.+10. +savdot: .=.+6 +bufcnt: .=.+2 +hshsiz = 1553. +hshtab: .=2*hshsiz+. +pof: .=.+1 +wordf: .=.+1 +fin: .=.+1 +fbfil: .=.+1 +fileflg:.=.+1 +errflg: .=.+1 +ch: .=.+1 +.even +symbol: .=.+8. +obufc: .=.+2 +outbuf: .=.+512. +line: .=.+2 +inbfcnt:.=.+2 +ifflg: .=.+2 +inbfp: .=.+2 +nargs: .=.+2 +curarg: .=.+2 +opfound:.=.+2 +savop: .=.+2 +numval: .=.+2 +nxtfb: .=.+4 +usymtab:.=.+36. +end: +.text diff --git a/source/as/as19.s b/source/as/as19.s new file mode 100644 index 0000000..2804f14 --- /dev/null +++ b/source/as/as19.s @@ -0,0 +1,347 @@ +/ +/ + +/ a9 -- pdp-11 assembler pass 1 + +eae = 0 + +/ key to types + +/ 0 undefined +/ 1 absolute +/ 2 text +/ 3 data +/ 4 bss +/ 5 flop freg,dst (movfo, = stcfd) +/ 6 branch +/ 7 jsr +/ 10 rts +/ 11 sys +/ 12 movf (=ldf,stf) +/ 13 double operand (mov) +/ 14 flop fsrc,freg (addf) +/ 15 single operand (clr) +/ 16 .byte +/ 17 string (.ascii, "<") +/ 20 .even +/ 21 .if +/ 22 .endif +/ 23 .globl +/ 24 register +/ 25 .text +/ 26 .data +/ 27 .bss +/ 30 mul,div, etc +/ 31 sob +/ 32 .comm +/ 33 estimated text +/ 34 estimated data +/ 35 jbr +/ 36 jeq, jne, etc + + .data +symtab: +/ special variables + +<.\0\0\0\0\0\0\0>; dotrel:02; dot:000000 +<..\0\0\0\0\0\0>; 01; dotdot:000000 + +/ register + +; 24;000000 +; 24;000001 +; 24;000002 +; 24;000003 +; 24;000004 +; 24;000005 +; 24;000006 +; 24;000007 + +.if eae + +/eae & switches + +; 01;177570 +; 01;177300 +; 01;177302 +; 01;177304 +; 01;177306 +; 01;177310 +; 01;177311 +; 01;177312 +; 01;177314 +; 01;177316 + +.endif + +/ system calls + +; 01;0000001 +; 01;0000002 +; 01;0000003 +; 01;0000004 +; 01;0000005 +; 01;0000006 +; 01;0000007 +; 01;0000010 +; 01;0000011 +; 01;0000012 +; 01;0000013 +; 01;0000014 +; 01;0000015 +; 01;0000016 +; 01;0000017 +; 01;0000020 +; 01;0000021 +; 01;0000022 +; 01;0000023 +; 01;0000024 +; 01;0000025 +; 01;0000026 +; 01;0000027 +; 01;0000030 +; 01;0000031 +; 01;0000034 +; 01;0000036 +; 01;0000037 +; 01;0000040 +; 01;0000042 +; 01;0000060 + +/ double operand + +; 13;0010000 +; 13;0110000 +; 13;0020000 +; 13;0120000 +; 13;0030000 +; 13;0130000 +; 13;0040000 +; 13;0140000 +; 13;0050000 +; 13;0150000 +; 13;0060000 +; 13;0160000 + +/ branch + +; 06;0000400 +; 06;0001000 +; 06;0001400 +; 06;0002000 +; 06;0002400 +; 06;0003000 +; 06;0003400 +; 06;0100000 +; 06;0100400 +; 06;0101000 +; 06;0101400 +; 06;0102000 +; 06;0102400 +; 06;0103000 +; 06;0103000 +; 06;0103000 +; 06;0103400 +; 06;0103400 +; 06;0103400 + +/ jump/branch type + +; 35;0000400 +; 36;0001000 +; 36;0001400 +; 36;0002000 +; 36;0002400 +; 36;0003000 +; 36;0003400 +; 36;0100000 +; 36;0100400 +; 36;0101000 +; 36;0101400 +; 36;0102000 +; 36;0102400 +; 36;0103000 +; 36;0103000 +; 36;0103000 +; 36;0103400 +; 36;0103400 +; 36;0103400 + +/ single operand + +; 15;0005000 +; 15;0105000 +; 15;0005100 +; 15;0105100 +; 15;0005200 +; 15;0105200 +; 15;0005300 +; 15;0105300 +; 15;0005400 +; 15;0105400 +; 15;0005500 +; 15;0105500 +; 15;0005600 +; 15;0105600 +; 15;0005700 +; 15;0105700 +; 15;0006000 +; 15;0106000 +; 15;0006100 +; 15;0106100 +; 15;0006200 +; 15;0106200 +; 15;0006300 +; 15;0106300 +; 15;0000100 +; 15;0000300 + +/ jsr + +; 07;0004000 + +/ rts + +; 010;000200 + +/ simple operand + +; 011;104400 + +/ flag-setting + +; 01;0000241 +; 01;0000242 +; 01;0000244 +; 01;0000250 +; 01;0000261 +; 01;0000262 +; 01;0000264 +; 01;0000270 + +/ floating point ops + +; 01;170000 +; 01;170001 +; 01;170011 +; 01;170002 +; 01;170012 +; 15;170400 +; 15;170700 +; 15;170600 +; 15;170500 +; 12;172400 +; 14;177000 +; 05;175400 +; 14;177400 +; 05;176000 +; 14;172000 +; 14;173000 +; 14;171000 +; 14;174400 +; 14;173400 +; 14;171400 +; 14;176400 +; 05;175000 +; 15;170100 +; 15;170200 +; 24;000000 +; 24;000001 +; 24;000002 +; 24;000003 +; 24;000004 +; 24;000005 + +/ 11/45 operations + +; 30;072000 +; 30;073000 +; 30;070000 +.if eae-1 +; 30;070000 +; 30;071000 +; 30;072000 +; 30;073000 +.endif +; 30;071000 +; 07;074000 +; 15;006700 +; 11;006400 +; 31;077000 + +/ specials + +<.byte\0\0\0>; 16;000000 +<.even\0\0\0>; 20;000000 +<.if\0\0\0\0\0>; 21;000000 +<.endif\0\0>; 22;000000 +<.globl\0\0>; 23;000000 +<.text\0\0\0>; 25;000000 +<.data\0\0\0>; 26;000000 +<.bss\0\0\0\0>; 27;000000 +<.comm\0\0\0>; 32;000000 + +ebsymtab: + + +start: + sys signal; 2; 1 + ror r0 + bcs 1f + sys signal; 2; aexit +1: + mov sp,r5 + mov (r5)+,r0 + cmpb *2(r5),$'- + bne 1f + tst (r5)+ + dec r0 + br 2f +1: + clr unglob +2: + movb r0,nargs + mov r5,curarg + jsr r5,fcreat; a.tmp1 + movb r0,pof + jsr r5,fcreat; a.tmp2 + movb r0,fbfil + jsr pc,setup + jmp go + +setup: + mov $symtab,r1 +1: + clr r3 + mov $8,r2 + mov r1,-(sp) +2: + movb (r1)+,r4 + beq 2f + add r4,r3 + swab r3 + sob r2,2b +2: + clr r2 + div $hshsiz,r2 + ashc $1,r2 + add $hshtab,r3 +4: + sub r2,r3 + cmp r3,$hshtab + bhi 3f + add $2*hshsiz,r3 +3: + tst -(r3) + bne 4b + mov (sp)+,r1 + mov r1,(r3) + add $12.,r1 + cmp r1,$ebsymtab + blo 1b + rts pc + +/overlay buffer +inbuf = setup +. =inbuf+512. + diff --git a/source/as/as21.s b/source/as/as21.s new file mode 100644 index 0000000..30dbf9d --- /dev/null +++ b/source/as/as21.s @@ -0,0 +1,258 @@ +/ +/ + +/ a21 -- pdp-11 assembler pass 2 + +indir = 0 + +main: + sys signal; 2; 1 + ror r0 + bcs 1f + sys signal; 2; aexit +1: + jmp start + +/ set up sizes and origins + +go: + +/ read in symbol table + + mov $usymtab,r1 +1: + jsr pc,getw + bvs 1f + add $14,symsiz / count symbols + jsr pc,getw + jsr pc,getw + jsr pc,getw + jsr pc,getw + mov r4,r0 + bic $!37,r0 + cmp r0,$2 /text + blo 2f + cmp r0,$3 /data + bhi 2f + add $31,r4 /mark "estimated" + mov r4,(r1)+ + jsr pc,getw + mov r4,(r1)+ + br 3f +2: + clr (r1)+ + clr (r1)+ + jsr pc,getw +3: + jsr pc,setbrk + br 1b +1: + +/ read in f-b definitions + + mov r1,fbbufp + movb fbfil,fin + clr ibufc +1: + jsr pc,getw + bvs 1f + add $31,r4 / "estimated" + mov r4,(r1)+ + jsr pc,getw + mov r4,(r1)+ + jsr pc,setbrk + br 1b +1: + mov r1,endtable + mov $100000,(r1)+ + +/ set up input text file; initialize f-b table + + jsr pc,setup +/ do pass 1 + + jsr pc,assem + +/ prepare for pass 2 + cmp outmod,$777 + beq 1f + jmp aexit +1: + clr dot + mov $2,dotrel + mov $..,dotdot + clr brtabp + movb fin,r0 + sys close + jsr r5,ofile; a.tmp1 + movb r0,fin + clr ibufc + jsr pc,setup + inc passno + inc bsssiz + bic $1,bsssiz + mov txtsiz,r1 + inc r1 + bic $1,r1 + mov r1,txtsiz + mov datsiz,r2 + inc r2 + bic $1,r2 + mov r2,datsiz + mov r1,r3 + mov r3,datbase / txtsiz + mov r3,savdot+2 + add r2,r3 + mov r3,bssbase / txtsiz+datsiz + mov r3,savdot+4 + asl r3 + add $20,r3 + mov r3,symseek / 2*txtsiz+2*datsiz+20 + sub r2,r3 + mov r3,drelseek / 2*txtsiz+datsiz + sub r1,r3 + mov r3,trelseek / txtsiz+datsiz+20 + sub r2,r3 + mov r3,datseek / txtsiz+20 + mov $usymtab,r1 +1: + jsr pc,doreloc + add $4,r1 + cmp r1,endtable + blo 1b + clr r0 + jsr r5,oset; txtp + mov trelseek,r0 + jsr r5,oset; relp + mov $8.,r2 + mov $txtmagic,r1 +1: + mov (r1)+,r0 + jsr r5,putw; txtp + dec r2 + bne 1b + jsr pc,assem + +/polish off text and relocation + + jsr r5,flush; txtp + jsr r5,flush; relp + +/ append full symbol table + + mov symf,r0 + mov r0,fin + sys seek; 0; 0; + clr ibufc + mov symseek,r0 + jsr r5,oset; txtp + mov $usymtab,r1 +1: + jsr pc,getw + bvs 1f + mov r4,r0 + jsr r5,putw; txtp + jsr pc,getw + mov r4,r0 + jsr r5,putw; txtp + jsr pc,getw + mov r4,r0 + jsr r5,putw; txtp + jsr pc,getw + mov r4,r0 + jsr r5,putw; txtp + mov (r1)+,r0 + jsr r5,putw; txtp + mov (r1)+,r0 + jsr r5,putw; txtp + jsr pc,getw + jsr pc,getw + br 1b +1: + jsr r5,flush; txtp + jmp aexit + + .data +aexit: + mov a.tmp1,0f + sys unlink; 0:.. + mov a.tmp2,0f + sys unlink; 0:.. + mov a.tmp3,0f + sys unlink; 0:.. + sys chmod; a.out; outmod: 777 + sys exit + .text + +filerr: + mov *(r5),r5 +1: + movb (r5)+,ch + beq 1f + mov $1,r0 + sys write; ch; 1 + br 1b +1: + mov $1,r0 + sys write; qnl; 2 + jmp aexit + +doreloc: + movb (r1),r0 + bne 1f + bisb defund,(r1) +1: + bic $!37,r0 + cmp r0,$5 + bhis 1f + cmp r0,$3 + blo 1f + beq 2f + add bssbase,2(r1) + rts pc +2: + add datbase,2(r1) +1: + rts pc + +setbrk: + mov r1,-(sp) + add $20,r1 + cmp r1,0f + blo 1f + add $512.,0f + sys indir; 9f + .data +9: sys break; 0: end + .text +1: + mov (sp)+,r1 + rts pc + +setup: + mov $curfb,r4 +1: + clr (r4)+ + cmp r4,$curfb+40. + blo 1b + mov txtfil,fin + clr ibufc + clr r4 +1: + jsr pc,fbadv + tstb (r4)+ + cmp r4,$10. + blt 1b + rts pc + +ofile: + mov *(r5),0f + sys indir; 9f + .data +9: sys open; 0:..; 0 + .text + bes 1f + tst (r5)+ + rts r5 +1: + jmp filerr diff --git a/source/as/as22.s b/source/as/as22.s new file mode 100644 index 0000000..c9a4bd3 --- /dev/null +++ b/source/as/as22.s @@ -0,0 +1,151 @@ +/ +/ + +/ a2 -- pdp-11 assembler pass 2 + +outw: + cmp dot-2,$4 + beq 9f + bit $1,dot + bne 1f + add $2,dot + tstb passno + beq 8f + clr -(sp) + rol r3 + adc (sp) + asr r3 / get relative pc bit + cmp r3,$40 + bne 2f +/ external references + mov $666,outmod / make nonexecutable + mov xsymbol,r3 + sub $usymtab,r3 + asl r3 + bis $4,r3 / external relocation + br 3f +2: + bic $40,r3 / clear any ext bits + cmp r3,$5 + blo 4f + cmp r3,$33 / est. text, data + beq 6f + cmp r3,$34 + bne 7f +6: + jsr r5,error; 'r +7: + mov $1,r3 / make absolute +4: + cmp r3,$2 + blo 5f + cmp r3,$4 + bhi 5f + tst (sp) + bne 4f + add dotdot,r2 + br 4f +5: + tst (sp) + beq 4f + sub dotdot,r2 +4: + dec r3 + bpl 3f + clr r3 +3: + asl r3 + bis (sp)+,r3 + mov r2,r0 + jsr r5,putw; txtp + add $2,*tseekp + mov r3,r0 + jsr r5,putw; relp + add $2,*rseekp +8: + rts pc +1: + jsr r5,error; 'o + clr r3 + jsr pc,outb + rts pc + +9: + jsr r5,error; 'x + rts pc + +outb: + cmp dot-2,$4 / test bss mode + beq 9b + cmp r3,$1 + blos 1f + jsr r5,error; 'r +1: + tstb passno + beq 2f + mov r2,r0 + bit $1,dot + bne 1f + jsr r5,putw; txtp + clr r0 + jsr r5,putw; relp + add $2,*rseekp + add $2,*tseekp + br 2f +1: + mov txtp,r0 + movb r2,-1(r0) +2: + inc dot + rts pc + +error: + mov $666,outmod / make nonexecutable + mov r3,-(sp) + mov r2,-(sp) + mov r1,-(sp) + mov r0,-(sp) + mov $argb,r1 +1: + movb (r1),ch + beq 1f + clrb (r1)+ + mov $1,r0 + sys write; ch; 1 + br 1b +1: + mov (r5)+,r0 + movb r0,0f + mov line,r3 + mov $0f+6,r0 + mov $4,r1 +2: + clr r2 + dvd $10.,r2 + add $'0,r3 + movb r3,-(r0) + mov r2,r3 + sob r1,2b + mov $1,r0 + sys write; 0f; 7 + mov (sp)+,r0 + mov (sp)+,r1 + mov (sp)+,r2 + mov (sp)+,r3 + rts r5 + + .data +0: + .even + .text + +betwen: + cmp r0,(r5)+ + blt 1f + cmp (r5)+,r0 + blt 2f +1: + tst (r5)+ +2: + rts r5 + diff --git a/source/as/as23.s b/source/as/as23.s new file mode 100644 index 0000000..26f16c8 --- /dev/null +++ b/source/as/as23.s @@ -0,0 +1,165 @@ +/ +/ + +/ a3 -- pdp-11 assembler pass 2 + +assem: + jsr pc,readop + cmp r4,$5 + beq 2f + cmp r4,$'< + beq 2f + jsr pc,checkeos + br eal1 + mov r4,-(sp) + cmp (sp),$1 + bne 1f + mov $2,(sp) + jsr pc,getw + mov r4,numval +1: + jsr pc,readop + cmp r4,$'= + beq 4f + cmp r4,$': + beq 1f + mov r4,savop + mov (sp)+,r4 +2: + jsr pc,opline +dotmax: + tstb passno + bne eal1 + movb dotrel,r0 + asl r0 + cmp dot,txtsiz-4(r0) + blos ealoop + mov dot,txtsiz-4(r0) +eal1: + jmp ealoop +1: + mov (sp)+,r4 + cmp r4,$200 + bhis 1f + cmp r4,$2 + beq 3f + jsr r5,error; 'x + br assem +1: + tstb passno + bne 2f + movb (r4),r0 + bic $!37,r0 + beq 5f + cmp r0,$33 + blt 6f + cmp r0,$34 + ble 5f +6: + jsr r5,error; 'm +5: + bic $37,(r4) + bis dotrel,(r4) + mov 2(r4),brdelt + sub dot,brdelt + mov dot,2(r4) + br assem +2: + cmp dot,2(r4) + beq assem + jsr r5,error; 'p + br assem +3: + mov numval,r4 + jsr pc,fbadv + asl r4 + mov curfb(r4),r0 + movb dotrel,(r0) + mov 2(r0),brdelt + sub dot,brdelt + mov dot,2(r0) + br assem +4: + jsr pc,readop + jsr pc,expres + mov (sp)+,r1 + cmp r1,$symtab /test for dot + bne 1f + bic $40,r3 + cmp r3,dotrel / can't change relocation + bne 2f + cmp r3,$4 / bss + bne 3f + mov r2,dot + br dotmax +3: + sub dot,r2 + bmi 2f + mov r2,-(sp) +3: + dec (sp) + bmi 3f + clr r2 + mov $1,r3 + jsr pc,outb + br 3b +3: + tst (sp)+ + br dotmax +2: + jsr r5,error; '. + br ealoop +1: + cmp r3,$40 + bne 1f + jsr r5,error; 'r +1: + bic $37,(r1) + bic $!37,r3 + bne 1f + clr r2 +1: + bisb r3,(r1) + mov r2,2(r1) + +ealoop: + cmp r4,$'\n + beq 1f + cmp r4,$'\e + bne 9f + rts pc +1: + inc line +9: + jmp assem + +checkeos: + cmp r4,$'\n + beq 1f + cmp r4,$'; + beq 1f + cmp r4,$'\e + beq 1f + add $2,(sp) +1: + rts pc + +fbadv: + asl r4 + mov nxtfb(r4),r1 + mov r1,curfb(r4) + bne 1f + mov fbbufp,r1 + br 2f +1: + add $4,r1 +2: + cmpb 1(r1),r4 + beq 1f + tst (r1) + bpl 1b +1: + mov r1,nxtfb(r4) + asr r4 + rts pc + diff --git a/source/as/as24.s b/source/as/as24.s new file mode 100644 index 0000000..c8f072c --- /dev/null +++ b/source/as/as24.s @@ -0,0 +1,113 @@ +/ +/ + +/ a4 -- pdp-11 assembler pass 2 + +oset: + mov r2,-(sp) + mov (r5)+,r1 + mov r0,r2 + bic $!777,r0 + add r1,r0 + add $6,r0 + mov r0,(r1)+ / next slot + mov r1,r0 + add $1004,r0 + mov r0,(r1)+ / buf max + mov r2,(r1)+ / seek addr + mov (sp)+,r2 + rts r5 + +putw: + mov r1,-(sp) + mov r2,-(sp) + mov (r5)+,r2 + mov (r2)+,r1 / slot + cmp r1,(r2) / buf max + bhis 1f + mov r0,(r1)+ + mov r1,-(r2) + br 2f +1: + tst (r2)+ + mov r0,-(sp) + jsr r5,flush1 + mov (sp)+,r0 + mov r0,*(r2)+ + add $2,-(r2) +2: + mov (sp)+,r2 + mov (sp)+,r1 + rts r5 + +flush: + mov (r5)+,r2 + cmp (r2)+,(r2)+ +flush1: + mov (r2)+,r1 + mov r1,0f / seek address + mov fout,r0 + sys indir; 9f + .data +9: sys seek; 0:..; 0 + .text + bic $!777,r1 + add r2,r1 / write address + mov r1,0f + mov r2,r0 + bis $777,-(r2) + inc (r2) / new seek addr + cmp -(r2),-(r2) + sub (r2),r1 + neg r1 + mov r1,0f+2 / count + mov r0,(r2) / new next slot + mov fout,r0 + sys indir; 9f + .data +9: sys write; 0:..; .. + .text + rts r5 + +readop: + mov savop,r4 + beq 1f + clr savop + rts pc +1: + jsr pc,getw1 + cmp r4,$200 + blo 1f + cmp r4,$4000 + blo 2f + add $usymtab-4000,r4 + rts pc +2: + add $symtab-1000,r4 +1: + rts pc + +getw: + mov savop,r4 + beq getw1 + clr savop + rts pc +getw1: + dec ibufc + bgt 1f + movb fin,r0 + sys read; inbuf; 512. + bes 3f + asr r0 + mov r0,ibufc + bne 2f +3: + mov $4,r4 + sev + rts pc +2: + mov $inbuf,ibufp +1: + mov *ibufp,r4 + add $2,ibufp + rts pc diff --git a/source/as/as25.s b/source/as/as25.s new file mode 100644 index 0000000..f8aaf11 --- /dev/null +++ b/source/as/as25.s @@ -0,0 +1,4 @@ +/ +/ + +/ as25 is empty diff --git a/source/as/as26.s b/source/as/as26.s new file mode 100644 index 0000000..9bff6c9 --- /dev/null +++ b/source/as/as26.s @@ -0,0 +1,559 @@ +/ +/ + +/ a6 -- pdp-11 assembler pass 2 + +opline: + mov r4,r0 + jsr r5,betwen; 0; 177 + br 2f + cmp r4,$5 + beq opeof + cmp r4,$'< + bne xpr + jmp opl17 +xxpr: + tst (sp)+ +xpr: + jsr pc,expres + jsr pc,outw + rts pc +2: + movb (r4),r0 + cmp r0,$24 /reg + beq xpr + cmp r0,$33 /est text + beq xpr + cmp r0,$34 / est data + beq xpr + jsr r5,betwen; 5; 36 + br xpr + mov 2(r4),-(sp) + mov r0,-(sp) + jsr pc,readop + mov (sp)+,r0 + asl r0 + mov $adrbuf,r5 + clr swapf + mov $-1,rlimit + jmp *1f-10.(r0) + +1: + opl5 + opl6 + opl7 + opl10 + opl11 + opl12 + opl13 + opl14 + opl15 + opl16 + opl17 + opl20 + opl21 + opl22 + opl23 + xxpr + opl25 + opl26 + opl27 + opl30 + opl31 + opl32 + xxpr + xxpr + opl35 + opl36 + +opeof: + mov $1,line + mov $20,-(sp) + mov $argb,r1 +1: + jsr pc,getw + tst r4 + bmi 1f + movb r4,(r1)+ + dec (sp) + bgt 1b + tstb -(r1) + br 1b +1: + movb $'\n,(r1)+ + clrb (r1)+ + tst (sp)+ + rts pc + +opl30: / mpy, dvd etc + inc swapf + mov $1000,rlimit + br opl13 + +opl14: / flop freg,fsrc + inc swapf + +opl5: / flop src,freg + mov $400,rlimit + +/double +opl13: + jsr pc,addres +op2a: + mov r2,-(sp) + jsr pc,readop +op2b: + jsr pc,addres + tst swapf + beq 1f + mov (sp),r0 + mov r2,(sp) + mov r0,r2 +1: + swab (sp) + asr (sp) + asr (sp) + cmp (sp),rlimit + blo 1f + jsr r5,error; 'x +1: + bis (sp)+,r2 + bis (sp)+,r2 + clr r3 + jsr pc,outw + mov $adrbuf,r1 +1: + cmp r1,r5 + bhis 1f + mov (r1)+,r2 + mov (r1)+,r3 + mov (r1)+,xsymbol + jsr pc,outw + br 1b +1: + rts pc + +opl15: / single operand + clr -(sp) + br op2b + +opl12: / movf + mov $400,rlimit + jsr pc,addres + cmp r2,$4 / see if source is fregister + blo 1f + inc swapf + br op2a +1: + mov $174000,(sp) + br op2a + +/ jbr +opl35: +/ jeq, jne, etc +opl36: + jsr pc,expres + tstb passno + bne 1f + mov r2,r0 + jsr pc,setbr + tst r2 + beq 2f + cmp (sp),$br + beq 2f + add $2,r2 +2: + add r2,dot / if doesn't fit + add $2,dot + tst (sp)+ + rts pc +1: + jsr pc,getbr + bcc dobranch + mov (sp)+,r0 + mov r2,-(sp) + mov r3,-(sp) + cmp r0,$br + beq 2f + mov $402,r2 + xor r0,r2 / flip cond, add ".+6" + mov $1,r3 + jsr pc,outw +2: + mov $1,r3 + mov $jmp+37,r2 + jsr pc,outw + mov (sp)+,r3 + mov (sp)+,r2 + jsr pc,outw + rts pc + +/sob +opl31: / sob + jsr pc,expres + jsr pc,checkreg + swab r2 + asr r2 + asr r2 + bis r2,(sp) + jsr pc,readop + jsr pc,expres + tstb passno + beq 3f + sub dot,r2 + neg r2 + mov r2,r0 + jsr r5,betwen; -2; 175 + br 2f + add $4,r2 + br 1f + +/branch +opl6: + jsr pc,expres + tstb passno + beq 3f +dobranch: + sub dot,r2 + mov r2,r0 + jsr r5,betwen; -254.; 256. + br 2f +1: + bit $1,r2 + bne 2f + cmp r3,dot-2 / same relocation as . + bne 2f + asr r2 + dec r2 + bic $177400,r2 +3: + bis (sp)+,r2 + clr r3 + jsr pc,outw + rts pc +2: + jsr r5,error; 'b + clr r2 + br 3b + +/jsr +opl7: + jsr pc,expres + jsr pc,checkreg + jmp op2a + +/ rts +opl10: + jsr pc,expres + jsr pc,checkreg + br 1f + +/ sys, emt etc +opl11: + jsr pc,expres + cmp r2,$64. + bhis 0f + cmp r3,$1 + ble 1f +0: + jsr pc,errora +1: + bis (sp)+,r2 + jsr pc,outw + rts pc + +/ .byte +opl16: + jsr pc,expres + jsr pc,outb + cmp r4,$', + bne 1f + jsr pc,readop + br opl16 +1: + tst (sp)+ + rts pc + +/ < (.ascii) +opl17: + jsr pc,getw + mov $1,r3 + mov r4,r2 + bmi 2f + bic $!377,r2 + jsr pc,outb + br opl17 +2: + jsr pc,getw + rts pc + +/.even +opl20: + bit $1,dot + beq 1f + cmp dot-2,$4 + beq 2f / bss mode + clr r2 + clr r3 + jsr pc,outb + br 1f +2: + inc dot +1: + tst (sp)+ + rts pc +opl21: /if + jsr pc,expres +opl22: +oplret: + tst (sp)+ + rts pc + + +/.globl +opl23: + cmp r4,$200 + blo 1f + bisb $40,(r4) + jsr pc,readop + cmp r4,$', + bne 1f + jsr pc,readop + br opl23 +1: + tst (sp)+ + rts pc + +/ .text, .data, .bss +opl25: +opl26: +opl27: + inc dot + bic $1,dot + mov r0,-(sp) + mov dot-2,r1 + asl r1 + mov dot,savdot-4(r1) + tstb passno + beq 1f + jsr r5,flush; txtp + jsr r5,flush; relp + mov (sp),r2 + add $txtseek-[2*25],r2 + mov r2,tseekp + mov (r2),r0 + jsr r5,oset; txtp + add $trelseek-txtseek,r2 + mov (r2),r0 + mov r2,rseekp + jsr r5,oset; relp +1: + mov (sp)+,r0 + mov savdot-[2*25](r0),dot + asr r0 + sub $25-2,r0 + mov r0,dot-2 / new . relocation + tst (sp)+ + rts pc + +opl32: + cmp r4,$200 + blo 1f + mov r4,-(sp) + jsr pc,readop + jsr pc,readop + jsr pc,expres + mov (sp)+,r0 + bit $37,(r0) + bne 1f + bis $40,(r0) + mov r2,2(r0) +1: + tst (sp)+ + rts pc + +addres: + clr -(sp) +4: + cmp r4,$'( + beq alp + cmp r4,$'- + beq amin + cmp r4,$'$ + beq adoll + cmp r4,$'* + bne getx + jmp astar +getx: + jsr pc,expres + cmp r4,$'( + bne 2f + jsr pc,readop + mov r2,(r5)+ + mov r3,(r5)+ + mov xsymbol,(r5)+ + jsr pc,expres + jsr pc,checkreg + jsr pc,checkrp + bis $60,r2 + bis (sp)+,r2 + rts pc + +2: + cmp r3,$24 + bne 1f + jsr pc,checkreg + bis (sp)+,r2 + rts pc +1: + mov r3,-(sp) + bic $40,r3 + mov (sp)+,r3 + bis $100000,r3 + sub dot,r2 + sub $4,r2 + cmp r5,$adrbuf + beq 1f + sub $2,r2 +1: + mov r2,(r5)+ / index + mov r3,(r5)+ / index reloc. + mov xsymbol,(r5)+ / index global + mov $67,r2 / address mode + bis (sp)+,r2 + rts pc + +alp: + jsr pc,readop + jsr pc,expres + jsr pc,checkrp + jsr pc,checkreg + cmp r4,$'+ + beq 1f + tst (sp)+ + beq 2f + bis $70,r2 + clr (r5)+ + clr (r5)+ + mov xsymbol,(r5)+ + rts pc +2: + bis $10,r2 + rts pc +1: + jsr pc,readop + bis $20,r2 + bis (sp)+,r2 + rts pc + +amin: + jsr pc,readop + cmp r4,$'( + beq 1f + mov r4,savop + mov $'-,r4 + br getx +1: + jsr pc,readop + jsr pc,expres + jsr pc,checkrp + jsr pc,checkreg + bis (sp)+,r2 + bis $40,r2 + rts pc + +adoll: + jsr pc,readop + jsr pc,expres + mov r2,(r5)+ + mov r3,(r5)+ + mov xsymbol,(r5)+ + mov (sp)+,r2 + bis $27,r2 + rts pc + +astar: + tst (sp) + beq 1f + jsr r5,error; '* +1: + mov $10,(sp) + jsr pc,readop + jmp 4b + +errora: + jsr r5,error; 'a + rts pc + +checkreg: + cmp r2,$7 + bhi 1f + cmp r1,$1 + blos 2f + cmp r3,$5 + blo 1f +2: + rts pc +1: + jsr pc,errora + clr r2 + clr r3 + rts pc + +errore: + jsr r5,error; 'e + rts pc + +checkrp: + cmp r4,$') + beq 1f + jsr r5,error; ') + rts pc +1: + jsr pc,readop + rts pc + +setbr: + mov brtabp,r1 + cmp r1,$brlen + blt 1f + mov $2,r2 + rts pc +1: + inc brtabp + clr -(sp) + sub dot,r0 + ble 1f + sub brdelt,r0 +1: + jsr r5,betwen; -254.; 256. + br 1f + br 2f +1: + mov r1,-(sp) + bic $!7,(sp) + mov $1,r0 + ash (sp)+,r0 + ash $-3,r1 + bisb r0,brtab(r1) + mov $2,(sp) +2: + mov (sp)+,r2 + rts pc + +getbr: + mov brtabp,r1 + cmp r1,$brlen + blt 1f + sec + rts pc +1: + mov r1,-(sp) + bic $!7,(sp) + neg (sp) + inc brtabp + ash $-3,r1 + movb brtab(r1),r1 + ash (sp)+,r1 + ror r1 / 0-bit into c-bit + rts pc diff --git a/source/as/as27.s b/source/as/as27.s new file mode 100644 index 0000000..a4d1625 --- /dev/null +++ b/source/as/as27.s @@ -0,0 +1,294 @@ +/ +/ + +/ a7 -- pdp-11 assembler + +expres: + clr xsymbol +expres1: + mov r5,-(sp) + mov $'+,-(sp) + clr r2 + mov $1,r3 + br 1f +advanc: + jsr pc,readop +1: + mov r4,r0 + jsr r5,betwen; 0; 177 + br .+4 + br 7f + movb (r4),r0 + tst r0 + bne 1f + tstb passno + beq 1f + jsr r5,error; 'u +1: + cmp r0,$40 + bne 1f + mov r4,xsymbol + clr r1 + br oprand +1: + mov 2(r4),r1 + br oprand +7: + cmp r4,$141 + blo 1f + asl r4 + mov curfb-[2*141](r4),r0 + mov 2(r0),r1 + movb (r0),r0 + br oprand +1: + mov $esw1,r1 +1: + cmp (r1)+,r4 + beq 1f + tst (r1)+ + bne 1b + tst (sp)+ + mov (sp)+,r5 + rts pc +1: + jmp *(r1) + +esw1: + '+; binop + '-; binop + '*; binop + '/; binop + '&; binop + 037; binop + 035; binop + 036; binop + '%; binop + '[; brack + '^; binop + 1; exnum + 2; exnum1 + '!; binop + 200; 0 + +binop: + cmpb (sp),$'+ + beq 1f + jsr pc,errore +1: + movb r4,(sp) + br advanc + +exnum1: + mov numval,r1 + br 1f + +exnum: + jsr pc,getw + mov r4,r1 +1: + mov $1,r0 + br oprand + +brack: + mov r2,-(sp) + mov r3,-(sp) + jsr pc,readop + jsr pc,expres1 + cmp r4,$'] + beq 1f + jsr r5,error; '] +1: + mov r3,r0 + mov r2,r1 + mov (sp)+,r3 + mov (sp)+,r2 + +oprand: + mov $exsw2,r5 +1: + cmp (sp),(r5)+ + beq 1f + tst (r5)+ + bne 1b + br eoprnd +1: + jmp *(r5) + +exsw2: + '+; exadd + '-; exsub + '*; exmul + '/; exdiv + 037; exor + '&; exand + 035;exlsh + 036;exrsh + '%; exmod + '^; excmbin + '!; exnot + 200; 0 + +excmbin: + mov r0,r3 + br eoprnd + +exrsh: + neg r1 + beq exlsh + inc r1 + clc + ror r2 +exlsh: + jsr r5,combin; relte2 + als r1,r2 + br eoprnd + +exmod: + jsr r5,combin; relte2 + mov r3,r0 + mov r2,r3 + clr r2 + dvd r1,r2 + mov r3,r2 + mov r0,r3 + br eoprnd + +exadd: + jsr r5,combin; reltp2 + add r1,r2 + br eoprnd + +exsub: + jsr r5,combin; reltm2 + sub r1,r2 + br eoprnd + +exand: + jsr r5,combin; relte2 + com r1 + bic r1,r2 + br eoprnd + +exor: + jsr r5,combin; relte2 + bis r1,r2 + br eoprnd + +exmul: + jsr r5,combin; relte2 + mpy r2,r1 + mov r1,r2 + br eoprnd + +exdiv: + jsr r5,combin; relte2 + mov r3,r0 + mov r2,r3 + clr r2 + dvd r1,r2 + mov r0,r3 + br eoprnd + +exnot: + jsr r5,combin; relte2 + com r1 + add r1,r2 + br eoprnd + +eoprnd: + mov $'+,(sp) + jmp advanc + +combin: + tstb passno + bne combin1 + mov r0,-(sp) + bis r3,(sp) + bic $!40,(sp) + bic $!37,r0 + bic $!37,r3 + cmp r0,r3 + ble 1f + mov r0,-(sp) + mov r3,r0 + mov (sp)+,r3 +1: + tst r0 + beq 1f + cmp (r5)+,$reltm2 + bne 2f + cmp r0,r3 + bne 2f + mov $1,r3 + br 2f +1: + tst (r5)+ + clr r3 +2: + bis (sp)+,r3 + rts r5 +combin1: + mov r1,-(sp) + clr maxtyp + jsr pc,maprel + mov r0,r1 + mpy $6,r1 + mov r3,r0 + jsr pc,maprel + add (r5)+,r0 + add r1,r0 + movb (r0),r3 + bpl 1f + cmp r3,$-1 + beq 2f + jsr r5,error; 'r +2: + mov maxtyp,r3 +1: + mov (sp)+,r1 + rts r5 + +maprel: + cmp r0,$40 + bne 1f + mov $5,r0 + rts pc +1: + bic $!37,r0 + cmp r0,maxtyp + blos 1f + mov r0,maxtyp +1: + cmp r0,$5 + blos 1f + mov $1,r0 +1: + rts pc + +X = -2 +M = -1 +reltp2: + .byte 0, 0, 0, 0, 0, 0 + .byte 0, M, 2, 3, 4,40 + .byte 0, 2, X, X, X, X + .byte 0, 3, X, X, X, X + .byte 0, 4, X, X, X, X + .byte 0,40, X, X, X, X + +reltm2: + .byte 0, 0, 0, 0, 0, 0 + .byte 0, M, 2, 3, 4,40 + .byte 0, X, 1, X, X, X + .byte 0, X, X, 1, X, X + .byte 0, X, X, X, 1, X + .byte 0, X, X, X, X, X + +relte2: + .byte 0, 0, 0, 0, 0, 0 + .byte 0, M, X, X, X, X + .byte 0, X, X, X, X, X + .byte 0, X, X, X, X, X + .byte 0, X, X, X, X, X + .byte 0, X, X, X, X, X + diff --git a/source/as/as28.s b/source/as/as28.s new file mode 100644 index 0000000..d40b24d --- /dev/null +++ b/source/as/as28.s @@ -0,0 +1,77 @@ +/ +/ + +/ as8 -- PDP-11 assembler pass 2 + +qnl: +a.out: + +.even +a.outp: a.out + + .data +a.tmp1: 0 +a.tmp2: 0 +a.tmp3: 0 + +tseekp: txtseek +rseekp: trelseek + +txtmagic: + br .+20 +txtsiz: .=.+2 +datsiz: .=.+2 +bsssiz: .=.+2 +symsiz: .=.+2 +stksiz: .=.+2 +exorig: .=.+2 + .=.+2 + +txtseek: 20 +datseek:.=.+2 + .=.+2 +trelseek:.=.+2 +drelseek:.=.+2 + .=.+2 +symseek:.=.+2 + +.bss + +brlen = 1024. +brtab: .=.+[brlen\/8.] +brtabp: .=.+2 +brdelt: .=.+2 +fbbufp: .=.+2 +defund: .=.+2 +savdot: .=.+6 +datbase:.=.+2 +bssbase:.=.+2 +fbfil: .=.+2 +fin: .=.+2 +ibufc: .=.+2 +txtfil: .=.+2 +symf: .=.+2 +adrbuf: .=.+12. +xsymbol:.=.+2 +fout: .=.+2 +ch: .=.+2 +wordf: .=.+2 +argb: .=.+22. +line: .=.+2 +savop: .=.+2 +curfb: .=.+20. +nxtfb: .=.+20. +numval: .=.+2 +maxtyp: .=.+2 +relfil: .=.+2 +ibufp: .=.+2 +txtp: .=.+6+512. +relp: .=.+6+512. +swapf: .=.+2 +rlimit: .=.+2 +passno: .=.+2 +endtable:.=.+2 +usymtab:.=.+20. +end: + +.text diff --git a/source/as/as29.s b/source/as/as29.s new file mode 100644 index 0000000..d3ca81e --- /dev/null +++ b/source/as/as29.s @@ -0,0 +1,280 @@ +/ +/ + +/ as9 -- PDP-11 assembler pass 2 + +eae = 0 + + .data +symtab: + +/ special variables + +dotrel: 02; dot:000000 /. + 01; dotdot:000000 /.. + +/ register + +24;000000 /r0 +24;000001 /r1 +24;000002 /r2 +24;000003 /r3 +24;000004 /r4 +24;000005 /r5 +24;000006 /sp +24;000007 /pc + + +.if eae +/eae & switches + +01;177570 /csw +01;177300 /div +01;177302 /ac +01;177304 /mq +01;177306 /mul +01;177310 /sc +01;177311 /sr +01;177312 /nor +01;177314 /lsh +01;177316 /ash + +.endif + +/ system calls + +01;0000001 /exit +01;0000002 /fork +01;0000003 /read +01;0000004 /write +01;0000005 /open +01;0000006 /close +01;0000007 /wait +01;0000010 /creat +01;0000011 /link +01;0000012 /unlink +01;0000013 /exec +01;0000014 /chdir +01;0000015 /time +01;0000016 /makdir +01;0000017 /chmod +01;0000020 /chown +01;0000021 /break +01;0000022 /stat +01;0000023 /seek +01;0000024 /tell +01;0000025 /mount +01;0000026 /umount +01;0000027 /setuid +01;0000030 /getuid +01;0000031 /stime +01;0000034 /fstat +01;0000036 /mdate +01;0000037 /stty +01;0000040 /gtty +01;0000042 /nice +01;0000060 /signal + +/ double operand + +13;0010000 /mov +13;0110000 /movb +13;0020000 /cmp +13;0120000 /cmpb +13;0030000 /bit +13;0130000 /bitb +13;0040000 /bic +13;0140000 /bicb +13;0050000 /bis +13;0150000 /bisb +13;0060000 /add +13;0160000 /sub + +/ branch + +06;0000400 /br +06;0001000 /bne +06;0001400 /beq +06;0002000 /bge +06;0002400 /blt +06;0003000 /bgt +06;0003400 /ble +06;0100000 /bpl +06;0100400 /bmi +06;0101000 /bhi +06;0101400 /blos +06;0102000 /bvc +06;0102400 /bvs +06;0103000 /bhis +06;0103000 /bec +06;0103000 /bcc +06;0103400 /blo +06;0103400 /bcs +06;0103400 /bes + +/ jump/ branch type + +35;0000400 /jbr +36;0001000 /jne +36;0001400 /jeq +36;0002000 /jge +36;0002400 /jlt +36;0003000 /jgt +36;0003400 /jle +36;0100000 /jpl +36;0100400 /jmi +36;0101000 /jhi +36;0101400 /jlos +36;0102000 /jvc +36;0102400 /jvs +36;0103000 /jhis +36;0103000 /jec +36;0103000 /jcc +36;0103400 /jlo +36;0103400 /jcs +36;0103400 /jes + +/ single operand + +15;0005000 /clr +15;0105000 /clrb +15;0005100 /com +15;0105100 /comb +15;0005200 /inc +15;0105200 /incb +15;0005300 /dec +15;0105300 /decb +15;0005400 /neg +15;0105400 /negb +15;0005500 /adc +15;0105500 /adcb +15;0005600 /sbc +15;0105600 /sbcb +15;0005700 /tst +15;0105700 /tstb +15;0006000 /ror +15;0106000 /rorb +15;0006100 /rol +15;0106100 /rolb +15;0006200 /asr +15;0106200 /asrb +15;0006300 /asl +15;0106300 /aslb +15;0000100 /jmp +15;0000300 /swab + +/ jsr + +07;0004000 /jsr + +/ rts + +10;000200 /rts + +/ simple operand + +11;104400 /sys + +/ flag-setting + +01;0000241 /clc +01;0000242 /clv +01;0000244 /clz +01;0000250 /cln +01;0000261 /sec +01;0000262 /sev +01;0000264 /sez +01;0000270 /sen + +/ floating point ops + +01;170000 / cfcc +01;170001 / setf +01;170011 / setd +01;170002 / seti +01;170012 / setl +15;170400 / clrf +15;170700 / negf +15;170600 / absf +15;170500 / tstf +12;172400 / movf +14;177000 / movif +05;175400 / movfi +14;177400 / movof +05;176000 / movfo +14;172000 / addf +14;173000 / subf +14;171000 / mulf +14;174400 / divf +14;173400 / cmpf +14;171400 / modf +14;176400 / movie +05;175000 / movei +15;170100 / ldfps +15;170200 / stfps +24;000000 / fr0 +24;000001 / fr1 +24;000002 / fr2 +24;000003 / fr3 +24;000004 / fr4 +24;000005 / fr5 + +/ 11/45 operations + +30;072000 /als (ash) +30;073000 /alsc (ashc) +30;070000 /mpy +.if eae-1 +30;070000/ mul +30;071000 / div +30;072000 / ash +30;073000 /ashc +.endif +30;071000 /dvd +07;074000 /xor +15;006700 /sxt +11;006400 /mark +31;077000 /sob + +/ specials + +16;000000 /.byte +20;000000 /.even +21;000000 /.if +22;000000 /.endif +23;000000 /.globl +25;000000 /.text +26;000000 /.data +27;000000 /.bss +32;000000 /.comm + +start: + cmp (sp),$4 + bge 1f + jmp aexit +1: + cmp (sp)+,$5 + blt 1f + mov $40,defund / globalize all undefineds +1: + tst (sp)+ + mov (sp)+,a.tmp1 + mov (sp)+,a.tmp2 + mov (sp)+,a.tmp3 + jsr r5,ofile; a.tmp1 + movb r0,txtfil + jsr r5,ofile; a.tmp2 + movb r0,fbfil + jsr r5,ofile; a.tmp3 + movb r0,symf + movb r0,fin + sys creat; a.out; 0 + bec 1f + jsr r5,filerr; a.outp +1: + movb r0,fout + jmp go + +/ overlaid buffer +inbuf = start +. = inbuf+512. diff --git a/source/as/run b/source/as/run new file mode 100644 index 0000000..06d4330 --- /dev/null +++ b/source/as/run @@ -0,0 +1,9 @@ +as as1?.s +ld -s -n a.out +cmp a.out /bin/as +cp a.out /bin/as +as as2?.s +ld -s -n a.out +cmp a.out /lib/as2 +cp a.out /lib/as2 +rm a.out diff --git a/source/c/c00.c b/source/c/c00.c new file mode 100644 index 0000000..51720ec --- /dev/null +++ b/source/c/c00.c @@ -0,0 +1,709 @@ +# +/* C compiler + * + * + * + * Called from cc: + * c0 source temp1 temp2 [ profileflag ] + * temp1 contains some ascii text and the binary expression + * trees. Each tree is introduced by the # character. + * Strings are put on temp2, which cc tacks onto + * temp1 for assembly. + */ + +#include "c0h.c" + +int isn 1; +int stflg 1; +int peeksym -1; +int line 1; +int debug 0; +int dimp 0; +struct tname funcblk { NAME, 0, 0, REG, 0, 0 }; +int *treespace { osspace }; + +struct kwtab { + char *kwname; + int kwval; +} kwtab[] +{ + "int", INT, + "char", CHAR, + "float", FLOAT, + "double", DOUBLE, + "struct", STRUCT, + "long", LONG, + "auto", AUTO, + "extern", EXTERN, + "static", STATIC, + "register", REG, + "goto", GOTO, + "return", RETURN, + "if", IF, + "while", WHILE, + "else", ELSE, + "switch", SWITCH, + "case", CASE, + "break", BREAK, + "continue", CONTIN, + "do", DO, + "default", DEFAULT, + "for", FOR, + "sizeof", SIZEOF, + 0, 0, +}; + +main(argc, argv) +char *argv[]; +{ + extern fin; + register char *sp; + register i; + register struct kwtab *ip; + + if(argc<3) { + error("Arg count"); + exit(1); + } + if((fin=open(argv[1],0))<0) { + error("Can't find %s", argv[1]); + exit(1); + } + if (fcreat(argv[2], obuf)<0 || fcreat(argv[3], sbuf)<0) { + error("Can't create temp"); + exit(1); + } + if (argc>4) + proflg++; + /* + * The hash table locations of the keywords + * are marked; if an identifier hashes to one of + * these locations, it is looked up in in the keyword + * table first. + */ + for (ip=kwtab; (sp = ip->kwname); ip++) { + i = 0; + while (*sp) + i =+ *sp++; + hshtab[i%hshsiz].hflag = FKEYW; + } + while(!eof) { + extdef(); + blkend(); + } + outcode("B", EOF); + strflg++; + outcode("B", EOF); + fflush(obuf); + fflush(sbuf); + exit(nerror!=0); +} + +/* + * Look up the identifier in symbuf in the symbol table. + * If it hashes to the same spot as a keyword, try the keyword table + * first. An initial "." is ignored in the hash. + * Return is a ptr to the symbol table entry. + */ +lookup() +{ + int ihash; + register struct hshtab *rp; + register char *sp, *np; + + ihash = 0; + sp = symbuf; + if (*sp=='.') + sp++; + while (sphflag&FKEYW) + if (findkw()) + return(KEYW); + while (*(np = rp->name)) { + for (sp=symbuf; sp= &hshtab[hshsiz]) + rp = hshtab; + } + if(++hshused >= hshsiz) { + error("Symbol table overflow"); + exit(1); + } + rp->hclass = 0; + rp->htype = 0; + rp->hoffset = 0; + rp->dimp = 0; + rp->hflag =| xdflg; + sp = symbuf; + for (np=rp->name; spkwname); kp++) { + p1 = wp; + while (*p1 == *p2++) + if (*p1++ == '\0') { + cval = kp->kwval; + return(1); + } + } + return(0); +} + + +/* + * Return the next symbol from the input. + * peeksym is a pushed-back symbol, peekc is a pushed-back + * character (after peeksym). + * mosflg means that the next symbol, if an identifier, + * is a member of structure or a structure tag, and it + * gets a "." prepended to it to distinguish + * it from other identifiers. + */ +symbol() { + register c; + register char *sp; + + if (peeksym>=0) { + c = peeksym; + peeksym = -1; + if (c==NAME) + mosflg = 0; + return(c); + } + if (peekc) { + c = peekc; + peekc = 0; + } else + if (eof) + return(EOF); + else + c = getchar(); +loop: + switch(ctab[c]) { + + case INSERT: /* ignore newlines */ + inhdr = 1; + c = getchar(); + goto loop; + + case NEWLN: + if (!inhdr) + line++; + inhdr = 0; + + case SPACE: + c = getchar(); + goto loop; + + case EOF: + eof++; + return(0); + + case PLUS: + return(subseq(c,PLUS,INCBEF)); + + case MINUS: + return(subseq(c,subseq('>',MINUS,ARROW),DECBEF)); + + case ASSIGN: + if (subseq(' ',0,1)) return(ASSIGN); + c = symbol(); + if (c>=PLUS && c<=EXOR) { + if (spnextchar() != ' ' + && (c==MINUS || c==AND || c==TIMES)) { + error("Warning: assignment operator assumed"); + nerror--; + } + return(c+ASPLUS-PLUS); + } + if (c==ASSIGN) + return(EQUAL); + peeksym = c; + return(ASSIGN); + + case LESS: + if (subseq(c,0,1)) return(LSHIFT); + return(subseq('=',LESS,LESSEQ)); + + case GREAT: + if (subseq(c,0,1)) return(RSHIFT); + return(subseq('=',GREAT,GREATEQ)); + + case EXCLA: + return(subseq('=',EXCLA,NEQUAL)); + + case DIVIDE: + if (subseq('*',1,0)) + return(DIVIDE); + while ((c = spnextchar()) != EOF) { + peekc = 0; + if (c=='*') { + if (spnextchar() == '/') { + peekc = 0; + c = getchar(); + goto loop; + } + } + } + eof++; + error("Nonterminated comment"); + return(0); + + case PERIOD: + case DIGIT: + peekc = c; + if ((c=getnum(c=='0'?8:10)) == FCON) + cval = isn++; + return(c); + + case DQUOTE: + return(getstr()); + + case SQUOTE: + return(getcc()); + + case LETTER: + sp = symbuf; + if (mosflg) { + *sp++ = '.'; + mosflg = 0; + } + while(ctab[c]==LETTER || ctab[c]==DIGIT) { + if (sp= 0) { + nchstr++; + if (sp >= &savstr[STRSIZ]) { + sp = savstr; + error("String too long"); + } + *sp++ = c; + } + strptr = sp; + cval = isn++; + return(STRING); +} + +/* + * Write out a string, either in-line + * or in the string temp file labelled by + * lab. + */ +putstr(lab) +{ + register char *sp; + + if (lab) { + strflg++; + outcode("BNB", LABEL, lab, BDATA); + } else + outcode("B", BDATA); + for (sp = savstr; sp= 0) + if(cc++ < NCPW) + *ccp++ = c; + if(cc>NCPW) + error("Long character constant"); + return(CON); +} + +/* + * Read a character in a string or character constant, + * detecting the end of the string. + * It implements the escape sequences. + */ +mapch(ac) +{ + register int a, c, n; + static mpeek; + + c = ac; + if (a = mpeek) + mpeek = 0; + else + a = getchar(); +loop: + if (a==c) + return(-1); + switch(a) { + + case '\n': + case '\0': + error("Nonterminated string"); + peekc = a; + return(-1); + + case '\\': + switch (a=getchar()) { + + case 't': + return('\t'); + + case 'n': + return('\n'); + + case 'b': + return('\b'); + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + n = 0; + c = 0; + while (++c<=3 && '0'<=a && a<='7') { + n =<< 3; + n =+ a-'0'; + a = getchar(); + } + mpeek = a; + return(n); + + case 'r': + return('\r'); + + case '\n': + if (!inhdr) + line++; + inhdr = 0; + a = getchar(); + goto loop; + } + } + return(a); +} + +/* + * Read an expression and return a pointer to its tree. + * It's the classical bottom-up, priority-driven scheme. + * The initflg prevents the parse from going past + * "," or ":" because those delimitesrs are special + * in initializer (and some other) expressions. + */ +tree() +{ +#define SEOF 200 +#define SSIZE 20 + int *op, opst[SSIZE], *pp, prst[SSIZE]; + register int andflg, o; + register struct hshtab *cs; + int p, ps, os; + + space = treespace; + op = opst; + pp = prst; + cp = cmst; + *op = SEOF; + *pp = 06; + andflg = 0; + +advanc: + switch (o=symbol()) { + + case NAME: + cs = csym; + if (cs->hclass==0 && cs->htype==0) + if(nextchar()=='(') { + /* set function */ + cs->hclass = EXTERN; + cs->htype = FUNC; + } else if (initflg) + cs->hclass = EXTERN; + else { + /* set label */ + cs->htype = ARRAY; + if (cs->hoffset==0) + cs->hoffset = isn++; + } + *cp++ = copname(cs); + goto tand; + + case FCON: + if (!initflg) + outcode("BBNB1N1N1N1N0B", DATA,LABEL, + cval, WDATA, fcval, PROG); + + case CON: + case SFCON: + *cp++ = block(1,o,(o==CON?INT:DOUBLE),0,cval); + goto tand; + + /* fake a static char array */ + case STRING: + putstr(cval); + *cp++ = block(3, NAME, ARRAY+CHAR,0,STATIC,0,cval); + +tand: + if(cp>=cmst+cmsiz) { + error("Expression overflow"); + exit(1); + } + if (andflg) + goto syntax; + andflg = 1; + goto advanc; + + case INCBEF: + case DECBEF: + if (andflg) + o =+ 2; + goto oponst; + + case COMPL: + case EXCLA: + case SIZEOF: + if (andflg) + goto syntax; + goto oponst; + + case MINUS: + if (!andflg) { + if ((peeksym=symbol())==FCON) { + fcval = - fcval; + goto advanc; + } + if (peeksym==SFCON) { + fcval = - fcval; + cval =^ 0100000; + goto advanc; + } + o = NEG; + } + andflg = 0; + goto oponst; + + case AND: + case TIMES: + if (andflg) + andflg = 0; else + if(o==AND) + o = AMPER; + else + o = STAR; + goto oponst; + + case LPARN: + if (andflg) { + o = symbol(); + if (o==RPARN) + o = MCALL; + else { + peeksym = o; + o = CALL; + andflg = 0; + } + } + goto oponst; + + case RBRACK: + case RPARN: + if (!andflg) + goto syntax; + goto oponst; + + case DOT: + case ARROW: + mosflg++; + break; + + } + /* binaries */ + if (!andflg) + goto syntax; + andflg = 0; + +oponst: + p = (opdope[o]>>9) & 077; + if ((o==COMMA || o==COLON) && initflg) + p = 05; +opon1: + ps = *pp; + if (p>ps || p==ps && (opdope[o]&RASSOC)!=0) { + switch (o) { + + case INCAFT: + case DECAFT: + p = 37; + break; + case LPARN: + case LBRACK: + case CALL: + p = 04; + } + if (op >= &opst[SSIZE-1]) { + error("expression overflow"); + exit(1); + } + *++op = o; + *++pp = p; + goto advanc; + } + --pp; + switch (os = *op--) { + + case SEOF: + peeksym = o; + build(0); /* flush conversions */ + return(*--cp); + + case CALL: + if (o!=RPARN) + goto syntax; + build(os); + goto advanc; + + case MCALL: + *cp++ = block(0,0,0,0); /* 0 arg call */ + os = CALL; + break; + + case INCBEF: + case INCAFT: + case DECBEF: + case DECAFT: + *cp++ = block(1, CON, INT, 0, 1); + break; + + case LPARN: + if (o!=RPARN) + goto syntax; + goto advanc; + + case LBRACK: + if (o!=RBRACK) + goto syntax; + build(LBRACK); + goto advanc; + } + build(os); + goto opon1; + +syntax: + error("Expression syntax"); + errflush(o); + return(0); +} + +/* + * Generate a tree node for a name. + * All the relevant info from the symbol table is + * copied out, including the name if it's an external. + * This is because the symbol table is gone in the next + * pass, so a ptr isn't sufficient. + */ +copname(acs) +struct hshtab *acs; +{ + register struct hshtab *cs; + register struct tname *tp; + register char *cp1; + int i; + char *cp2; + + cs = acs; + tp = gblock(sizeof(*tp)/NCPW); + tp->op = NAME; + tp->type = cs->htype; + tp->dimp = cs->hdimp; + if ((tp->class = cs->hclass)==0) + tp->class = STATIC; + tp->offset = 0; + tp->nloc = cs->hoffset; + if (cs->hclass==EXTERN) { + gblock((ncps-NCPW)/NCPW); + cp1 = tp->nname; + cp2 = cs->name; + i = ncps; + do { + *cp1++ = *cp2++; + } while (--i); + } + if (cs->hflag&FFIELD) + tp->class = FMOS; + return(tp); +} diff --git a/source/c/c01.c b/source/c/c01.c new file mode 100644 index 0000000..2b33ad3 --- /dev/null +++ b/source/c/c01.c @@ -0,0 +1,521 @@ +# +/* + * C compiler + * + * + */ + +#include "c0h.c" + +/* + * Called from tree, this routine takes the top 1, 2, or 3 + * operands on the expression stack, makes a new node with + * the operator op, and puts it on the stack. + * Essentially all the work is in inserting + * appropriate conversions. + */ +build(op) { + register int t1; + int t2, t3, t; + struct tnode *p3, *disarray(); + register struct tnode *p1, *p2; + int d, dope, leftc, cvn, pcvn; + + /* + * a[i] => *(a+i) + */ + if (op==LBRACK) { + build(PLUS); + op = STAR; + } + dope = opdope[op]; + if ((dope&BINARY)!=0) { + p2 = chkfun(disarray(*--cp)); + t2 = p2->type; + } + p1 = *--cp; + /* + * sizeof gets turned into a number here. + * Bug: sizeof(structure-member-array) is 2 because + * the array has been turned into a ptr already. + */ + if (op==SIZEOF) { + t1 = length(p1); + p1->op = CON; + p1->type = INT; + p1->dimp = 0; + p1->value = t1; + *cp++ = p1; + return; + } + if (op!=AMPER) { + p1 = disarray(p1); + if (op!=CALL) + p1 = chkfun(p1); + } + t1 = p1->type; + pcvn = 0; + t = INT; + switch (op) { + + /* end of expression */ + case 0: + *cp++ = p1; + return; + + /* no-conversion operators */ + case QUEST: + if (p2->op!=COLON) + error("Illegal conditional"); + t = t2; + + case COMMA: + case LOGAND: + case LOGOR: + *cp++ = block(2, op, t, 0, p1, p2); + return; + + case CALL: + if ((t1&XTYPE) != FUNC) + error("Call of non-function"); + *cp++ = block(2,CALL,decref(t1),p1->dimp,p1,p2); + return; + + case STAR: + if (p1->op==AMPER ) { + *cp++ = p1->tr1; + return; + } + if ((t1&XTYPE) == FUNC) + error("Illegal indirection"); + *cp++ = block(1,STAR,decref(t1),p1->dimp,p1); + return; + + case AMPER: + if (p1->op==STAR) { + p1->tr1->dimp = p1->dimp; + p1->tr1->type = incref(t1); + *cp++ = p1->tr1; + return; + } + if (p1->op==NAME) { + *cp++ = block(1,op,incref(t1),p1->dimp,p1); + return; + } + error("Illegal lvalue"); + break; + + /* + * a->b goes to (*a).b + */ + case ARROW: + *cp++ = p1; + chkw(p1, -1); + p1->type = PTR+STRUCT; + build(STAR); + p1 = *--cp; + + /* + * In a.b, a fairly complicated process has to + * be used to make the left operand look + * as if it had the type of the second. + * Also, the offset in the structure has to be + * given a special type to prevent conversion. + */ + case DOT: + if (p2->op!=NAME || (p2->class!=MOS && p2->class!=FMOS)) + error("Illegal structure ref"); + *cp++ = p1; + t = t2; + if ((t&XTYPE) == ARRAY) { + t = decref(t); + p2->ssp++; + } + setype(p1, t, p2->dimp); + build(AMPER); + *cp++ = block(1,CON,NOTYPE,0,p2->nloc); + build(PLUS); + if ((t2&XTYPE) != ARRAY) + build(STAR); + if (p2->class == FMOS) + *cp++ = block(2, FSEL, t, 0, *--cp, p2->dimp); + return; + } + if ((dope&LVALUE)!=0) + chklval(p1); + if ((dope&LWORD)!=0) + chkw(p1, LONG); + if ((dope&RWORD)!=0) + chkw(p2, LONG); + if ((dope&BINARY)==0) { + if (op==ITOF) + t1 = DOUBLE; + else if (op==FTOI) + t1 = INT; + if (!fold(op, p1, 0)) + *cp++ = block(1,op,t1,p1->dimp,p1); + return; + } + cvn = 0; + if (t1==STRUCT || t2==STRUCT) { + error("Unimplemented structure operation"); + t1 = t2 = INT; + } + if (t2==NOTYPE) { + t = t1; + p2->type = INT; /* no int cv for struct */ + t2 = INT; + } else + cvn = cvtab[lintyp(t1)][lintyp(t2)]; + leftc = (cvn>>4)&017; + cvn =& 017; + t = leftc? t2:t1; + if (dope&ASSGOP) { + t = t1; + if (op==ASSIGN && (cvn==ITP||cvn==PTI)) + cvn = leftc = 0; + if (leftc) + cvn = leftc; + leftc = 0; + } else if (op==COLON && t1>=PTR && t1==t2) + cvn = 0; + else if (dope&RELAT) { + if (op>=LESSEQ && (t1>=PTR || t2>=PTR)) + op =+ LESSEQP-LESSEQ; + if (cvn==PTI) + cvn = 0; + } + if (cvn==PTI) { + cvn = 0; + if (op==MINUS) { + t = INT; + pcvn++; + } else { + if (t1!=t2 || t1!=(PTR+CHAR)) + cvn = XX; + } + } + if (cvn) { + t1 = plength(p1); + t2 = plength(p2); + if (cvn==XX || (cvn==PTI&&t1!=t2)) + error("Illegal conversion"); + else if (leftc) + p1 = convert(p1, t, cvn, t2); + else + p2 = convert(p2, t, cvn, t1); + } + if (dope&RELAT) + t = INT; + if (fold(op, p1, p2)==0) + *cp++ = block(2,op,t,(p1->dimp==0? p2:p1)->dimp,p1,p2); + if (pcvn && t1!=(PTR+CHAR)) { + p1 = *--cp; + *cp++ = convert(p1, 0, PTI, plength(p1->tr1)); + } +} + +/* + * Generate the appropirate conversion operator. + * For pointer <=> integer this is a multiplication + * or division, otherwise a special operator. + */ +convert(p, t, cvn, len) +struct tnode *p; +{ + register int n; + + switch(cvn) { + + case PTI: + case ITP: + if (len==1) + return(p); + return(block(2, (cvn==PTI?DIVIDE:TIMES), t, 0, p, + block(1, CON, 0, 0, len))); + + case ITF: + n = ITOF; + break; + case FTI: + n = FTOI; + break; + case ITL: + n = ITOL; + break; + case LTI: + n = LTOI; + break; + case FTL: + n = FTOL; + break; + case LTF: + n = LTOF; + break; + } + return(block(1, n, t, 0, p)); +} + +/* + * Traverse an expression tree, adjust things + * so the types of things in it are consistent + * with the view that its top node has + * type at. + * Used with structure references. + */ +setype(ap, at, adimptr) +struct tnode *ap; +{ + register struct tnode *p; + register t, dimptr; + + p = ap; + t = at; + dimptr = adimptr; + p->type = t; + if (dimptr != -1) + p->dimp = dimptr; + switch(p->op) { + + case AMPER: + setype(p->tr1, decref(t), dimptr); + return; + + case STAR: + setype(p->tr1, incref(t), dimptr); + return; + + case PLUS: + case MINUS: + setype(p->tr1, t, dimptr); + } +} + +/* + * A mention of a function name is turned into + * a pointer to that function. + */ +chkfun(ap) +struct tnode *ap; +{ + register struct tnode *p; + register int t; + + p = ap; + if (((t = p->type)&XTYPE)==FUNC) + return(block(1,AMPER,incref(t),p->dimp,p)); + return(p); +} + +/* + * A mention of an array is turned into + * a pointer to the base of the array. + */ +struct tnode *disarray(ap) +struct tnode *ap; +{ + register int t; + register struct tnode *p; + + p = ap; + /* check array & not MOS */ + if (((t = p->type)&XTYPE)!=ARRAY || p->op==NAME&&p->class==MOS) + return(p); + p->ssp++; + *cp++ = p; + setype(p, decref(t), -1); + build(AMPER); + return(*--cp); +} + +/* + * make sure that p is a ptr to a node + * with type int or char or 'okt.' + * okt might be nonexistent or 'long' + * (e.g. for <<). + */ +chkw(p, okt) +struct tnode *p; +{ + register int t; + + if ((t=p->type)>CHAR && t= &osspace[OSSIZ]) { + error("Expression overflow"); + exit(1); + } + return(p); +} + +/* + * Check that a tree can be used as an lvalue. + */ +chklval(ap) +struct tnode *ap; +{ + register struct tnode *p; + + p = ap; + if (p->op!=NAME && p->op!=STAR) + error("Lvalue required"); +} + +/* + * reduce some forms of `constant op constant' + * to a constant. More of this is done in the next pass + * but this is used to allow constant expressions + * to be used in switches and array bounds. + */ +fold(op, ap1, ap2) +struct tnode *ap1, *ap2; +{ + register struct tnode *p1; + register int v1, v2; + + p1 = ap1; + if (p1->op!=CON || (ap2!=0 && ap2->op!=CON)) + return(0); + v1 = p1->value; + v2 = ap2->value; + switch (op) { + + case PLUS: + v1 =+ v2; + break; + + case MINUS: + v1 =- v2; + break; + + case TIMES: + v1 =* v2; + break; + + case DIVIDE: + v1 =/ v2; + break; + + case MOD: + v1 =% v2; + break; + + case AND: + v1 =& v2; + break; + + case OR: + v1 =| v2; + break; + + case EXOR: + v1 =^ v2; + break; + + case NEG: + v1 = - v1; + break; + + case COMPL: + v1 = ~ v1; + break; + + case LSHIFT: + v1 =<< v2; + break; + + case RSHIFT: + v1 =>> v2; + break; + + default: + return(0); + } + p1->value = v1; + *cp++ = p1; + return(1); +} + +/* + * Compile an expression expected to have constant value, + * for example an array bound or a case value. + */ +conexp() +{ + register struct tnode *t; + + initflg++; + if (t = tree()) + if (t->op != CON) + error("Constant required"); + initflg--; + return(t->value); +} diff --git a/source/c/c02.c b/source/c/c02.c new file mode 100644 index 0000000..1a37702 --- /dev/null +++ b/source/c/c02.c @@ -0,0 +1,673 @@ +# +/* C compiler + * + * + */ + +#include "c0h.c" + +/* + * Process a single external definition + */ +extdef() +{ + register o, elsize; + int type, sclass; + register struct hshtab *ds; + + if(((o=symbol())==EOF) || o==SEMI) + return; + peeksym = o; + type = INT; + sclass = EXTERN; + xdflg = FNDEL; + if ((elsize = getkeywords(&sclass, &type)) == -1 && peeksym!=NAME) + goto syntax; + if (type==STRUCT) + blkhed(); + do { + defsym = 0; + decl1(EXTERN, type, 0, elsize); + if ((ds=defsym)==0) + return; + funcsym = ds; + ds->hflag =| FNDEL; + outcode("BS", SYMDEF, ds->name); + xdflg = 0; + if ((ds->type&XTYPE)==FUNC) { + if ((peeksym=symbol())==LBRACE || peeksym==KEYW) { + funcblk.type = decref(ds->type); + cfunc(ds->name); + return; + } + } else + cinit(ds); + } while ((o=symbol())==COMMA); + if (o==SEMI) + return; +syntax: + if (o==RBRACE) { + error("Too many }'s"); + peeksym = 0; + return; + } + error("External definition syntax"); + errflush(o); + statement(0); +} + +/* + * Process a function definition. + */ +cfunc(cs) +char *cs; +{ + register savdimp; + + savdimp = dimp; + outcode("BBS", PROG, RLABEL, cs); + declist(ARG); + regvar = 5; + retlab = isn++; + if ((peeksym = symbol()) != LBRACE) + error("Compound statement required"); + statement(1); + outcode("BNB", LABEL, retlab, RETRN); + dimp = savdimp; +} + +/* + * Process the initializers for an external definition. + */ +cinit(ds) +struct hshtab *ds; +{ + register basetype, nel, ninit; + int o, width, realwidth; + + nel = 1; + basetype = ds->type; + /* + * If it's an array, find the number of elements. + * "basetype" is the type of thing it's an array of. + */ + while ((basetype&XTYPE)==ARRAY) { + if ((nel = dimtab[ds->ssp&0377])==0) + nel = 1; + basetype = decref(basetype); + } + realwidth = width = length(ds) / nel; + /* + * Pretend a structure is kind of an array of integers. + * This is a kludge. + */ + if (basetype==STRUCT) { + nel =* realwidth/2; + width = 2; + } + if ((peeksym=symbol())==COMMA || peeksym==SEMI) { + outcode("BSN",CSPACE,ds->name,(nel*width+ALIGN)&~ALIGN); + return; + } + ninit = 0; + outcode("BBS", DATA, NLABEL, ds->name); + if ((o=symbol())==LBRACE) { + do + ninit = cinit1(ds, basetype, width, ninit, nel); + while ((o=symbol())==COMMA); + if (o!=RBRACE) + peeksym = o; + } else { + peeksym = o; + ninit = cinit1(ds, basetype, width, 0, nel); + } + /* + * Above we pretended that a structure was a bunch of integers. + * Readjust in accordance with reality. + * First round up partial initializations. + */ + if (basetype==STRUCT) { + if (o = 2*ninit % realwidth) + outcode("BN", SSPACE, realwidth-o); + ninit = (2*ninit+realwidth-2) / realwidth; + nel =/ realwidth/2; + } + /* + * If there are too few initializers, allocate + * more storage. + * If there are too many initializers, extend + * the declared size for benefit of "sizeof" + */ + if (ninitnel) { + if ((ds->type&XTYPE)==ARRAY) + dimtab[ds->ssp&0377] = ninit; + nel = ninit; + } + /* + * If it's not an array, only one initializer is allowed. + */ + if (ninit>1 && (ds->type&XTYPE)!=ARRAY) + error("Too many initializers"); + if (((nel&width)&ALIGN)) + outcode("B", EVEN); +} + +/* + * Process a single expression in a sequence of initializers + * for an external. Mainly, it's for checking + * type compatibility. + */ +cinit1(ds, type, awidth, aninit, nel) +struct hshtab *ds; +{ + float sf; + register struct tnode *s; + register width, ninit; + + width = awidth; + ninit = aninit; + if ((peeksym=symbol())==STRING && type==CHAR) { + peeksym = -1; + if (ninit) + bxdec(); + putstr(0); + if (nel>nchstr) { + strflg++; + outcode("BN", SSPACE, nel-nchstr); + strflg = 0; + nchstr = nel; + } + return(nchstr); + } + if (peeksym==RBRACE) + return(ninit); + initflg++; + s = tree(); + initflg = 0; + switch(width) { + + case 1: + if (s->op != CON) + goto bad; + outcode("B1N0", BDATA, s->value); + break; + + case 2: + if (s->op==CON) { + outcode("B1N0", WDATA, s->value); + break; + } + if (s->op==FCON || s->op==SFCON) { + if (type==STRUCT) { + ninit =+ 3; + goto prflt; + } + goto bad; + } + rcexpr(block(1,INIT,0,0,s)); + break; + + case 4: + sf = fcval; + outcode("B1N1N0", WDATA, sf); + goto flt; + + case 8: + prflt: + outcode("B1N1N1N1N0", WDATA, fcval); + flt: + if (s->op==FCON || s->op==SFCON) + break; + + default: + bad: + bxdec(); + + } + return(++ninit); +} + +bxdec() +{ + error("Inconsistent external initialization"); +} + +/* + * Process one statement in a function. + */ +statement(d) +{ + register o, o1, o2; + int o3, o4; + struct tnode *np; + +stmt: + switch(o=symbol()) { + + case EOF: + error("Unexpected EOF"); + case SEMI: + return; + + case LBRACE: + if (d) { + if (proflg) + outcode("BN", PROFIL, isn++); + outcode("BN", SAVE, blkhed()); + } + while (!eof) { + if ((o=symbol())==RBRACE) + return; + peeksym = o; + statement(0); + } + error("Missing '}'"); + return; + + case KEYW: + switch(cval) { + + case GOTO: + if (o1 = simplegoto()) + branch(o1); + else + dogoto(); + goto semi; + + case RETURN: + doret(); + goto semi; + + case IF: + np = pexpr(); + o2 = 0; + if ((o1=symbol())==KEYW) switch (cval) { + case GOTO: + if (o2=simplegoto()) + goto simpif; + cbranch(np, o2=isn++, 0); + dogoto(); + label(o2); + goto hardif; + + case RETURN: + if (nextchar()==';') { + o2 = retlab; + goto simpif; + } + cbranch(np, o1=isn++, 0); + doret(); + label(o1); + o2++; + goto hardif; + + case BREAK: + o2 = brklab; + goto simpif; + + case CONTIN: + o2 = contlab; + simpif: + chconbrk(o2); + cbranch(np, o2, 1); + hardif: + if ((o=symbol())!=SEMI) + goto syntax; + if ((o1=symbol())==KEYW && cval==ELSE) + goto stmt; + peeksym = o1; + return; + } + peeksym = o1; + cbranch(np, o1=isn++, 0); + statement(0); + if ((o=symbol())==KEYW && cval==ELSE) { + o2 = isn++; + branch(o2); + label(o1); + statement(0); + label(o2); + return; + } + peeksym = o; + label(o1); + return; + + case WHILE: + o1 = contlab; + o2 = brklab; + label(contlab = isn++); + cbranch(pexpr(), brklab=isn++, 0); + statement(0); + branch(contlab); + label(brklab); + contlab = o1; + brklab = o2; + return; + + case BREAK: + chconbrk(brklab); + branch(brklab); + goto semi; + + case CONTIN: + chconbrk(contlab); + branch(contlab); + goto semi; + + case DO: + o1 = contlab; + o2 = brklab; + contlab = isn++; + brklab = isn++; + label(o3 = isn++); + statement(0); + label(contlab); + contlab = o1; + if ((o=symbol())==KEYW && cval==WHILE) { + cbranch(tree(), o3, 1); + label(brklab); + brklab = o2; + goto semi; + } + goto syntax; + + case CASE: + o1 = conexp(); + if ((o=symbol())!=COLON) + goto syntax; + if (swp==0) { + error("Case not in switch"); + goto stmt; + } + if(swp>=swtab+swsiz) { + error("Switch table overflow"); + } else { + swp->swlab = isn; + (swp++)->swval = o1; + label(isn++); + } + goto stmt; + + case SWITCH: + o1 = brklab; + brklab = isn++; + np = pexpr(); + chkw(np, -1); + rcexpr(block(1,RFORCE,0,0,np)); + pswitch(); + brklab = o1; + return; + + case DEFAULT: + if (swp==0) + error("Default not in switch"); + if ((o=symbol())!=COLON) + goto syntax; + label(deflab = isn++); + goto stmt; + + case FOR: + o1 = contlab; + o2 = brklab; + contlab = isn++; + brklab = isn++; + if (o=forstmt()) + goto syntax; + label(brklab); + contlab = o1; + brklab = o2; + return; + } + + error("Unknown keyword"); + goto syntax; + + case NAME: + if (nextchar()==':') { + peekc = 0; + o1 = csym; + if (o1->hclass>0) { + error("Redefinition"); + goto stmt; + } + o1->hclass = STATIC; + o1->htype = ARRAY; + if (o1->hoffset==0) + o1->hoffset = isn++; + label(o1->hoffset); + goto stmt; + } + } + peeksym = o; + rcexpr(tree()); + +semi: + if ((o=symbol())==SEMI) + return; +syntax: + error("Statement syntax"); + errflush(o); +} + +/* + * Process a for statement. + */ +forstmt() +{ + register int l, o, sline; + int sline1, *ss; + struct tnode *st; + + if ((o=symbol()) != LPARN) + return(o); + if ((o=symbol()) != SEMI) { /* init part */ + peeksym = o; + rcexpr(tree()); + if ((o=symbol()) != SEMI) + return(o); + } + label(contlab); + if ((o=symbol()) != SEMI) { /* test part */ + peeksym = o; + rcexpr(block(1,CBRANCH,tree(),brklab,0)); + if ((o=symbol()) != SEMI) + return(o); + } + if ((peeksym=symbol()) == RPARN) { /* incr part */ + peeksym = -1; + statement(0); + branch(contlab); + return(0); + } + l = contlab; + contlab = isn++; + st = tree(); + sline = line; + if ((o=symbol()) != RPARN) + return(o); + ss = treespace; + treespace = space; + statement(0); + sline1 = line; + line = sline; + label(contlab); + rcexpr(st); + line = sline1; + treespace = ss; + branch(l); + return(0); +} + +/* + * A parenthesized expression, + * as after "if". + */ +pexpr() +{ + register o, t; + + if ((o=symbol())!=LPARN) + goto syntax; + t = tree(); + if ((o=symbol())!=RPARN) + goto syntax; + return(t); +syntax: + error("Statement syntax"); + errflush(o); + return(0); +} + +/* + * The switch stateent, which involves collecting the + * constants and labels for the cases. + */ +pswitch() +{ + register struct swtab *cswp, *sswp; + int dl, swlab; + + cswp = sswp = swp; + if (swp==0) + cswp = swp = swtab; + branch(swlab=isn++); + dl = deflab; + deflab = 0; + statement(0); + branch(brklab); + label(swlab); + if (deflab==0) + deflab = brklab; + outcode("BNN", SWIT, deflab, line); + for (; cswp < swp; cswp++) + outcode("NN", cswp->swlab, cswp->swval); + outcode("0"); + label(brklab); + deflab = dl; + swp = sswp; +} + +/* + * blkhed is called at the start of each function. + * It reads the declarations at the start; + * then assigns storage locations for the + * parameters (which have been linked into a list, + * in order of appearance). + * This list is necessary because in + * f(a, b) float b; int a; ... + * the names are seen before the types. + * Also, the routine adjusts structures involved + * in some kind of forward-referencing. + */ +blkhed() +{ + register pl; + register struct hshtab *cs; + + autolen = 6; + declist(0); + pl = 4; + while(paraml) { + parame->hoffset = 0; + cs = paraml; + paraml = paraml->hoffset; + if (cs->htype==FLOAT) + cs->htype = DOUBLE; + cs->hoffset = pl; + cs->hclass = AUTO; + if ((cs->htype&XTYPE) == ARRAY) { + cs->htype =- (ARRAY-PTR); /* set ptr */ + cs->ssp++; /* pop dims */ + } + pl =+ rlength(cs); + } + for (cs=hshtab; csname[0] == '\0') + continue; + /* check tagged structure */ + if (cs->hclass>KEYWC && (cs->htype&TYPE)==RSTRUCT) { + cs->lenp = dimtab[cs->lenp&0377]->lenp; + cs->htype = cs->htype&~TYPE | STRUCT; + } + if (cs->hclass == STRTAG && dimtab[cs->lenp&0377]==0) + error("Undefined structure: %.8s", cs->name); + if (cs->hclass == ARG) + error("Not an argument: %.8s", cs->name); + if (stflg) + prste(cs); + } + space = treespace; + outcode("BN", SETREG, regvar); + return(autolen); +} + +/* + * After a function definition, delete local + * symbols. + * Also complain about undefineds. + */ +blkend() { + register struct hshtab *cs; + + for (cs=hshtab; csname[0]) { + if (cs->hclass==0 && (cs->hflag&FNUND)==0) { + error("%.8s undefined", cs->name); + cs->hflag =| FNUND; + } + if((cs->hflag&FNDEL)==0) { + cs->name[0] = '\0'; + hshused--; + cs->hflag =& ~(FNUND|FFIELD); + } + } + } +} + +/* + * write out special definitions of local symbols for + * benefit of the debugger. None of these are used + * by the assembler except to save them. + */ +prste(acs) +{ + register struct hshtab *cs; + register nkind; + + cs = acs; + switch (cs->hclass) { + case REG: + nkind = RNAME; + break; + + case AUTO: + nkind = ANAME; + break; + + case STATIC: + nkind = SNAME; + break; + + default: + return; + + } + outcode("BSN", nkind, cs->name, cs->hoffset); +} + +/* + * In case of error, skip to the next + * statement delimiter. + */ +errflush(ao) +{ + register o; + + o = ao; + while(o>RBRACE) /* ; { } */ + o = symbol(); + peeksym = o; +} diff --git a/source/c/c03.c b/source/c/c03.c new file mode 100644 index 0000000..3c72ae0 --- /dev/null +++ b/source/c/c03.c @@ -0,0 +1,412 @@ +# +/* + * C compiler, phase 1 + * + * + * Handles processing of declarations, + * except for top-level processing of + * externals. + */ + +#include "c0h.c" + +/* + * Process a sequence of declaration statements + */ +declist(sclass) +{ + register sc, elsize, offset; + int type; + + offset = 0; + sc = sclass; + while ((elsize = getkeywords(&sclass, &type)) != -1) { + offset = declare(sclass, type, offset, elsize); + sclass = sc; + } + return(offset+align(INT, offset, 0)); +} + +/* + * Read the keywords introducing a declaration statement + */ +getkeywords(scptr, tptr) +int *scptr, *tptr; +{ + register skw, tkw, longf; + int o, elsize, isadecl, ismos; + + isadecl = 0; + longf = 0; + tkw = -1; + skw = *scptr; + elsize = 0; + ismos = skw==MOS; + for (;;) { + mosflg = ismos; + switch ((o=symbol())==KEYW? cval: -1) { + + case AUTO: + case STATIC: + case EXTERN: + case REG: + if (skw && skw!=cval) + error("Conflict in storage class"); + skw = cval; + break; + + case LONG: + longf++; + break; + + case STRUCT: + o = STRUCT; + elsize = strdec(&o, ismos); + cval = o; + case INT: + case CHAR: + case FLOAT: + case DOUBLE: + if (tkw>=0) + error("Type clash"); + tkw = cval; + break; + + default: + peeksym = o; + if (isadecl==0) + return(-1); + if (tkw<0) + tkw = INT; + if (skw==0) + skw = AUTO; + if (longf) { + if (tkw==FLOAT) + tkw = DOUBLE; + else if (tkw==INT) + tkw = LONG; + else + error("Misplaced 'long'"); + } + *scptr = skw; + *tptr = tkw; + return(elsize); + } + isadecl++; + } +} + +/* + * Process a structure declaration; a subroutine + * of getkeywords. + */ +strdec(tkwp, mosf) +int *tkwp; +{ + register elsize, o; + register struct hshtab *ssym; + int savebits; + struct hshtab *ds; + + mosflg = 1; + ssym = 0; + if ((o=symbol())==NAME) { + ssym = csym; + if (ssym->hclass==0) { + ssym->hclass = STRTAG; + ssym->lenp = dimp; + chkdim(); + dimtab[dimp++] = 0; + } + if (ssym->hclass != STRTAG) + redec(); + mosflg = mosf; + o = symbol(); + } + mosflg = 0; + if (o != LBRACE) { + if (ssym==0) { + syntax: + decsyn(o); + return(0); + } + if (ssym->hclass!=STRTAG) + error("Bad structure name"); + if ((elsize = dimtab[ssym->lenp&0377])==0) { + *tkwp = RSTRUCT; + elsize = ssym; + } + peeksym = o; + } else { + ds = defsym; + mosflg = 0; + savebits = bitoffs; + bitoffs = 0; + elsize = declist(MOS); + bitoffs = savebits; + defsym = ds; + if ((o = symbol()) != RBRACE) + goto syntax; + if (ssym) { + if (dimtab[ssym->lenp&0377]) + error("%.8s redeclared", ssym->name); + dimtab[ssym->lenp&0377] = elsize; + } + } + return(elsize); +} + +/* + * Check that the dimension table has not overflowed + */ +chkdim() +{ + if (dimp >= dimsiz) { + error("Dimension/struct table overflow"); + exit(1); + } +} + +/* + * Process a comma-separated list of declarators + */ +declare(askw, tkw, offset, elsize) +{ + register int o; + register int skw; + + skw = askw; + do { + offset =+ decl1(skw, tkw, offset, elsize); + } while ((o=symbol()) == COMMA); + if (o==SEMI || o==RPARN && skw==ARG1) + return(offset); + decsyn(o); +} + +/* + * Process a single declarator + */ +decl1(askw, tkw, offset, elsize) +{ + int t1, chkoff, a; + register int type, skw; + register struct hshtab *dsym; + + skw = askw; + chkoff = 0; + mosflg = skw==MOS; + if ((peeksym=symbol())==SEMI || peeksym==RPARN) + return(0); + /* + * Filler field + */ + if (peeksym==COLON && skw==MOS) { + peeksym = -1; + t1 = conexp(); + elsize = align(tkw, offset, t1); + bitoffs =+ t1; + return(elsize); + } + if ((t1=getype()) < 0) + goto syntax; + type = 0; + do + type = type<>TYLEN) & XTYPE)!=0); + type =| tkw; + dsym = defsym; + if (!(dsym->hclass==0 + || (skw==ARG && dsym->hclass==ARG1) + || (skw==EXTERN && dsym->hclass==EXTERN && dsym->htype==type))) + if (skw==MOS && dsym->hclass==MOS && dsym->htype==type) + chkoff = 1; + else { + redec(); + goto syntax; + } + dsym->htype = type; + if (skw) + dsym->hclass = skw; + if (skw==ARG1) { + if (paraml==0) + paraml = dsym; + else + parame->hoffset = dsym; + parame = dsym; + } + if (elsize && ((type&TYPE)==RSTRUCT || (type&TYPE)==STRUCT)) { + dsym->lenp = dimp; + chkdim(); + dimtab[dimp++] = elsize; + } + elsize = 0; + if (skw==MOS) { + elsize = length(dsym); + t1 = 0; + if ((peeksym = symbol())==COLON) { + elsize = 0; + peeksym = -1; + t1 = conexp(); + dsym->hflag =| FFIELD; + } + a = align(type, offset, t1); + elsize =+ a; + offset =+ a; + if (t1) { + if (chkoff && (dsym->bitoffs!=bitoffs + || dsym->flen!=t1)) + redec(); + dsym->bitoffs = bitoffs; + dsym->flen = t1; + bitoffs =+ t1; + } + if (chkoff && dsym->hoffset != offset) + redec(); + dsym->hoffset = offset; + } + if ((dsym->htype&XTYPE)==FUNC) { + if (dsym->hclass!=EXTERN && dsym->hclass!=AUTO) + error("Bad function"); + dsym->hclass = EXTERN; + } + if (dsym->hclass==AUTO) { + autolen =+ rlength(dsym); + dsym->hoffset = -autolen; + } else if (dsym->hclass==STATIC) { + dsym->hoffset = isn; + outcode("BBNBNB", BSS, LABEL, isn++, + SSPACE, rlength(dsym), PROG); + } else if (dsym->hclass==REG) { + if ((type&TYPE)>CHAR && (type&XTYPE)==0 + || (type&XTYPE)>PTR || regvar<3) + error("Bad register %o", type); + dsym->hoffset = --regvar; + } +syntax: + return(elsize); +} + +/* + * Read a declarator and get the implied type + */ +getype() +{ + register int o, type; + register struct hshtab *ds; + + switch(o=symbol()) { + + case TIMES: + return(getype()<ssp = dimp; + getf: + switch(o=symbol()) { + + case LPARN: + if (xdflg) { + xdflg = 0; + ds = defsym; + declare(ARG1, 0, 0, 0); + defsym = ds; + xdflg++; + } else + if ((o=symbol()) != RPARN) + goto syntax; + type = type<ssp&0377; ooffset) + bitoffs = 0; + } + if (flen) { + if (type==INT) { + if (flen > NBPW) + error(ftl); + if (flen+bitoffs > NBPW) { + bitoffs = 0; + a =+ NCPW; + } + } else if (type==CHAR) { + if (flen > NBPC) + error(ftl); + if (flen+bitoffs > NCPW) { + bitoffs = 0; + a =+ 1; + } + } else + error("Bad type for field"); + } + return(a-offset); +} + +/* + * Complain about syntax error in declaration + */ +decsyn(o) +{ + error("Declaration syntax"); + errflush(o); +} + +/* + * Complain about a redeclaration + */ +redec() +{ + error("%.8s redeclared", defsym->name); +} diff --git a/source/c/c04.c b/source/c/c04.c new file mode 100644 index 0000000..064aed4 --- /dev/null +++ b/source/c/c04.c @@ -0,0 +1,343 @@ +# +/* + * C compiler + * + * + */ + +#include "c0h.c" + +/* + * Reduce the degree-of-reference by one. + * e.g. turn "ptr-to-int" into "int". + */ +decref(at) +{ + register t; + + t = at; + if ((t & ~TYPE) == 0) { + error("Illegal indirection"); + return(t); + } + return((t>>TYLEN) & ~TYPE | t&TYPE); +} + +/* + * Increase the degree of reference by + * one; e.g. turn "int" to "ptr-to-int". + */ +incref(t) +{ + return(((t&~TYPE)<op) { + + case 0: + outcode("B", NULL); + return; + + case NAME: + outcode("BNN", NAME, tree->class, tree->type); + if (tree->class==EXTERN) + outcode("S", tree->nname); + else + outcode("N", tree->nloc); + return; + + case CON: + case FCON: + case SFCON: + outcode("BNN", tree->op, tree->type, tree->value); + return; + + case FSEL: + treeout(tree->tr1); + outcode("BNN", tree->op, tree->type, tree->tr2); + return; + + case CBRANCH: + treeout(tree->btree); + outcode("BNN", tree->op, tree->lbl, tree->cond); + return; + + default: + treeout(tree->tr1); + if (opdope[tree->op]&BINARY) + treeout(tree->tr2); + outcode("BN", tree->op, tree->type); + return; + } +} + +/* + * Generate a branch + */ +branch(lab) { + outcode("BN", BRANCH, lab); +} + +/* + * Generate a label + */ +label(l) { + outcode("BN", LABEL, l); +} + +/* + * ap is a tree node whose type + * is some kind of pointer; return the size of the object + * to which the pointer points. + */ +plength(ap) +struct tname *ap; +{ + register t, l; + register struct tname *p; + + p = ap; + if (p==0 || ((t=p->type)&~TYPE) == 0) /* not a reference */ + return(1); + p->type = decref(t); + l = length(p); + p->type = t; + return(l); +} + +/* + * return the number of bytes in the object + * whose tree node is acs. + */ +length(acs) +struct tnode *acs; +{ + register t, n; + register struct tnode *cs; + + cs = acs; + t = cs->type; + n = 1; + while ((t&XTYPE) == ARRAY) { + t = decref(t); + n = dimtab[cs->ssp&0377]; + } + if ((t&~TYPE)==FUNC) + return(0); + if (t>=PTR) + return(2*n); + switch(t&TYPE) { + + case INT: + return(2*n); + + case CHAR: + return(n); + + case FLOAT: + case LONG: + return(4*n); + + case DOUBLE: + return(8*n); + + case STRUCT: + return(n * dimtab[cs->lenp&0377]); + + case RSTRUCT: + error("Bad structure"); + return(0); + } + error("Compiler error (length)"); +} + +/* + * The number of bytes in an object, rounded up to a word. + */ +rlength(cs) +struct tnode *cs; +{ + return((length(cs)+ALIGN) & ~ALIGN); +} + +/* + * After an "if (...) goto", look to see if the transfer + * is to a simple label. + */ +simplegoto() +{ + register struct hshtab *csp; + + if ((peeksym=symbol())==NAME && nextchar()==';') { + csp = csym; + if (csp->hclass==0 && csp->htype==0) { + csp->htype = ARRAY; + if (csp->hoffset==0) + csp->hoffset = isn++; + } + if ((csp->hclass==0||csp->hclass==STATIC) + && csp->htype==ARRAY) { + peeksym = -1; + return(csp->hoffset); + } + } + return(0); +} + +/* + * Return the next non-white-space character + */ +nextchar() +{ + while (spnextchar()==' ') + peekc = 0; + return(peekc); +} + +/* + * Return the next character, translating all white space + * to blank and handling line-ends. + */ +spnextchar() +{ + register c; + + if ((c = peekc)==0) + c = getchar(); + if (c=='\t') + c = ' '; + else if (c=='\n') { + c = ' '; + if (inhdr==0) + line++; + inhdr = 0; + } else if (c=='\001') { /* SOH, insert marker */ + inhdr++; + c = ' '; + } + peekc = c; + return(c); +} + +/* + * is a break or continue legal? + */ +chconbrk(l) +{ + if (l==0) + error("Break/continue error"); +} + +/* + * The goto statement. + */ +dogoto() +{ + register struct tnode *np; + + *cp++ = tree(); + build(STAR); + chkw(np = *--cp, -1); + rcexpr(block(1,JUMP,0,0,np)); +} + +/* + * The return statement, which has to convert + * the returned object to the function's type. + */ +doret() +{ + register struct tnode *t; + + if (nextchar() != ';') { + t = tree(); + *cp++ = &funcblk; + *cp++ = t; + build(ASSIGN); + cp[-1] = cp[-1]->tr2; + build(RFORCE); + rcexpr(*--cp); + } + branch(retlab); +} + +/* + * write out a character to the usual output + * or to the string file + */ +putchar(c) +{ + write(1, &c, 1); +} + +outcode(s, a) +char *s; +{ + register char *sp; + register *ap, *bufp; + int n; + char *np; + + bufp = obuf; + if (strflg) + bufp = sbuf; + ap = &a; + for (;;) switch(*s++) { + case 'B': + putw(*ap++ | (0376<<8), bufp); + continue; + + case 'N': + putw(*ap++, bufp); + continue; + + case 'S': + np = *ap++; + n = ncps; + while (n-- && *np) { + putc(*np++, bufp); + } + putc(0, bufp); + continue; + + case '1': + putw(1, bufp); + continue; + + case '0': + putw(0, bufp); + continue; + + case '\0': + return; + } + error("Botch in outcode"); +} diff --git a/source/c/c05.c b/source/c/c05.c new file mode 100644 index 0000000..3dbad30 --- /dev/null +++ b/source/c/c05.c @@ -0,0 +1,176 @@ +# +#include "c0h.c" +/* + * info on operators: + * 01-- is binary operator + * 02-- left (or only) operand must be lvalue + * 04-- is relational operator + * 010-- is assignment-type operator + * 020-- non-float req. on left + * 040-- non-float req. on right + * 0100-- is commutative + * 0200-- is right, not left-associative + * 0400-- is leaf of tree + * *0XX000-- XX is priority of operator + */ +int opdope[] { + 000000, /* EOF */ + 000000, /* ; */ + 000000, /* { */ + 000000, /* } */ + 036000, /* [ */ + 002000, /* ] */ + 036000, /* ( */ + 002000, /* ) */ + 014201, /* : */ + 007001, /* , */ + 000000, /* field selection */ + 000000, /* 11 */ + 000000, /* 12 */ + 000000, /* 13 */ + 000000, /* 14 */ + 000000, /* 15 */ + 000000, /* 16 */ + 000000, /* 17 */ + 000000, /* 18 */ + 000000, /* 19 */ + 000400, /* name */ + 000400, /* short constant */ + 000400, /* string */ + 000400, /* float */ + 000400, /* double */ + 000000, /* 25 */ + 000000, /* 26 */ + 000000, /* 27 */ + 000000, /* 28 */ + 000000, /* 29 */ + 034203, /* ++pre */ + 034203, /* --pre */ + 034203, /* ++post */ + 034203, /* --post */ + 034220, /* !un */ + 034202, /* &un */ + 034220, /* *un */ + 034200, /* -un */ + 034220, /* ~un */ + 036001, /* . (structure reference) */ + 030101, /* + */ + 030001, /* - */ + 032101, /* * */ + 032001, /* / */ + 032001, /* % */ + 026061, /* >> */ + 026061, /* << */ + 020161, /* & */ + 017161, /* | */ + 017161, /* ^ */ + 036001, /* -> */ + 000000, /* int -> double */ + 000000, /* double -> int */ + 016001, /* && */ + 015001, /* || */ + 030001, /* &~ */ + 000000, /* 56 */ + 000000, /* 57 */ + 000000, /* 58 */ + 000000, /* 59 */ + 022005, /* == */ + 022005, /* != */ + 024005, /* <= */ + 024005, /* < */ + 024005, /* >= */ + 024005, /* > */ + 024005, /*

p */ + 024005, /* >=p */ + 012213, /* =+ */ + 012213, /* =- */ + 012213, /* =* */ + 012213, /* =/ */ + 012213, /* =% */ + 012253, /* =>> */ + 012253, /* =<< */ + 012253, /* =& */ + 012253, /* =| */ + 012253, /* =^ */ + 012213, /* = */ + 000000, /* 81 */ + 000000, /* 82 */ + 000000, /* 83 */ + 000000, /* 84 */ + 000000, /* 85 */ + 000000, /* 86 */ + 000000, /* 87 */ + 000000, /* 88 */ + 000000, /* 89 */ + 014201, /* ? */ + 034200, /* sizeof */ + 000000, /* 92 */ + 000000, /* 93 */ + 000000, /* 94 */ + 000000, /* 95 */ + 000000, /* 96 */ + 000000, /* 97 */ + 000000, /* 98 */ + 000000, /* 99 */ + 036001, /* call */ + 036001, /* mcall */ + 000000, /* goto */ + 000000, /* jump cond */ + 000000, /* branch cond */ + 000000, /* 105 */ + 000000, /* 106 */ + 000000, /* 107 */ + 000000, /* 108 */ + 000000, /* 109 */ + 000000 /* force r0 */ +}; + +/* + * conversion table: + * FTI: float (or double) to integer + * ITF: integer to float + * ITP: integer to pointer + * ITL: integer to long + * LTI: long to integer + * LTF: long to float + * FTL: float to long + * PTI: pointer to integer + * XX: usually illegal + * When FTI, LTI, FTL are added in they specify + * that it is the left operand that should be converted. + * For + this is done and the conversion is turned back into + * ITF, ITL, LTF. + * For = however the left operand can't be converted + * and the specified conversion is applied to the rhs. + */ +char cvtab[4][4] { +/* int double long ptr */ +/* int */ 0, (FTI<<4)+ITF, (LTI<<4)+ITL, (ITP<<4)+ITP, +/* double */ ITF, 0, LTF, XX, +/* long */ ITL, (FTL<<4)+LTF, 0, XX, +/* ptr */ ITP, XX, XX, PTI +}; + +/* + * character type table + */ +char ctab[] { + EOF, INSERT, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + UNKN, SPACE, NEWLN, UNKN, UNKN, UNKN, UNKN, UNKN, + UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + SPACE, EXCLA, DQUOTE, UNKN, UNKN, MOD, AND, SQUOTE, + LPARN, RPARN, TIMES, PLUS, COMMA, MINUS, PERIOD, DIVIDE, + DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, + DIGIT, DIGIT, COLON, SEMI, LESS, ASSIGN, GREAT, QUEST, + UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LBRACK, UNKN, RBRACK, EXOR, LETTER, + UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LBRACE, OR, RBRACE, COMPL, UNKN +}; diff --git a/source/c/c0h.c b/source/c/c0h.c new file mode 100644 index 0000000..90b67db --- /dev/null +++ b/source/c/c0h.c @@ -0,0 +1,351 @@ +# +/* + + C compiler-- pass 1 header + + +*/ + +/* + parameters +*/ + +#define ncps 8 +#define hshsiz 200 +#define cmsiz 40 +#define swsiz 200 +#define OSSIZ 500 +#define dimsiz 100 +#define NBPW 16 +#define NBPC 8 +#define NCPW 2 +#define STRSIZ 256 + +struct tnode { + int op; + int type; + int dimp; + struct tnode *tr1, *tr2; +}; + +struct { + int op; + int type; + char ssp; /* subscript list */ + char lenp; /* structure length */ +}; + +struct tname { + int op; + int type; + int dimp; + int class; + int offset; + int nloc; +}; + +struct txname { + int op; + int type; + int dimp; + int class; + int offset; + char nname[ncps]; +}; + +struct tconst { + int op; + int type; + int dimp; + int value; +}; + +struct hshtab { + char hclass; + char hflag; + int htype; + int hdimp; + int hoffset; + char name[ncps]; +}; + +struct { + char hclass; + char hflag; + int htype; + char flen; /* Field length */ + char bitoffs; /* Offset of field */ +}; + +struct swtab { + int swlab; + int swval; +}; + +struct bnode { + int bop; + struct tnode *btree; + int lbl; + int cond; +}; + +char cvtab[4][4]; +char savstr[STRSIZ]; +char *strptr; +int opdope[]; +char ctab[]; +char symbuf[ncps+2]; +int hshused; +struct hshtab hshtab[hshsiz]; +int *space; +int *cp; +int cmst[cmsiz]; +int isn; +struct swtab swtab[swsiz]; +struct swtab *swp; +int contlab; +int brklab; +int retlab; +int deflab; +int nauto; +int autolen; +int peeksym; +int peekc; +int eof; +int line; +int osspace[OSSIZ]; +int *treespace; +struct hshtab *defsym; +struct hshtab *funcsym; +int xdflg; +int proflg; +int stflg; +struct hshtab *csym; +int cval; +double fcval; +int nchstr; +int nerror; +struct hshtab *paraml; +struct hshtab *parame; +int strflg; +int mosflg; +int initflg; +int inhdr; +int dimtab[dimsiz]; +char obuf[518]; +char sbuf[518]; +int dimp; +int regvar; +int bitoffs; +struct tname funcblk; + +/* + operators +*/ +#define EOF 0 +#define SEMI 1 +#define LBRACE 2 +#define RBRACE 3 +#define LBRACK 4 +#define RBRACK 5 +#define LPARN 6 +#define RPARN 7 +#define COLON 8 +#define COMMA 9 +#define FSEL 10 + +#define KEYW 19 +#define NAME 20 +#define CON 21 +#define STRING 22 +#define FCON 23 +#define SFCON 24 + +#define SIZEOF 91 +#define INCBEF 30 +#define DECBEF 31 +#define INCAFT 32 +#define DECAFT 33 +#define EXCLA 34 +#define AMPER 35 +#define STAR 36 +#define NEG 37 +#define COMPL 38 + +#define DOT 39 +#define PLUS 40 +#define MINUS 41 +#define TIMES 42 +#define DIVIDE 43 +#define MOD 44 +#define RSHIFT 45 +#define LSHIFT 46 +#define AND 47 +#define OR 48 +#define EXOR 49 +#define ARROW 50 +#define ITOF 51 +#define FTOI 52 +#define LOGAND 53 +#define LOGOR 54 +#define FTOL 56 +#define LTOF 57 +#define ITOL 58 +#define LTOI 59 + +#define EQUAL 60 +#define NEQUAL 61 +#define LESSEQ 62 +#define LESS 63 +#define GREATEQ 64 +#define GREAT 65 +#define LESSEQP 66 +#define LESSP 67 +#define GREATQP 68 +#define GREATP 69 + +#define ASPLUS 70 +#define ASMINUS 71 +#define ASTIMES 72 +#define ASDIV 73 +#define ASMOD 74 +#define ASRSH 75 +#define ASLSH 76 +#define ASSAND 77 +#define ASOR 78 +#define ASXOR 79 +#define ASSIGN 80 + +#define QUEST 90 +#define CALL 100 +#define MCALL 101 +#define JUMP 102 +#define CBRANCH 103 +#define INIT 104 +#define SETREG 105 +#define RFORCE 110 +#define BRANCH 111 +#define LABEL 112 +#define NLABEL 113 +#define RLABEL 114 + +/* + types +*/ +#define INT 0 +#define CHAR 1 +#define FLOAT 2 +#define DOUBLE 3 +#define STRUCT 4 +#define RSTRUCT 5 +#define LONG 6 +#define NOTYPE 7 /* used internally */ + +#define ALIGN 01 +#define TYPE 07 +#define TYLEN 2 +#define XTYPE (03<<3) +#define PTR 010 +#define FUNC 020 +#define ARRAY 030 + +/* + storage classes +*/ +#define KEYWC 1 +#define MOS 10 +#define AUTO 11 +#define EXTERN 12 +#define STATIC 13 +#define REG 14 +#define STRTAG 15 +#define ARG 16 +#define ARG1 17 +#define FMOS 18 + +/* + keywords +*/ +#define GOTO 20 +#define RETURN 21 +#define IF 22 +#define WHILE 23 +#define ELSE 24 +#define SWITCH 25 +#define CASE 26 +#define BREAK 27 +#define CONTIN 28 +#define DO 29 +#define DEFAULT 30 +#define FOR 31 + +/* + characters +*/ +#define INSERT 119 +#define PERIOD 120 +#define SQUOTE 121 +#define DQUOTE 122 +#define LETTER 123 +#define DIGIT 124 +#define NEWLN 125 +#define SPACE 126 +#define UNKN 127 + +/* + * Special operators in intermediate code + */ +#define BDATA 200 +#define WDATA 201 +#define PROG 202 +#define DATA 203 +#define BSS 204 +#define CSPACE 205 +#define SSPACE 206 +#define SYMDEF 207 +#define SAVE 208 +#define RETRN 209 +#define EVEN 210 +#define PROFIL 212 +#define SWIT 213 +#define EXPR 214 +#define SNAME 215 +#define RNAME 216 +#define ANAME 217 +#define NULL 218 + +/* + Flag bits +*/ + +#define BINARY 01 +#define LVALUE 02 +#define RELAT 04 +#define ASSGOP 010 +#define LWORD 020 +#define RWORD 040 +#define COMMUTE 0100 +#define RASSOC 0200 +#define LEAF 0400 + +/* + * Conversion codes + */ +#define ITF 1 +#define ITL 2 +#define LTF 3 +#define ITP 4 +#define PTI 5 +#define FTI 6 +#define LTI 7 +#define FTL 8 +#define XX 15 + +/* + * symbol table flags + */ + +#define FNDEL 01 +#define FNUND 02 +#define FKEYW 04 +#define FFIELD 020 diff --git a/source/c/c0t.s b/source/c/c0t.s new file mode 100644 index 0000000..5ed6f59 --- /dev/null +++ b/source/c/c0t.s @@ -0,0 +1,159 @@ +/ assure fake printf (no floating) + +.globl fltused; fltused = 0 + +/ convert stream to number; result is type. +/ value in cval or fcval + +fpp = 1 + +.globl _getnum + +.globl _peekc +.globl _getchar +.globl _cval +.globl _fcval +.globl _error + +_getnum: + .if fpp + movif $10.,fr3 + clrf fr0 + .endif + clr nfract + clr totdig + clr decpt + clr _cval + mov 2(sp),base + mov r2,-(sp) +1: + jsr r5,getdig + br 2f + .if fpp + mulf fr3,fr0 + movif r0,fr1 + addf fr1,fr0 + .endif + inc nfract + br 1b +2: + tst decpt + bne 1f + clr nfract + cmp r0,$'. + bne 1f + mov pc,decpt + br 1b +1: + tst totdig + beq 1f + cmp r0,$'e + bne 1f + clr -(sp) + clr _cval + mov pc,decpt + clr _cval + mov $10.,base + jsr pc,_getchar + cmp r0,$'+ + beq 2f + cmp r0,$'- + bne 3f + inc (sp) + br 2f +3: + mov r0,_peekc +2: + jsr r5,getdig + br 2f + br 2b +2: + tst (sp)+ + beq 2f + neg _cval +2: + sub _cval,nfract +1: + mov r0,_peekc + tst totdig + bne 1f + mov $39.,r0 / "." operator +9: + mov (sp)+,r2 + rts pc +1: + tst decpt + bne 1f + mov $21.,r0 / fixed constant + br 9b +1: + .if fpp + movif $1,fr2 + mov nfract,r2 + mov r2,-(sp) + beq 2f + bgt 1f + neg r2 +1: + mulf fr3,fr2 + sob r2,1b +2: + tst (sp)+ + ble 1f + divf fr2,fr0 + br 2f +1: + mulf fr2,fr0 +2: + mov $_fcval,r0 + movf fr0,(r0) + tst (r0)+ + tst (r0)+ + bne 1f + tst (r0)+ + bne 1f + tst (r0)+ + bne 1f + mov $24.,r0 + mov _fcval,_cval + br 9b +1: + mov $23.,r0 + br 9b + .endif + .if 1-fpp + mov $fperr,-(sp) + jsr pc,_error + tst (sp)+ + mov $21.,r0 + br 9b +fperr: ; .even + .endif + +getdig: + mov _peekc,r0 + beq 1f + clr _peekc + br 2f +1: + jsr pc,_getchar +2: + sub $'0,r0 + cmp r0,$9. + bhi 1f + inc totdig + mov _cval,r1 + mul base,r1 + add r0,r1 + mov r1,_cval + tst (r5)+ + rts r5 +1: + add $'0,r0 + rts r5 + +.bss +base: .=.+2 +nfract: .=.+2 +decpt: .=.+2 +totdig: .=.+2 diff --git a/source/c/c10.c b/source/c/c10.c new file mode 100644 index 0000000..a3fc68b --- /dev/null +++ b/source/c/c10.c @@ -0,0 +1,922 @@ +# +/* + + C compiler, part 2 + + +*/ + +#include "c1h.c" + +char maprel[] { EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ, + LESS, GREATQP, GREATP, LESSEQP, LESSP +}; + +char notrel[] { NEQUAL, EQUAL, GREAT, GREATEQ, LESS, + LESSEQ, GREATP, GREATQP, LESSP, LESSEQP +}; + +struct tconst czero { CON, INT, 0, 0}; +struct tconst cone { CON, INT, 0, 1}; +struct tconst fczero { SFCON, DOUBLE, 0, 0 }; + +struct table *cregtab; + +int nreg 3; +int isn 10000; +int namsiz 8; + +main(argc, argv) +char *argv[]; +{ + extern fout; + + if (argc<4) { + error("Arg count"); + exit(1); + } + if(fopen(argv[1], ascbuf)<0) { + error("Missing temp file"); + exit(1); + } + if ((fout = creat(argv[3], 0666)) < 0) { + error("Can't create %s", argv[3]); + exit(1); + } + spacep = treespace; + getree(); + /* + * If any floating-point instructions + * were used, generate a reference which + * pulls in the floating-point part of printf. + */ + if (nfloat) + printf(".globl fltused\n"); + /* + * tack on the string file. + */ + close(ascbuf[0]); + if (fopen(argv[2], ascbuf)<0) { + error("Missing temp file"); + exit(1); + } + printf(".globl\n.data\n"); + getree(); + flush(); + exit(nerror!=0); +} + +/* + * Given a tree, a code table, and a + * count of available registers, find the code table + * for the appropriate operator such that the operands + * are of the right type and the number of registers + * required is not too large. + * Return a ptr to the table entry or 0 if none found. + */ +char *match(atree, table, nrleft) +struct tnode *atree; +struct table *table; +{ + int op, d1, d2, t1, t2, dope; + struct tnode *p2; + register struct tnode *p1, *tree; + register struct optab *opt; + + if ((tree=atree)==0) + return(0); + if (table==lsptab) + table = sptab; + if ((op = tree->op)==0) + return(0); + dope = opdope[op]; + if ((dope&LEAF) == 0) + p1 = tree->tr1; + else + p1 = tree; + t1 = p1->type; + d1 = dcalc(p1, nrleft); + if ((dope&BINARY)!=0) { + p2 = tree->tr2; + /* + * If a subtree starts off with a conversion operator, + * try for a match with the conversion eliminated. + * E.g. int = double can be done without generating + * the converted int in a register by + * movf double,fr0; movfi fr0,int . + */ + if(opdope[p1->op]&CNVRT && (opdope[p2->op]&CNVRT)==0) { + tree->tr1 = p1->tr1; + if (opt = match(tree, table, nrleft)) + return(opt); + tree->tr1 = p1; + } else if (opdope[p2->op]&CNVRT && (opdope[p1->op]&CNVRT)==0) { + tree->tr2 = p2->tr1; + if (opt = match(tree, table, nrleft)) + return(opt); + tree->tr2 = p2; + } + t2 = p2->type; + d2 = dcalc(p2, nrleft); + } + for (; table->op!=op; table++) + if (table->op==0) + return(0); + for (opt = table->tabp; opt->tabdeg1!=0; opt++) { + if (d1 > (opt->tabdeg1&077) + || (opt->tabdeg1 >= 0100 && (p1->op != STAR))) + continue; + if (notcompat(p1, opt->tabtyp1, op)) { + continue; + } + if ((opdope[op]&BINARY)!=0 && p2!=0) { + if (d2 > (opt->tabdeg2&077) + || (opt->tabdeg2 >= 0100) && (p2->op != STAR) ) + continue; + if (notcompat(p2,opt->tabtyp2, 0)) + continue; + } + return(opt); + } + return(0); +} + +/* + * Given a tree, a code table, and a register, + * produce code to evaluate the tree with the appropriate table. + * Registers reg and upcan be used. + * If there is a value, it is desired that it appear in reg. + * The routine returns the register in which the value actually appears. + * This routine must work or there is an error. + * If the table called for is cctab, sptab, or efftab, + * and tree can't be done using the called-for table, + * another try is made. + * If the tree can't be compiled using cctab, regtab is + * used and a "tst" instruction is produced. + * If the tree can't be compiled using sptab, + * regtab is used and the register is pushed on the stack. + * If the tree can't be compiled using efftab, + * just use regtab. + * Regtab must succeed or an "op not found" error results. + * + * A number of special cases are recognized, and + * there is an interaction with the optimizer routines. + */ +rcexpr(atree, atable, reg) +struct tnode *atree; +struct table *atable; +{ + register r; + int modf, nargs, recurf; + register struct tnode *tree; + register struct table *table; + + table = atable; + recurf = 0; + if (reg<0) { + recurf++; + reg = ~reg; + if (reg>=020) { + reg =- 020; + recurf++; + } + } + if((tree=atree)==0) + return(0); + switch (tree->op) { + + /* + * A conditional branch + */ + case CBRANCH: + cbranch(optim(tree->btree), tree->lbl, tree->cond, 0); + return(0); + + /* + * An initializing expression + */ + case INIT: + if (tree->tr1->op == AMPER) + tree->tr1 = tree->tr1->tr1; + if (tree->tr1->op==NAME) + pname(tree->tr1); + else if (tree->tr1==CON) + psoct(tree->tr1->value); + else + error("Illegal initialization"); + putchar('\n'); + return(0); + + /* + * Put the value of an expression in r0, + * for a switch or a return + */ + case RFORCE: + if((r=rcexpr(tree->tr1, regtab, reg)) != 0) + printf("mov%c r%d,r0\n", isfloat(tree->tr1), r); + return(0); + + /* + * sequential execution + */ + case COMMA: + rcexpr(tree->tr1, efftab, reg); + atree = tree = tree->tr2; + break; + + /* + * In the generated &~ operator, + * fiddle things so a PDP-11 "bit" + * instruction will be produced when cctab is used. + */ + case NAND: + if (table==cctab) { + tree->op = TAND; + tree->tr2 = optim(block(1, COMPL, INT, 0, tree->tr2)); + } + break; + + + /* + * Handle a subroutine call. It has to be done + * here because if cexpr got called twice, the + * arguments might be compiled twice. + * There is also some fiddling so the + * first argument, in favorable circumstances, + * goes to (sp) instead of -(sp), reducing + * the amount of stack-popping. + */ + case CALL: + r = 0; + nargs = 0; + modf = 0; + if (tree->tr1->op!=NAME) { /* get nargs right */ + nargs++; + nstack++; + } + tree = tree->tr2; + if(tree->op) { + while (tree->op==COMMA) { + r =+ comarg(tree->tr2, &modf); + tree = tree->tr1; + nargs++; + } + r =+ comarg(tree, &modf); + nargs++; + } + tree = atree; + tree->op = CALL2; + if (modf && tree->tr1->op==NAME && tree->tr1->class==EXTERN) + tree->op = CALL1; + cexpr(tree, regtab, reg); + popstk(r); + nstack =- nargs; + if (table==efftab || table==regtab) + return(0); + r = 0; + goto fixup; + + /* + * Longs need special treatment. + */ + case ASLSH: + case LSHIFT: + if (tree->type==LONG) { + if (tree->tr2->op==ITOL) + tree->tr2 = tree->tr2->tr1; + if (tree->op==ASLSH) + tree->op = ASLSHL; + else + tree->op = LLSHIFT; + } + break; + + /* + * Try to change * and / to shifts. + */ + case TIMES: + case DIVIDE: + case ASTIMES: + case ASDIV: + tree = pow2(tree); + } + /* + * Try to find postfix ++ and -- operators that can be + * pulled out and done after the rest of the expression + */ + if (table!=cctab && table!=cregtab && recurf<2 + && (opdope[tree->op]&LEAF)==0) { + if (r=delay(&atree, table, reg)) { + tree = atree; + table = efftab; + reg = r-1; + } + } + /* + * Basically, try to reorder the computation + * so reg = x+y is done as reg = x; reg =+ y + */ + if (recurf==0 && reorder(&atree, table, reg)) { + if (table==cctab && atree->op==NAME) + return(reg); + } + tree = atree; + if (table==efftab && tree->op==NAME) + return(reg); + if ((r=cexpr(tree, table, reg))>=0) + return(r); + if (table!=regtab) { + if((r=cexpr(tree, regtab, reg))>=0) { + fixup: + modf = isfloat(tree); + if (table==sptab || table==lsptab) { + if (tree->type==LONG) { + printf("mov\tr%d,-(sp)\n",r+1); + nstack++; + } + printf("mov%c r%d,%c(sp)\n", modf, r, + table==sptab? '-':0); + nstack++; + } + if (table==cctab) + printf("tst%c r%d\n", modf, r); + return(r); + } + } + if (tree->op>0 && tree->opop]) + error("No code table for op: %s", opntab[tree->op]); + else + error("No code table for op %d", tree->op); + return(reg); +} + +/* + * Try to compile the tree with the code table using + * registers areg and up. If successful, + * return the register where the value actually ended up. + * If unsuccessful, return -1. + * + * Most of the work is the macro-expansion of the + * code table. + */ +cexpr(atree, table, areg) +struct tnode *atree; +struct table *table; +{ + int c, r; + register struct tnode *p, *p1, *tree; + struct table *ctable; + struct tnode *p2; + char *string; + int reg, reg1, rreg, flag, opd; + char *opt; + + tree = atree; + reg = areg; + p1 = tree->tr2; + c = tree->op; + opd = opdope[c]; + /* + * When the value of a relational or a logical expression is + * desired, more work must be done. + */ + if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) { + cbranch(tree, c=isn++, 1, reg); + rcexpr(&czero, table, reg); + branch(isn, 0); + label(c); + rcexpr(&cone, table, reg); + label(isn++); + return(reg); + } + if(c==QUEST) { + if (table==cctab) + return(-1); + cbranch(tree->tr1, c=isn++, 0, reg); + flag = nstack; + rreg = rcexpr(p1->tr1, table, reg); + nstack = flag; + branch(r=isn++, 0); + label(c); + reg = rcexpr(p1->tr2, table, rreg); + if (rreg!=reg) + printf("mov%c r%d,r%d\n", + isfloat(tree),reg,rreg); + label(r); + return(rreg); + } + reg = oddreg(tree, reg); + reg1 = reg+1; + /* + * long values take 2 registers. + */ + if (tree->type==LONG && tree->op!=ITOL) + reg1++; + /* + * Leaves of the expression tree + */ + if ((r = chkleaf(tree, table, reg)) >= 0) + return(r); + /* + * x + (-1) is better done as x-1. + */ + + if ((tree->op==PLUS||tree->op==ASPLUS) && + (p1=tree->tr2)->op == CON && p1->value == -1) { + p1->value = 1; + tree->op =+ (MINUS-PLUS); + } + if (table==cregtab) + table = regtab; + /* + * The following peculiar code depends on the fact that + * if you just want the codition codes set, efftab + * will generate the right code unless the operator is + * postfix ++ or --. Unravelled, if the table is + * cctab and the operator is not special, try first + * for efftab; if the table isn't, if the operator is, + * or the first match fails, try to match + * with the table actually asked for. + */ + if (table!=cctab || c==INCAFT || c==DECAFT + || (opt = match(tree, efftab, nreg-reg)) == 0) + if ((opt=match(tree, table, nreg-reg))==0) + return(-1); + string = opt->tabstring; + p1 = tree->tr1; + p2 = 0; + if (opdope[tree->op]&BINARY) + p2 = tree->tr2; +loop: + /* + * The 0200 bit asks for a tab. + */ + if ((c = *string++) & 0200) { + c =& 0177; + putchar('\t'); + } + switch (c) { + + case '\0': + if (!isfloat(tree)) + if (tree->op==DIVIDE || tree->op==ASDIV) + reg--; + return(reg); + + /* A1 */ + case 'A': + p = p1; + goto adr; + + /* A2 */ + case 'B': + p = p2; + goto adr; + + adr: + c = 0; + if (*string=='\'') { + c = 1; + string++; + } else if (*string=='+') { + c = 2; + string++; + } + pname(p, c); + goto loop; + + /* I */ + case 'M': + if ((c = *string)=='\'') + string++; + else + c = 0; + prins(tree->op, c, instab); + goto loop; + + /* B1 */ + case 'C': + if ((opd&LEAF) != 0) + p = tree; + else + p = p1; + goto pbyte; + + /* BF */ + case 'P': + p = tree; + goto pb1; + + /* B2 */ + case 'D': + p = p2; + pbyte: + if (p->type==CHAR) + putchar('b'); + pb1: + if (isfloat(p)) + putchar('f'); + goto loop; + + /* BE */ + case 'L': + if (p1->type==CHAR || p2->type==CHAR) + putchar('b'); + p = tree; + goto pb1; + + /* F */ + case 'G': + p = p1; + flag = 01; + goto subtre; + + /* S */ + case 'K': + p = p2; + flag = 02; + goto subtre; + + /* H */ + case 'H': + p = tree; + flag = 04; + + subtre: + ctable = regtab; + c = *string++ - 'A'; + if (*string=='!') { + string++; + c =| 020; /* force right register */ + } + if ((c&02)!=0) + ctable = sptab; + if ((c&04)!=0) + ctable = cctab; + if ((flag&01) && ctable==regtab && (c&01)==0 + && (tree->op==DIVIDE||tree->op==MOD + || tree->op==ASDIV||tree->op==ASMOD)) + ctable = cregtab; + if ((c&01)!=0) { + p = p->tr1; + if(collcon(p) && ctable!=sptab) { + if (p->op==STAR) + p = p->tr1; + p = p->tr1; + } + } + if (table==lsptab && ctable==sptab) + ctable = lsptab; + if (c&010) + r = reg1; + else + if (opdope[p->op]&LEAF || p->degree < 2) + r = reg; + else + r = areg; + rreg = rcexpr(p, ctable, r); + if (ctable!=regtab && ctable!=cregtab) + goto loop; + if (c&010) { + if (c&020 && rreg!=reg1) + printf("mov%c r%d,r%d\n", + isfloat(tree),rreg,reg1); + else + reg1 = rreg; + } else if (rreg!=reg) + if ((c&020)==0 && oddreg(tree, 0)==0 && (flag&04 || + flag&01 + && xdcalc(p2, nreg-rreg-1) <= (opt->tabdeg2&077) + || flag&02 + && xdcalc(p1,nreg-rreg-1) <= (opt->tabdeg1&077))) { + reg = rreg; + reg1 = rreg+1; + } else + printf("mov%c\tr%d,r%d\n", + isfloat(tree), rreg, reg); + goto loop; + + /* R */ + case 'I': + r = reg; + if (*string=='-') { + string++; + r--; + } + goto preg; + + /* R1 */ + case 'J': + r = reg1; + preg: + if (*string=='+') { + string++; + r++; + } + if (r>nreg) + error("Register overflow: simplify expression"); + printf("r%d", r); + goto loop; + + case '-': /* check -(sp) */ + if (*string=='(') { + nstack++; + if (table!=lsptab) + putchar('-'); + goto loop; + } + break; + + case ')': /* check (sp)+ */ + putchar(')'); + if (*string=='+') + nstack--; + goto loop; + + /* #1 */ + case '#': + p = p1->tr1; + goto nmbr; + + /* #2 */ + case '"': + p = p2->tr1; + + nmbr: + if(collcon(p)) { + if (p->op==STAR) { + printf("*"); + p = p->tr1; + } + if ((p = p->tr2)->op == CON) { + if (p->value) + psoct(p->value); + } else if (p->op==AMPER) + pname(p->tr1, 0); + } + goto loop; + + case 'T': /* "tst R" if 1st op not in cctab */ + if (dcalc(p1, 5)>12 && !match(p1, cctab, 10)) + printf("tst r%d\n", reg); + goto loop; + case 'V': /* adc or sbc as required for longs */ + switch(tree->op) { + case PLUS: + case ASPLUS: + case INCBEF: + case INCAFT: + printf("adc"); + break; + + case MINUS: + case ASMINUS: + case NEG: + case DECBEF: + case DECAFT: + printf("sbc"); + break; + + default: + while ((c = *string++)!='\n' && c!='\0'); + break; + } + goto loop; + } + putchar(c); + goto loop; +} + +/* + * This routine just calls sreorder (below) + * on the subtrees and then on the tree itself. + * It returns non-zero if anything changed. + */ +reorder(treep, table, reg) +struct tnode **treep; +struct table *table; +{ + register r, r1; + register struct tnode *p; + + p = *treep; + if (opdope[p->op]&LEAF) + return(0); + r1 = 0; + while(sreorder(&p->tr1, table, reg)) + r1++; + if (opdope[p->op]&BINARY) + while(sreorder(&p->tr2, table, reg)) + r1++; + r = 0; + while (sreorder(treep, table, reg)) + r++; + *treep = optim(*treep); + return(r); +} + +/* + * Basically this routine carries out two kinds of optimization. + * First, it observes that "x + (reg = y)" where actually + * the = is any assignment op is better done as "reg=y; x+reg". + * In this case rcexpr is called to do the first part and the + * tree is modified so the name of the register + * replaces the assignment. + * Moreover, expressions like "reg = x+y" are best done as + * "reg = x; reg =+ y" (so long as "reg" and "y" are not the same!). + */ +sreorder(treep, table, reg) +struct tnode **treep; +struct table *table; +{ + register struct tnode *p, *p1; + + p = *treep; + if (opdope[p->op]&LEAF) + return(0); + if (p->op==PLUS) + if (reorder(&p->tr2, table, reg)) + *treep = p = optim(p); + p1 = p->tr1; + if (p->op==STAR || p->op==PLUS) { + if (reorder(&p->tr1, table, reg)) + *treep = p = optim(p); + p1 = p->tr1; + } + if (p1->op==NAME) switch(p->op) { + case ASLSH: + case ASRSH: + case ASSIGN: + if (p1->class != REG || isfloat(p->tr2)) + return(0); + if (p->op==ASSIGN) switch (p->tr2->op) { + case TIMES: + case DIVIDE: + if (!ispow2(p->tr2)) + break; + p->tr2 = pow2(p->tr2); + case PLUS: + case MINUS: + case AND: + case NAND: + case OR: + case EXOR: + case LSHIFT: + case RSHIFT: + p1 = p->tr2->tr2; + if (xdcalc(p1) > 12 + || p1->op==NAME + &&(p1->nloc==p->tr1->nloc + || p1->regno==p->tr1->nloc)) + return(0); + p1 = p->tr2; + p->tr2 = p1->tr1; + if (p1->tr1->op!=NAME + || p1->tr1->class!=REG + || p1->tr1->nloc!=p->tr1->nloc) + rcexpr(p, efftab, reg); + p->tr2 = p1->tr2; + p->op = p1->op + ASPLUS - PLUS; + *treep = p; + return(1); + } + goto OK; + + case ASTIMES: + case ASDIV: + if (!ispow2(p)) + return(0); + case ASPLUS: + case ASMINUS: + case ASSAND: + case ASSNAND: + case ASOR: + case ASXOR: + case DECBEF: + case INCBEF: + OK: + if (table==cctab||table==cregtab) + reg =+ 020; + rcexpr(optim(p), efftab, ~reg); + *treep = p1; + return(1); + } + return(0); +} + +/* + * Delay handles postfix ++ and -- + * It observes that "x + y++" is better + * treated as "x + y; y++". + * If the operator is ++ or -- itself, + * it calls rcexpr to load the operand, letting + * the calling instance of rcexpr to do the + * ++ using efftab. + * Otherwise it uses sdelay to search for inc/dec + * among the operands. + */ +delay(treep, table, reg) +struct tnode **treep; +{ + register struct tnode *p, *p1; + register r; + + p = *treep; + if (table!=efftab && (p->op==INCAFT||p->op==DECAFT) + && p->tr1->op==NAME) { + return(1+rcexpr(p->tr1, table, reg)); + } + p1 = 0; + if (opdope[p->op]&BINARY) + p1 = sdelay(&p->tr2); + if (p1==0) + p1 = sdelay(&p->tr1); + if (p1) { + r = rcexpr(optim(p), table, reg); + *treep = p1; + return(r+1); + } + return(0); +} + +sdelay(ap) +struct tnode **ap; +{ + register struct tnode *p, *p1; + + p = *ap; + if ((p->op==INCAFT||p->op==DECAFT) && p->tr1->op==NAME) { + *ap = ncopy(p->tr1); + return(p); + } + if (p->op==STAR || p->op==PLUS) + if (p1=sdelay(&p->tr1)) + return(p1); + if (p->op==PLUS) + return(sdelay(&p->tr2)); + return(0); +} + +/* + * Copy a tree node for a register variable. + * Used by sdelay because if *reg-- is turned + * into *reg; reg-- the *reg will in turn + * be changed to some offset class, accidentally + * modifying the reg--. + */ +ncopy(ap) +struct tname *ap; +{ + register struct tname *p; + + p = ap; + if (p->class!=REG) + return(p); + return(block(3, NAME, p->type, p->elsize, p->tr1, + p->offset, p->nloc)); +} + +/* + * If the tree can be immediately loaded into a register, + * produce code to do so and return success. + */ +chkleaf(atree, table, reg) +struct tnode *atree; +{ + struct tnode lbuf; + register struct tnode *tree; + + tree = atree; + if (tree->op!=STAR && dcalc(tree, nreg-reg) > 12) + return(-1); + lbuf.op = LOAD; + lbuf.type = tree->type; + lbuf.degree = tree->degree; + lbuf.tr1 = tree; + return(rcexpr(&lbuf, table, reg)); +} + +/* + * Compile a function argument. + * If the stack is currently empty, put it in (sp) + * rather than -(sp); this will save a pop. + * Return the number of bytes pushed, + * for future popping. + */ +comarg(atree, flagp) +int *flagp; +{ + register struct tnode *tree; + register retval; + + tree = atree; + if (nstack || isfloat(tree) || tree->type==LONG) { + rcexpr(tree, sptab, 0); + retval = arlength(tree->type); + } else { + (*flagp)++; + rcexpr(tree, lsptab, 0); + retval = 0; + } + return(retval); +} diff --git a/source/c/c11.c b/source/c/c11.c new file mode 100644 index 0000000..8c88291 --- /dev/null +++ b/source/c/c11.c @@ -0,0 +1,849 @@ +# +/* + * C compiler + */ + +#include "c1h.c" + +max(a, b) +{ + if (a>b) + return(a); + return(b); +} + +degree(at) +struct tnode *at; +{ + register struct tnode *t, *t1; + + if ((t=at)==0 || t->op==0) + return(0); + if (t->op == CON) + return(-3); + if (t->op == AMPER) + return(-2); + if (t->op==ITOL && (t1 = isconstant(t)) && t1->value>= 0) + return(-2); + if ((opdope[t->op] & LEAF) != 0) { + if (t->type==CHAR || t->type==FLOAT) + return(1); + return(0); + } + return(t->degree); +} + +pname(ap, flag) +struct tnode *ap; +{ + register i; + register struct tnode *p; + + p = ap; +loop: + switch(p->op) { + + case SFCON: + case CON: + printf("$"); + psoct(p->value); + return; + + case FCON: + printf("L%d", p->value); + return; + + case NAME: + i = p->offset; + if (flag==2) + i =+ 2; + if (i) { + psoct(i); + if (p->class!=OFFS) + putchar('+'); + if (p->class==REG) + regerr(); + } + switch(p->class) { + + case SOFFS: + case XOFFS: + pbase(p); + + case OFFS: + printf("(r%d)", p->regno); + return; + + case EXTERN: + case STATIC: + pbase(p); + return; + + case REG: + printf("r%d", p->nloc); + return; + + } + error("Compiler error: pname"); + return; + + case AMPER: + putchar('$'); + p = p->tr1; + if (p->op==NAME && p->class==REG) + regerr(); + goto loop; + + case AUTOI: + printf("(r%d)%c", p->nloc, flag==1?0:'+'); + return; + + case AUTOD: + printf("%c(r%d)", flag==1?0:'-', p->nloc); + return; + + case STAR: + p = p->tr1; + putchar('*'); + goto loop; + + } + error("pname called illegally"); +} + +regerr() +{ + error("Illegal use of register"); +} + +pbase(ap) +struct tnode *ap; +{ + register struct tnode *p; + + p = ap; + if (p->class==SOFFS || p->class==STATIC) + printf("L%d", p->nloc); + else + printf("_%.8s", &(p->nloc)); +} + +xdcalc(ap, nrleft) +struct tnode *ap; +{ + register struct tnode *p; + register d; + + p = ap; + d = dcalc(p, nrleft); + if (d<20 && p->type==CHAR) { + if (nrleft>=1) + d = 20; + else + d = 24; + } + return(d); +} + +dcalc(ap, nrleft) +struct tnode *ap; +{ + register struct tnode *p, *p1; + + if ((p=ap)==0) + return(0); + switch (p->op) { + + case NAME: + if (p->class==REG) + return(9); + + case AMPER: + case FCON: + case AUTOI: + case AUTOD: + return(12); + + case CON: + case SFCON: + if (p->value==0) + return(4); + if (p->value==1) + return(5); + if (p->value > 0) + return(8); + return(12); + + case STAR: + p1 = p->tr1; + if (p1->op==NAME||p1->op==CON||p1->op==AUTOI||p1->op==AUTOD) + if (p->type!=LONG) + return(12); + } + if (p->type==LONG) + nrleft--; + return(p->degree <= nrleft? 20: 24); +} + +notcompat(ap, ast, op) +struct tnode *ap; +{ + register at, st; + register struct tnode *p; + + p = ap; + at = p->type; + st = ast; + if (st==0) /* word, byte */ + return(at>CHAR && atINT && atop==NAME && p->class==REG && op==ASSIGN && st==CHAR) + return(0); + return(st != at); +} + +prins(op, c, itable) +struct instab *itable; +{ + register struct instab *insp; + register char *ip; + + for (insp=itable; insp->op != 0; insp++) { + if (insp->op == op) { + ip = c? insp->str2: insp->str1; + if (ip==0) + break; + printf("%s", ip); + return; + } + } + error("No match' for op %d", op); +} + +collcon(ap) +struct tnode *ap; +{ + register op; + register struct tnode *p; + + p = ap; + if (p->op==STAR) + p = p->tr1; + if (p->op==PLUS) { + op = p->tr2->op; + if (op==CON || op==AMPER) + return(1); + } + return(0); +} + +isfloat(at) +struct tnode *at; +{ + register struct tnode *t; + + t = at; + if ((opdope[t->op]&RELAT)!=0) + t = t->tr1; + if (t->type==FLOAT || t->type==DOUBLE) { + nfloat = 1; + return('f'); + } + return(0); +} + +oddreg(t, areg) +struct tnode *t; +{ + register reg; + + reg = areg; + if (!isfloat(t)) + switch(t->op) { + case DIVIDE: + case MOD: + case ASDIV: + case ASMOD: + reg++; + + case TIMES: + case ASTIMES: + return(reg|1); + } + return(reg); +} + +arlength(t) +{ + if (t>=PTR) + return(2); + switch(t) { + + case INT: + case CHAR: + return(2); + + case LONG: + return(4); + + case FLOAT: + case DOUBLE: + return(8); + } + return(1024); +} + +/* + * Strings for switch code. + */ + +char dirsw[] {"\ +cmp r0,$%o\n\ +jhi L%d\n\ +asl r0\n\ +jmp *L%d(r0)\n\ +.data\n\ +L%d:\ +" }; + +char simpsw[] {"\ +mov $L%d,r1\n\ +mov r0,L%d\n\ +L%d:cmp r0,(r1)+\n\ +jne L%d\n\ +jmp *L%d-L%d(r1)\n\ +.data\n\ +L%d:\ +"}; + +char hashsw[] {"\ +mov r0,r1\n\ +clr r0\n\ +div $%o,r0\n\ +asl r1\n\ +add $L%d,r1\n\ +mov r0,*(r1)+\n\ +mov (r1)+,r1\n\ +L%d:cmp r0,-(r1)\n\ +jne L%d\n\ +jmp *L%d-L%d(r1)\n\ +.data\n\ +L%d:\ +"}; + +pswitch(afp, alp, deflab) +struct swtab *afp, *alp; +{ + int tlab, ncase, i, j, tabs, worst, best, range; + register struct swtab *swp, *fp, *lp; + int poctab[swsiz]; + + fp = afp; + lp = alp; + if (fp==lp) { + printf("jbr L%d\n", deflab); + return; + } + tlab = isn++; + if (sort(fp, lp)) + return; + ncase = lp-fp; + lp--; + range = lp->swval - fp->swval; + /* direct switch */ + if (range>0 && range <= 3*ncase) { + if (fp->swval) + printf("sub $%o,r0\n", fp->swval); + printf(dirsw, range, deflab, isn, isn); + isn++; + for (i=fp->swval; i<=lp->swval; i++) { + if (i==fp->swval) { + printf("L%d\n", fp->swlab); + fp++; + } else + printf("L%d\n", deflab); + } + goto esw; + } + /* simple switch */ + if (ncase<8) { + i = isn++; + j = isn++; + printf(simpsw, i, j, isn, isn, j, i, i); + isn++; + for (; fp<=lp; fp++) + printf("%o\n", fp->swval); + printf("L%d:..\n", j); + for (fp = afp; fp<=lp; fp++) + printf("L%d\n", fp->swlab); + printf("L%d\n", deflab); + goto esw; + } + /* hash switch */ + best = 077777; + for (i=ncase/4; i<=ncase/2; i++) { + for (j=0; jswval, i)]++; + worst = 0; + for (j=0; jworst) + worst = poctab[j]; + if (i*worst < best) { + tabs = i; + best = i*worst; + } + } + i = isn++; + printf(hashsw, tabs, isn, i, i, isn+tabs+1, isn+1, isn); + isn++; + for (i=0; i<=tabs; i++) + printf("L%d\n", isn+i); + for (i=0; iswval, tabs) == i) + printf("%o\n", ldiv(0, swp->swval, tabs)); + } + printf("L%d:", isn++); + for (i=0; iswval, tabs) == i) + printf("L%d\n", swp->swlab); + } +esw: + printf(".text\n"); +} + +sort(afp, alp) +struct swtab *afp, *alp; +{ + register struct swtab *cp, *fp, *lp; + int intch, t; + + fp = afp; + lp = alp; + while (fp < --lp) { + intch = 0; + for (cp=fp; cpswval == cp[1].swval) { + error("Duplicate case (%d)", cp->swval); + return(1); + } + if (cp->swval > cp[1].swval) { + intch++; + t = cp->swval; + cp->swval = cp[1].swval; + cp[1].swval = t; + t = cp->swlab; + cp->swlab = cp[1].swlab; + cp[1].swlab = t; + } + } + if (intch==0) + break; + } + return(0); +} + +ispow2(atree) +{ + register int d; + register struct tnode *tree; + + tree = atree; + if (!isfloat(tree) && tree->tr2->op==CON) { + d = tree->tr2->value; + if (d>1 && (d&(d-1))==0) + return(d); + } + return(0); +} + +pow2(atree) +struct tnode *atree; +{ + register int d, i; + register struct tnode *tree; + + tree = atree; + if (d = ispow2(tree)) { + for (i=0; (d=>>1)!=0; i++); + tree->tr2->value = i; + d = tree->op; + tree->op = d==TIMES? LSHIFT: + (d==DIVIDE? RSHIFT: + (d==ASTIMES? ASLSH: ASRSH)); + tree = optim(tree); + } + return(tree); +} + +cbranch(atree, albl, cond, areg) +struct tnode *atree; +{ + int l1, op; + register lbl, reg; + register struct tnode *tree; + + lbl = albl; + reg = areg; + if ((tree=atree)==0) + return; + switch(tree->op) { + + case LOGAND: + if (cond) { + cbranch(tree->tr1, l1=isn++, 0, reg); + cbranch(tree->tr2, lbl, 1, reg); + label(l1); + } else { + cbranch(tree->tr1, lbl, 0, reg); + cbranch(tree->tr2, lbl, 0, reg); + } + return; + + case LOGOR: + if (cond) { + cbranch(tree->tr1, lbl, 1, reg); + cbranch(tree->tr2, lbl, 1, reg); + } else { + cbranch(tree->tr1, l1=isn++, 1, reg); + cbranch(tree->tr2, lbl, 0, reg); + label(l1); + } + return; + + case EXCLA: + cbranch(tree->tr1, lbl, !cond, reg); + return; + + case COMMA: + rcexpr(tree->tr1, efftab, reg); + tree = tree->tr2; + break; + } + op = tree->op; + if (tree->type==LONG || opdope[op]&RELAT&&tree->tr1->type==LONG) { + if (tree->type!=LONG) { + tree->op = MINUS; + tree->type = LONG; + tree = optim(tree); + } else + op = NEQUAL; + rcexpr(tree, regtab, 0); + printf("ashc $0,r0\n"); + branch(lbl, op, !cond); + return; + } + rcexpr(tree, cctab, reg); + op = tree->op; + if ((opdope[op]&RELAT)==0) + op = NEQUAL; + else { + l1 = tree->tr2->op; + if ((l1==CON || l1==SFCON) && tree->tr2->value==0) + op =+ 200; /* special for ptr tests */ + else + op = maprel[op-EQUAL]; + } + if (isfloat(tree)) + printf("cfcc\n"); + branch(lbl, op, !cond); +} + +branch(lbl, aop, c) +{ + register op; + + if(op=aop) + prins(op, c, branchtab); + else + printf("jbr"); + printf("\tL%d\n", lbl); +} + +label(l) +{ + printf("L%d:", l); +} + +popstk(a) +{ + switch(a) { + + case 0: + return; + + case 2: + printf("tst (sp)+\n"); + return; + + case 4: + printf("cmp (sp)+,(sp)+\n"); + return; + } + printf("add $%o,sp\n", a); +} + +error(s, p1, p2, p3, p4, p5, p6) +{ + register f; + extern fout; + + nerror++; + flush(); + f = fout; + fout = 1; + printf("%d: ", line); + printf(s, p1, p2, p3, p4, p5, p6); + putchar('\n'); + flush(); + fout = f; +} + +psoct(an) +{ + register int n, sign; + + sign = 0; + if ((n = an) < 0) { + n = -n; + sign = '-'; + } + printf("%c%o", sign, n); +} + +/* + * Read in an intermediate file. + */ +getree() +{ + struct tnode *expstack[20]; + register struct tnode **sp; + register t, op; + static char s[9]; + struct swtab *swp; + + spacep = treespace; + sp = expstack; + for (;;) { + if (sp >= &expstack[20]) + error("Stack botch"); + op = getw(ascbuf); + if ((op&0177400) != 0177000) { + error("Intermediate file error"); + exit(1); + } + switch(op =& 0377) { + + case EOF: + return; + + case BDATA: + printf(".byte "); + seq(','); + break; + + case WDATA: + seq(';'); + break; + + case PROG: + printf(".text\n"); + break; + + case DATA: + printf(".data\n"); + break; + + case BSS: + printf(".bss\n"); + break; + + case SYMDEF: + printf(".globl _%s\n", outname(s)); + break; + + case RETRN: + printf("jmp cret\n"); + break; + + case CSPACE: + t = outname(s); + printf(".comm _%s,%o\n", t, getw(ascbuf)); + break; + + case SSPACE: + printf(".=.+%o\n", getw(ascbuf)); + break; + + case EVEN: + printf(".even\n"); + break; + + case SAVE: + printf("jsr r5,csv\n"); + t = getw(ascbuf)-6; + if (t==2) + printf("tst -(sp)\n"); + else if (t > 2) + printf("sub $%o,sp\n", t); + break; + + case PROFIL: + t = getw(ascbuf); + printf("mov $L%d,r0\njsr pc,mcount\n", t); + printf(".bss\nL%d:.=.+2\n.text\n", t); + break; + + case SNAME: + t = outname(s); + printf("~%s=L%d\n", t, getw(ascbuf)); + break; + + case ANAME: + t = outname(s); + printf("~%s=%o\n", t, getw(ascbuf)); + break; + + case RNAME: + t = outname(s); + printf("~%s=r%d\n", t, getw(ascbuf)); + break; + + case SWIT: + t = getw(ascbuf); + line = getw(ascbuf); + swp = treespace; + while (swp->swlab = getw(ascbuf)) { + swp->swval = getw(ascbuf); + swp++; + } + pswitch(treespace, swp, t); + break; + + case EXPR: + line = getw(ascbuf); + if (sp != &expstack[1]) { + error("Expression input botch\n"); + exit(1); + } + nstack = 0; + rcexpr(optim(*--sp), efftab, 0); + spacep = treespace; + break; + + case NAME: + t = getw(ascbuf); + if (t==EXTERN) { + t = getw(ascbuf); + *sp = block(6, NAME, t, 0, EXTERN, 0, 0,0,0,0); + outname(&(*sp)->nloc); + sp++; + break; + } + *sp = block(3, NAME, 0, 0, t, 0, 0); + (*sp)->type = getw(ascbuf); + (*sp)->nloc = getw(ascbuf); + sp++; + break; + + case CON: + case SFCON: + case FCON: + t = getw(ascbuf); + *sp++ = block(1, op, t, 0, getw(ascbuf)); + break; + + case FSEL: + t = getw(ascbuf); + sp[-1] = block(2, op, t, 0, sp[-1], getw(ascbuf)); + break; + + case NULL: + *sp++ = block(0, 0, 0, 0); + break; + + case CBRANCH: + t = getw(ascbuf); + sp[-1] = block(1, CBRANCH, sp[-1], t, getw(ascbuf)); + break; + + case LABEL: + label(getw(ascbuf)); + break; + + case NLABEL: + printf("_%s:\n", outname(s)); + break; + + case RLABEL: + t = outname(s); + printf("_%s:\n~~%s:\n", t, t); + break; + + case BRANCH: + branch(getw(ascbuf), 0); + break; + + case SETREG: + nreg = getw(ascbuf)-1; + break; + + default: + if (opdope[op]&BINARY) { + if (sp < &expstack[1]) { + error("Binary expression botch"); + exit(1); + } + t = *--sp; + *sp++ = block(2, op, getw(ascbuf), 0, *--sp, t); + } else { + sp[-1] = block(1, op, getw(ascbuf), 0, sp[-1]); + } + break; + } + } +} + +outname(s) +{ + register char *p, c; + register n; + + p = s; + n = 0; + while (c = getc(ascbuf)) { + *p++ = c; + n++; + } + while (n++ < 8) + *p++ = 0; + return(s); +} + +seq(c) +{ + register o; + + if (getw(ascbuf) == 0) + return; + for (;;) { + printf("%o", getw(ascbuf)); + if ((o = getw(ascbuf)) != 1) + break; + printf("%c", c); + } + printf("\n"); +} diff --git a/source/c/c12.c b/source/c/c12.c new file mode 100644 index 0000000..69961f2 --- /dev/null +++ b/source/c/c12.c @@ -0,0 +1,621 @@ +# +/* + * C compiler part 2 -- expression optimizer + * + */ + +#include "c1h.c" + +optim(atree) +struct tnode *atree; +{ + register op, dope; + int d1, d2; + struct tnode *t; + register struct tnode *tree; + + if ((tree=atree)==0) + return(0); + if ((op = tree->op)==0) + return(tree); + if (op==NAME && tree->class==AUTO) { + tree->class = OFFS; + tree->regno = 5; + tree->offset = tree->nloc; + } + dope = opdope[op]; + if ((dope&LEAF) != 0) + return(tree); + if ((dope&BINARY) == 0) + return(unoptim(tree)); + /* is known to be binary */ + if (tree->type==CHAR) + tree->type = INT; + if ((dope&COMMUTE)!=0) { + acomm: d1 = tree->type; + tree = acommute(tree); + tree->type = d1; + /* + * PDP-11 special: + * replace a&b by a NAND ~ b. + * This will be undone when in + * truth-value context. + */ + if (tree->op!=AND) + return(tree); + tree->op = NAND; + tree->tr2 = block(1, COMPL, tree->tr2->type, 0, tree->tr2); + } + again: + tree->tr1 = optim(tree->tr1); + tree->tr2 = optim(tree->tr2); + if ((dope&RELAT) != 0) { + if ((d1=degree(tree->tr1)) < (d2=degree(tree->tr2)) + || d1==d2 && tree->tr1->op==NAME && tree->tr2->op!=NAME) { + t = tree->tr1; + tree->tr1 = tree->tr2; + tree->tr2 = t; + tree->op = maprel[op-EQUAL]; + } + if (tree->tr1->type==CHAR && tree->tr2->op==CON + && (dcalc(tree->tr1) <= 12 || tree->tr1->op==STAR) + && tree->tr2->value <= 127 && tree->tr2->value >= 0) + tree->tr2->type = CHAR; + } + d1 = max(degree(tree->tr1), islong(tree->type)); + d2 = max(degree(tree->tr2), 0); + if (tree->tr1->type==LONG && dope&RELAT) + d1 = 10; + switch (op) { + + case LTIMES: + case LDIV: + case LMOD: + case LASTIMES: + case LASDIV: + case LASMOD: + tree->degree = 10; + break; + + /* + * PDP-11 special: + * generate new =&~ operator out of =& + * by complementing the RHS. + */ + case ASSAND: + op = ASSNAND; + tree->op = op; + tree->tr2 = block(2, COMPL, tree->tr2->type, 0, tree->tr2); + goto again; + + case NAND: + if (isconstant(tree->tr2) && tree->tr2->value==0) + return(tree->tr1); + goto def; + + case CALL: + tree->degree = 10; + break; + + case QUEST: + case COLON: + tree->degree = max(d1, d2); + break; + + case MINUS: + if (t = isconstant(tree->tr2)) { + tree->op = PLUS; + if (t->type==DOUBLE) + /* PDP-11 FP representation */ + t->value =^ 0100000; + else + t->value = -t->value; + goto acomm; + } + goto def; + + case DIVIDE: + case ASDIV: + case ASTIMES: + if (tree->tr2->op==CON && tree->tr2->value==1) + return(tree->tr1); + if (ispow2(tree) == 0) { + + case MOD: + case ASMOD: + d1 =+ 2; + d2 =+ 2; + } + if (tree->type==LONG) + return(hardlongs(tree)); + goto constant; + + case LSHIFT: + case RSHIFT: + case ASRSH: + case ASLSH: + if (tree->tr2->op==CON && tree->tr2->value==0) + return(tree->tr1); + /* + * PDP-11 special: turn right shifts into negative + * left shifts + */ + if (op==LSHIFT||op==ASLSH) + goto constant; + if (tree->tr2->op==CON && tree->tr2->value==1) + goto constant; + op =+ (LSHIFT-RSHIFT); + tree->op = op; + tree->tr2 = block(1, NEG, tree->type, 0, tree->tr2); + goto again; + + constant: + if (tree->tr1->op==CON && tree->tr2->op==CON) { + const(op, &tree->tr1->value, tree->tr2->value); + return(tree->tr1); + } + + + def: + default: + tree->degree = d1==d2? d1+islong(tree->type): max(d1, d2); + break; + } + return(tree); +} + +unoptim(atree) +struct tnode *atree; +{ + register struct tnode *subtre, *tree; + register int *p; + double static fv; + struct { int integer; }; + + if ((tree=atree)==0) + return(0); + if (tree->op==CBRANCH) { + tree->btree = optim(tree->btree); + return(tree); + } + subtre = tree->tr1 = optim(tree->tr1); + switch (tree->op) { + + case FSEL: + tree->tr1 = block(2, RSHIFT, INT, 0, subtre, + block(1, CON, INT, 0, tree->bitoffs)); + tree->op = AND; + tree->type = INT; + tree->tr2 = block(1, CON, INT, 0, (1<flen)-1); + return(optim(tree)); + + case AMPER: + if (subtre->op==STAR) + return(subtre->tr1); + if (subtre->op==NAME && subtre->class == OFFS) { + p = block(2, PLUS, tree->type, 1, subtre, tree); + subtre->type = tree->type; + tree->op = CON; + tree->type = INT; + tree->degree = 0; + tree->value = subtre->offset; + subtre->class = REG; + subtre->nloc = subtre->regno; + subtre->offset = 0; + return(p); + } + break; + + case STAR: + if (subtre->op==AMPER) + return(subtre->tr1); + if (subtre->op==NAME && subtre->class==REG) { + subtre->type = tree->type; + subtre->class = OFFS; + subtre->regno = subtre->nloc; + return(subtre); + } + p = subtre->tr1; + if ((subtre->op==INCAFT||subtre->op==DECBEF)&&tree->type!=LONG + && p->op==NAME && p->class==REG && p->type==subtre->type) { + p->type = tree->type; + p->op = subtre->op==INCAFT? AUTOI: AUTOD; + return(p); + } + if (subtre->op==PLUS && p->op==NAME && p->class==REG) { + if (subtre->tr2->op==CON) { + p->offset =+ subtre->tr2->value; + p->class = OFFS; + p->type = tree->type; + p->regno = p->nloc; + return(p); + } + if (subtre->tr2->op==AMPER) { + subtre = subtre->tr2->tr1; + subtre->class =+ XOFFS-EXTERN; + subtre->regno = p->nloc; + subtre->type = tree->type; + return(subtre); + } + } + break; + case EXCLA: + if ((opdope[subtre->op]&RELAT)==0) + break; + tree = subtre; + tree->op = notrel[tree->op-EQUAL]; + break; + + case NEG: + case COMPL: + if (tree->type==CHAR) + tree->type = INT; + if (tree->op == subtre->op) + return(subtre->tr1); + if (subtre->op==ITOL) { + subtre->op = tree->op; + subtre->type = INT; + tree->op = ITOL; + } + } + if (subtre->op == CON) switch(tree->op) { + + case NEG: + subtre->value = -subtre->value; + return(subtre); + + case COMPL: + subtre->value = ~subtre->value; + return(subtre); + + case ITOF: + fv = subtre->value; + p = &fv; + p++; + if (*p++==0 && *p++==0 && *p++==0) { + subtre->type = DOUBLE; + subtre->value = fv.integer; + subtre->op = SFCON; + return(subtre); + } + break; + } + tree->degree = max(islong(tree->type), degree(subtre)); + return(tree); +} + +struct acl { + int nextl; + int nextn; + struct tnode *nlist[20]; + struct tnode *llist[21]; +}; + +acommute(atree) +{ + struct acl acl; + int d, i, op, flt; + register struct tnode *t1, **t2, *tree; + struct tnode *t; + + acl.nextl = 0; + acl.nextn = 0; + tree = atree; + op = tree->op; + flt = isfloat(tree); + insert(op, tree, &acl); + acl.nextl--; + t2 = &acl.llist[acl.nextl]; + if (!flt) { + /* put constants together */ + for (i=acl.nextl;i>0&&t2[0]->op==CON&&t2[-1]->op==CON;i--) { + acl.nextl--; + t2--; + const(op, &t2[0]->value, t2[1]->value); + } + } + if (op==PLUS || op==OR) { + /* toss out "+0" */ + if (acl.nextl>0 && (t1 = isconstant(*t2)) && t1->value==0) { + acl.nextl--; + t2--; + } + if (acl.nextl <= 0) + return(*t2); + /* subsume constant in "&x+c" */ + if (op==PLUS && t2[0]->op==CON && t2[-1]->op==AMPER) { + t2--; + t2[0]->tr1->offset =+ t2[1]->value; + acl.nextl--; + } + } else if (op==TIMES || op==AND) { + t1 = acl.llist[acl.nextl]; + if (t1->op==CON) { + if (t1->value==0) + return(t1); + if (op==TIMES && t1->value==1 && acl.nextl>0) + if (--acl.nextl <= 0) + return(acl.llist[0]); + } + } + if (op==PLUS && !flt) + distrib(&acl); + tree = *(t2 = &acl.llist[0]); + d = max(degree(tree), islong(tree->type)); + if (op==TIMES && !flt) + d++; + for (i=0; itr2 = t = *++t2; + t1->degree = d = d==degree(t)? d+islong(t1->type): max(d, degree(t)); + t1->tr1 = tree; + tree = t1; + if (tree->type==LONG) { + if (tree->op==TIMES) + tree = hardlongs(tree); + else if (tree->op==PLUS && (t = isconstant(tree->tr1)) + && t->value < 0) { + tree->op = MINUS; + t->value = - t->value; + t = tree->tr1; + tree->tr1 = tree->tr2; + tree->tr2 = t; + } + } + } + if (tree->op==TIMES && ispow2(tree)) + tree->degree = max(degree(tree->tr1), islong(tree->type)); + return(tree); +} + +distrib(list) +struct acl *list; +{ +/* + * Find a list member of the form c1c2*x such + * that c1c2 divides no other such constant, is divided by + * at least one other (say in the form c1*y), and which has + * fewest divisors. Reduce this pair to c1*(y+c2*x) + * and iterate until no reductions occur. + */ + register struct tnode **p1, **p2; + struct tnode *t; + int ndmaj, ndmin; + struct tnode **dividend, **divisor; + struct tnode **maxnod, **mindiv; + + loop: + maxnod = &list->llist[list->nextl]; + ndmaj = 1000; + dividend = 0; + for (p1 = list->llist; p1 <= maxnod; p1++) { + if ((*p1)->op!=TIMES || (*p1)->tr2->op!=CON) + continue; + ndmin = 0; + for (p2 = list->llist; p2 <= maxnod; p2++) { + if (p1==p2 || (*p2)->op!=TIMES || (*p2)->tr2->op!=CON) + continue; + if ((*p1)->tr2->value == (*p2)->tr2->value) { + (*p2)->tr2 = (*p1)->tr1; + (*p2)->op = PLUS; + (*p1)->tr1 = (*p2); + *p1 = optim(*p1); + squash(p2, maxnod); + list->nextl--; + goto loop; + } + if (((*p2)->tr2->value % (*p1)->tr2->value) == 0) + goto contmaj; + if (((*p1)->tr2->value % (*p2)->tr2->value) == 0) { + ndmin++; + mindiv = p2; + } + } + if (ndmin > 0 && ndmin < ndmaj) { + ndmaj = ndmin; + dividend = p1; + divisor = mindiv; + } + contmaj:; + } + if (dividend==0) + return; + t = list->nlist[--list->nextn]; + p1 = dividend; + p2 = divisor; + t->op = PLUS; + t->type = (*p1)->type; + t->tr1 = (*p1); + t->tr2 = (*p2)->tr1; + (*p1)->tr2->value =/ (*p2)->tr2->value; + (*p2)->tr1 = t; + t = optim(*p2); + if (p1 < p2) { + *p1 = t; + squash(p2, maxnod); + } else { + *p2 = t; + squash(p1, maxnod); + } + list->nextl--; + goto loop; +} + +squash(p, maxp) +struct tnode **p, **maxp; +{ + register struct tnode **np; + + for (np = p; np < maxp; np++) + *np = *(np+1); +} + +const(op, vp, av) +int *vp; +{ + register int v; + + v = av; + switch (op) { + + case PLUS: + *vp =+ v; + return; + + case TIMES: + *vp =* v; + return; + + case AND: + *vp =& v; + return; + + case OR: + *vp =| v; + return; + + case EXOR: + *vp =^ v; + return; + + case DIVIDE: + case MOD: + if (v==0) + error("Divide check"); + else + if (op==DIVIDE) + *vp =/ v; + else + *vp =% v; + return; + + case RSHIFT: + *vp =>> v; + return; + + case LSHIFT: + *vp =<< v; + return; + + case NAND: + *vp =& ~ v; + return; + } + error("C error: const"); +} + +insert(op, atree, alist) +struct acl *alist; +{ + register d; + register struct acl *list; + register struct tnode *tree; + int d1, i; + struct tnode *t; + + tree = atree; + list = alist; + if (tree->op == op) { + ins: list->nlist[list->nextn++] = tree; + insert(op, tree->tr1, list); + insert(op, tree->tr2, list); + return; + } + tree = optim(tree); + if (tree->op == op) + goto ins; + if (!isfloat(tree)) { + /* c1*(x+c2) -> c1*x+c1*c2 */ + if ((tree->op==TIMES||tree->op==LSHIFT) + && tree->tr2->op==CON && tree->tr2->value>0 + && tree->tr1->op==PLUS && tree->tr1->tr2->op==CON) { + d = tree->tr2->value; + if (tree->op==TIMES) + tree->tr2->value =* tree->tr1->tr2->value; + else + tree->tr2->value = tree->tr1->tr2->value << d; + tree->tr1->tr2->value = d; + tree->tr1->op = tree->op; + tree->op = PLUS; + if (op==PLUS) + goto ins; + } + } + d = degree(tree); + for (i=0; inextl; i++) { + if ((d1=degree(list->llist[i]))llist[i]; + list->llist[i] = tree; + tree = t; + d = d1; + } + } + list->llist[list->nextl++] = tree; +} + +block(an, args) +{ + register int *p; + int *oldp; + register *argp, n; + + oldp = p = spacep; + n = an+3; + argp = &args; + do + *p++ = *argp++; + while (--n); + if (p >= &treespace[ossiz]) { + error("Exp. ov. pass 2"); + exit(1); + } + spacep = p; + return(oldp); +} + +islong(t) +{ + if (t==LONG) + return(2); + return(1); +} + +isconstant(at) +struct tnode *at; +{ + register struct tnode *t; + + t = at; + if (t->op==CON || t->op==SFCON) + return(t); + if (t->op==ITOL && t->tr1->op==CON) + return(t->tr1); + return(0); +} + +hardlongs(at) +struct tnode *at; +{ + register struct tnode *t; + + t = at; + switch(t->op) { + + case TIMES: + case DIVIDE: + case MOD: + t->op =+ LTIMES-TIMES; + break; + + case ASTIMES: + case ASDIV: + case ASMOD: + t->op =+ LASTIMES-ASTIMES; + t->tr1 = block(1, AMPER, LONG+PTR, 0, t->tr1); + break; + + default: + return(t); + } + return(optim(t)); +} diff --git a/source/c/c13.c b/source/c/c13.c new file mode 100644 index 0000000..49cf6a6 --- /dev/null +++ b/source/c/c13.c @@ -0,0 +1,227 @@ +int opdope[] { + 000000, /* EOF */ + 000000, /* ; */ + 000000, /* { */ + 000000, /* } */ + 036000, /* [ */ + 002000, /* ] */ + 036000, /* ( */ + 002000, /* ) */ + 014201, /* : */ + 007001, /* , */ + 000000, /* field selection */ + 000000, /* 11 */ + 000000, /* 12 */ + 000000, /* 13 */ + 000000, /* 14 */ + 000000, /* 15 */ + 000000, /* 16 */ + 000000, /* 17 */ + 000000, /* 18 */ + 000000, /* 19 */ + 000400, /* name */ + 000400, /* short constant */ + 000400, /* string */ + 000400, /* float */ + 000400, /* double */ + 000000, /* 25 */ + 000000, /* 26 */ + 000400, /* autoi, *r++ */ + 000400, /* autod, *--r */ + 000000, /* 29 */ + 034203, /* ++pre */ + 034203, /* --pre */ + 034203, /* ++post */ + 034203, /* --post */ + 034220, /* !un */ + 034202, /* &un */ + 034220, /* *un */ + 034200, /* -un */ + 034220, /* ~un */ + 036001, /* . (structure reference) */ + 030101, /* + */ + 030001, /* - */ + 032101, /* * */ + 032001, /* / */ + 032001, /* % */ + 026061, /* >> */ + 026061, /* << */ + 020161, /* & */ + 016161, /* | */ + 016161, /* ^ */ + 036001, /* -> */ + 001000, /* int -> double */ + 001000, /* double -> int */ + 000001, /* && */ + 000001, /* || */ + 030001, /* &~ */ + 001000, /* double -> long */ + 001000, /* long -> double */ + 001000, /* integer -> long */ + 001000, /* long -> integer */ + 022005, /* == */ + 022005, /* != */ + 024005, /* <= */ + 024005, /* < */ + 024005, /* >= */ + 024005, /* > */ + 024005, /*

p */ + 024005, /* >=p */ + 012213, /* =+ */ + 012213, /* =- */ + 012213, /* =* */ + 012213, /* =/ */ + 012213, /* =% */ + 012253, /* =>> */ + 012253, /* =<< */ + 012253, /* =& */ + 012253, /* =| */ + 012253, /* =^ */ + 012213, /* = */ + 030001, /* & for tests */ + 032101, /* * (long) */ + 032001, /* / (long) */ + 032001, /* % (long) */ + 012253, /* =& ~ */ + 012213, /* =* (long) */ + 012213, /* / (long) */ + 012213, /* % (long) */ + 000000, /* 89 */ + 014201, /* ? */ + 026061, /* long << */ + 012253, /* long =<< */ + 000000, /* 93 */ + 000000, /* 94 */ + 000000, /* 95 */ + 000000, /* 96 */ + 000000, /* 97 */ + 000000, /* 98 */ + 000000, /* 99 */ + 036001, /* call */ + 036000, /* mcall */ + 000000, /* goto */ + 000000, /* jump cond */ + 000000, /* branch cond */ + 000400, /* set nregs */ + 000000, /* 106 */ + 000000, /* 107 */ + 000000, /* 108 */ + 000000, /* 109 */ + 000000 /* force r0 */ +}; + +char *opntab[] { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ":", + ",", + "field select", + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + "name", + "short constant", + "string", + "float", + "double", + 0, + 0, + "*r++", + "*--r", + 0, + "++pre", + "--pre", + "++post", + "--post", + "!un", + "&", + "*", + "-", + "~", + ".", + "+", + "-", + "*", + "/", + "%", + ">>", + "<<", + "&", + "|", + "^", + "->", + "int->double", + "double->int", + "&&", + "||", + "&~", + "double->long", + "long->double", + "integer->long", + "long->integer", + "==", + "!=", + "<=", + "<", + ">=", + ">", + "p", + ">=p", + "=+", + "=-", + "=*", + "=/", + "=%", + "=>>", + "=<<", + "=&", + "=|", + "=^", + "=", + "& for tests", + "*", + "/", + "%", + "=& ~", + "=*", + "=/", + "=%", + 0, + "?", + "<<", + "=<<", + 0, + 0, + 0, + 0, + 0, + "call", + "call", + "call", + 0, + "goto", + "jump cond", + "branch cond", + "set nregs", + "load value", + 0, + 0, + 0, + "force register" +}; diff --git a/source/c/c1h.c b/source/c/c1h.c new file mode 100644 index 0000000..ea972a6 --- /dev/null +++ b/source/c/c1h.c @@ -0,0 +1,272 @@ +/* + * C pass 2 header + */ + +#define swsiz 200 +#define ossiz 500 + +struct tnode { + int op; + int type; + int degree; + struct tnode *tr1, *tr2; +}; + +struct bnode { + int bop; + struct tnode *btree; + int lbl; + int cond; +}; + +struct tname { + int nop; + int ntype; + int elsize; + char class; + char regno; + int offset; + int nloc; +}; + +/* + * for field selections + */ +struct tsel { + int op; + int type; + int degree; + struct tnode *tr1; + char flen; + char bitoffs; +}; + +struct tconst { + int cop; + int ctype; + int cdeg; + int value; +}; + +struct optab { + char tabdeg1; + char tabtyp1; + char tabdeg2; + char tabtyp2; + char *tabstring; +}; + +struct table { + int tabop; + struct optab *tabp; +}; + +struct instab { + int iop; + char *str1; + char *str2; +}; + +struct swtab { + int swlab; + int swval; +}; + +char maprel[]; +char notrel[]; +int nreg; +int isn; +int namsiz; +int line; +char ascbuf[518]; +int nerror; +struct table cctab[]; +struct table efftab[]; +struct table regtab[]; +struct table sptab[]; +struct table lsptab[]; +struct instab instab[]; +struct instab branchtab[]; +int opdope[]; +char *opntab[]; +int nstack; +int nfloat; +int *spacep; +int treespace[ossiz]; +int eolflg; +struct tconst czero, cone, fczero; + +/* + operators +*/ +#define EOF 0 +#define SEMI 1 +#define LBRACE 2 +#define RBRACE 3 +#define LBRACK 4 +#define RBRACK 5 +#define LPARN 6 +#define RPARN 7 +#define COLON 8 +#define COMMA 9 +#define FSEL 10 + +#define KEYW 19 +#define NAME 20 +#define CON 21 +#define STRING 22 +#define FCON 23 +#define SFCON 24 + +#define AUTOI 27 +#define AUTOD 28 +#define INCBEF 30 +#define DECBEF 31 +#define INCAFT 32 +#define DECAFT 33 +#define EXCLA 34 +#define AMPER 35 +#define STAR 36 +#define NEG 37 +#define COMPL 38 + +#define DOT 39 +#define PLUS 40 +#define MINUS 41 +#define TIMES 42 +#define DIVIDE 43 +#define MOD 44 +#define RSHIFT 45 +#define LSHIFT 46 +#define AND 47 +#define NAND 55 +#define OR 48 +#define EXOR 49 +#define ARROW 50 +#define ITOF 51 +#define FTOI 52 +#define LOGAND 53 +#define LOGOR 54 +#define FTOL 56 +#define LTOF 57 +#define ITOL 58 +#define LTOI 59 + +#define EQUAL 60 +#define NEQUAL 61 +#define LESSEQ 62 +#define LESS 63 +#define GREATEQ 64 +#define GREAT 65 +#define LESSEQP 66 +#define LESSP 67 +#define GREATQP 68 +#define GREATP 69 + +#define ASPLUS 70 +#define ASMINUS 71 +#define ASTIMES 72 +#define ASDIV 73 +#define ASMOD 74 +#define ASRSH 75 +#define ASLSH 76 +#define ASSAND 77 +#define ASOR 78 +#define ASXOR 79 +#define ASSIGN 80 +#define TAND 81 +#define LTIMES 82 +#define LDIV 83 +#define LMOD 84 +#define ASSNAND 85 +#define LASTIMES 86 +#define LASDIV 87 +#define LASMOD 88 + +#define QUEST 90 +#define LLSHIFT 91 +#define ASLSHL 92 +#define CALL1 98 +#define CALL2 99 +#define CALL 100 +#define MCALL 101 +#define JUMP 102 +#define CBRANCH 103 +#define INIT 104 +#define SETREG 105 +#define LOAD 106 +#define RFORCE 110 + +/* + * Intermediate code operators + */ +#define BRANCH 111 +#define LABEL 112 +#define NLABEL 113 +#define RLABEL 114 +#define BDATA 200 +#define WDATA 201 +#define PROG 202 +#define DATA 203 +#define BSS 204 +#define CSPACE 205 +#define SSPACE 206 +#define SYMDEF 207 +#define SAVE 208 +#define RETRN 209 +#define EVEN 210 +#define PROFIL 212 +#define SWIT 213 +#define EXPR 214 +#define SNAME 215 +#define RNAME 216 +#define ANAME 217 +#define NULL 218 + +/* + * types + */ +#define INT 0 +#define CHAR 1 +#define FLOAT 2 +#define DOUBLE 3 +#define STRUCT 4 +#define RSTRUCT 5 +#define LONG 6 + +#define TYLEN 2 +#define TYPE 07 +#define XTYPE (03<<3) +#define PTR 010 +#define FUNC 020 +#define ARRAY 030 + +/* + storage classes +*/ +#define KEYWC 1 +#define MOS 10 +#define AUTO 11 +#define EXTERN 12 +#define STATIC 13 +#define REG 14 +#define STRTAG 15 +#define ARG 16 +#define OFFS 20 +#define XOFFS 21 +#define SOFFS 22 + +/* + Flag bits +*/ + +#define BINARY 01 +#define LVALUE 02 +#define RELAT 04 +#define ASSGOP 010 +#define LWORD 020 +#define RWORD 040 +#define COMMUTE 0100 +#define RASSOC 0200 +#define LEAF 0400 +#define CNVRT 01000 diff --git a/source/c/c1t.s b/source/c/c1t.s new file mode 100644 index 0000000..8cc6ca6 --- /dev/null +++ b/source/c/c1t.s @@ -0,0 +1,85 @@ +/ C operator tables + +.globl fltused; fltused=. +.globl _instab +.globl _branchtab + +.data +_instab: + 80.; 1f; 2f; .text; 1:; 2:; .data + 60.; 1f; 2f; .text; 1: ; 2: ; .data + 106.; 1b; 2b + 61.; 1b; 2b + 62.; 1b; 2b + 63.; 1b; 2b + 64.; 1b; 2b + 65.; 1b; 2b + 66.; 1b; 2b + 67.; 1b; 2b + 68.; 1b; 2b + 69.; 1b; 2b + 40.; 1f; 3f; .text; 1:; .data + 70.; 1b; 3f + 41.; 2f; 4f; .text; 2:; .data + 71.; 2b; 4f + 30.; 1b; 3f; .text; 3:; .data + 31.; 2b; 4f; .text; 4:; .data + 32.; 1b; 3b + 33.; 2b; 4b + 42.; 5f; 5f; .text; 5:; .data + 72.; 5b; 5b + 43.; 6f; 6f; .text; 6:; .data + 73.; 6b; 6b + 44.; 5b; 6b + 74.; 5b; 6b + 45.; 5f; 6f; .text; 6:; .data + 75.; 5f; 6b + 46.; 5f; 6f; .text; 5:; 6:; .data + 76.; 5b; 6b + 47.; 5f; 5f; .text; 5:; 6:; .data + 55.; 5b; 6b + 85.; 5b; 6b + 81.; 5f; 6f; .text; 5:; 6:; .data + 48.; 5f; 6f; .text; 5:; 6:; .data + 78.; 5b; 6b + 49.; 5f; 5f; .text; 5:; .data + 79.; 5b; 5b + 37.; 1f; 1f; .text; 1:; .data + 38.; 1f; 1f; .text; 1:; .data + + 98.; 1f; 1f; .text; 1:<*$\0>; .data + 99.; 1b+2; 1b+2 + 91.; 1f; 1f; .text; 1: ; .data + 92.; 1b; 1b + 82.; 1f; 1f; .text; 1:; .data + 83.; 1f; 1f; .text; 1:; .data + 84.; 1f; 1f; .text; 1:; .data + 86.; 1f; 1f; .text; 1:; .data + 87.; 1f; 1f; .text; 1:; .data + 88.; 1f; 1f; .text; 1:; .data + 0 + +.data +_branchtab: + 60.; 0f; 1f; .text; 0:; 1:; .data + 61.; 1b; 0b + 62.; 2f; 5f; .text; 2:; 5:; .data + 63.; 3f; 4f; .text; 3:; 4:; .data + 64.; 4b; 3b + 65.; 5b; 2b + 66.; 6f; 9f; .text; 6:; 9:; .data + 67.; 7f; 8f; .text; 7:; 8:; .data + 68.; 8b; 7b + 69.; 9b; 6b + + 260.; 0b; 1b + 261.; 1b; 0b + 262.; 2b; 5b + 263.; 3b; 4b + 264.; 4b; 3b + 265.; 5b; 2b + 266.; 0b; 1b + 267.; 7f; 8f; .text; 7:; 8:; .data + 268.; 8b; 7b + 269.; 1b; 0b + 0 diff --git a/source/c/c20.c b/source/c/c20.c new file mode 100644 index 0000000..d06571f --- /dev/null +++ b/source/c/c20.c @@ -0,0 +1,673 @@ +# +/* + * C object code improver + */ + +#include "c2h.c" + +struct optab optab[] { + "jbr", JBR, + "jeq", CBR | JEQ<<8, + "jne", CBR | JNE<<8, + "jle", CBR | JLE<<8, + "jge", CBR | JGE<<8, + "jlt", CBR | JLT<<8, + "jgt", CBR | JGT<<8, + "jlo", CBR | JLO<<8, + "jhi", CBR | JHI<<8, + "jlos", CBR | JLOS<<8, + "jhis", CBR | JHIS<<8, + "jmp", JMP, + ".globl",EROU, + "mov", MOV, + "clr", CLR, + "com", COM, + "inc", INC, + "dec", DEC, + "neg", NEG, + "tst", TST, + "asr", ASR, + "asl", ASL, + "sxt", SXT, + "cmp", CMP, + "add", ADD, + "sub", SUB, + "bit", BIT, + "bic", BIC, + "bis", BIS, + "mul", MUL, + "ash", ASH, + "xor", XOR, + ".text",TEXT, + ".data",DATA, + ".bss", BSS, + ".even",EVEN, + "movf", MOVF, + "movof",MOVOF, + "movfo",MOVFO, + "addf", ADDF, + "subf", SUBF, + "divf", DIVF, + "mulf", MULF, + "clrf", CLRF, + "cmpf", CMPF, + "negf", NEGF, + "tstf", TSTF, + "cfcc", CFCC, + "sob", SOB, + "jsr", JSR, + ".end", END, + 0, 0}; + +char revbr[] { JNE, JEQ, JGT, JLT, JGE, JLE, JHIS, JLOS, JHI, JLO }; +int isn 20000; + +main(argc, argv) +char **argv; +{ + register int niter, maxiter, isend; + extern end; + extern fin, fout; + int nflag; + + if (argc>1 && argv[1][0]=='+') { + argc--; + argv++; + debug++; + } + if (argc>1 && argv[1][0]=='-') { + argc--; + argv++; + nflag++; + } + if (argc>1) { + if ((fin = open(argv[1], 0)) < 0) { + printf("C2: can't find %s\n", argv[1]); + exit(1); + } + } else + fin = dup(0); + if (argc>2) { + if ((fout = creat(argv[2], 0666)) < 0) { + fout = 1; + printf("C2: can't create %s\n", argv[2]); + exit(1); + } + } else + fout = dup(1); + lasta = firstr = lastr = sbrk(2); + maxiter = 0; + opsetup(); + do { + isend = input(); + movedat(); + niter = 0; + do { + refcount(); + do { + iterate(); + clearreg(); + niter++; + } while (nchange); + comjump(); + rmove(); + } while (nchange || jumpsw()); + addsob(); + output(); + if (niter > maxiter) + maxiter = niter; + lasta = firstr; + } while (isend); + flush(); + fout = 2; + if (nflag) { + printf("%d iterations\n", maxiter); + printf("%d jumps to jumps\n", nbrbr); + printf("%d inst. after jumps\n", iaftbr); + printf("%d jumps to .+2\n", njp1); + printf("%d redundant labels\n", nrlab); + printf("%d cross-jumps\n", nxjump); + printf("%d code motions\n", ncmot); + printf("%d branches reversed\n", nrevbr); + printf("%d redundant moves\n", redunm); + printf("%d simplified addresses\n", nsaddr); + printf("%d loops inverted\n", loopiv); + printf("%d redundant jumps\n", nredunj); + printf("%d common seqs before jmp's\n", ncomj); + printf("%d skips over jumps\n", nskip); + printf("%d sob's added\n", nsob); + printf("%d redundant tst's\n", nrtst); + printf("%d literals eliminated\n", nlit); + printf("%dK core\n", ((lastr+01777)>>10)&077); + flush(); + } + exit(0); +} + +input() +{ + register struct node *p, *lastp; + register int op; + + lastp = &first; + for (;;) { + op = getline(); + switch (op.op) { + + case LABEL: + p = alloc(sizeof first); + if (line[0] == 'L') { + p->combop = LABEL; + p->labno = getnum(line+1); + p->code = 0; + } else { + p->combop = DLABEL; + p->labno = 0; + p->code = copy(line); + } + break; + + case JBR: + case CBR: + case JMP: + case JSW: + p = alloc(sizeof first); + p->combop = op; + if (*curlp=='L' && (p->labno = getnum(curlp+1))) + p->code = 0; + else { + p->labno = 0; + p->code = copy(curlp); + } + break; + + default: + p = alloc(sizeof first); + p->combop = op; + p->labno = 0; + p->code = copy(curlp); + break; + + } + p->forw = 0; + p->back = lastp; + lastp->forw = p; + lastp = p; + p->ref = 0; + if (op==EROU) + return(1); + if (op==END) + return(0); + } +} + +getline() +{ + register char *lp; + register c; + + lp = line; + while (c = getchar()) { + if (c==':') { + *lp++ = 0; + return(LABEL); + } + if (c=='\n') { + *lp++ = 0; + return(oplook()); + } + *lp++ = c; + } + *lp++ = 0; + return(END); +} + +getnum(ap) +char *ap; +{ + register char *p; + register n, c; + + p = ap; + n = 0; + while ((c = *p++) >= '0' && c <= '9') + n = n*10 + c - '0'; + if (*--p != 0) + return(0); + return(n); +} + +output() +{ + register struct node *t; + register struct optab *op; + register int byte; + + t = &first; + while (t = t->forw) switch (t->op) { + + case END: + return; + + case LABEL: + printf("L%d:", t->labno); + continue; + + case DLABEL: + printf("%s:", t->code); + continue; + + default: + if ((byte = t->subop) == BYTE) + t->subop = 0; + for (op = optab; op->opstring!=0; op++) + if (op->opcode == t->combop) { + printf("%s", op->opstring); + if (byte==BYTE) + printf("b"); + break; + } + if (t->code) { + reducelit(t); + printf("\t%s\n", t->code); + } else if (t->op==JBR || t->op==CBR) + printf("\tL%d\n", t->labno); + else + printf("\n"); + continue; + + case JSW: + printf("L%d\n", t->labno); + continue; + + case SOB: + printf("sob %s,L%d\n", t->code, t->labno); + continue; + + case 0: + if (t->code) + printf("%s", t->code); + printf("\n"); + continue; + } +} + +/* + * Notice addresses of the form + * $xx,xx(r) + * and replace them with (pc),xx(r) + * -- Thanx and a tip of the Hatlo hat to Bliss-11. + */ +reducelit(at) +struct node *at; +{ + register char *c1, *c2; + char *c2s; + register struct node *t; + + t = at; + if (*t->code != '$') + return; + c1 = t->code; + while (*c1 != ',') + if (*c1++ == '\0') + return; + c2s = c1; + c1++; + if (*c1=='*') + c1++; + c2 = t->code+1; + while (*c1++ == *c2++); + if (*--c1!='(' || *--c2!=',') + return; + t->code = copy("(pc)", c2s); + nlit++; +} + +copy(ap) +char *ap; +{ + register char *p, *np; + char *onp; + register n; + int na; + + na = nargs(); + p = ap; + n = 0; + if (*p==0) + return(0); + do + n++; + while (*p++); + if (na>1) { + p = (&ap)[1]; + while (*p++) + n++; + } + onp = np = alloc(n); + p = ap; + while (*np++ = *p++); + if (na>1) { + p = (&ap)[1]; + np--; + while (*np++ = *p++); + } + return(onp); +} + +opsetup() +{ + register struct optab *optp, **ophp; + register char *p; + + for (optp = optab; p = optp->opstring; optp++) { + ophp = &ophash[(((p[0]<<3)+(p[1]<<1)+p[2])&077777) % OPHS]; + while (*ophp++) + if (ophp > &ophash[OPHS]) + ophp = ophash; + *--ophp = optp; + } +} + +oplook() +{ + register struct optab *optp; + register char *lp, *op; + static char tmpop[32]; + struct optab **ophp; + + op = tmpop; + for (lp = line; *lp && *lp!=' ' && *lp!='\t';) + *op++ = *lp++; + *op++ = 0; + while (*lp=='\t' || *lp==' ') + lp++; + curlp = lp; + ophp = &ophash[(((tmpop[0]<<3)+(tmpop[1]<<1)+tmpop[2])&077777) % OPHS]; + while (optp = *ophp) { + op = optp->opstring; + lp = tmpop; + while (*lp == *op++) + if (*lp++ == 0) + return(optp->opcode); + if (*lp++=='b' && *lp++==0 && *--op==0) + return(optp->opcode + (BYTE<<8)); + ophp++; + if (ophp >= &ophash[OPHS]) + ophp = ophash; + } + if (line[0]=='L') { + lp = &line[1]; + while (*lp) + if (*lp<'0' || *lp++>'9') + return(0); + curlp = line; + return(JSW); + } + curlp = line; + return(0); +} + +refcount() +{ + register struct node *p, *lp; + static struct node *labhash[LABHS]; + register struct node **hp; + + for (hp = labhash; hp < &labhash[LABHS];) + *hp++ = 0; + for (p = first.forw; p!=0; p = p->forw) + if (p->op==LABEL) { + labhash[p->labno % LABHS] = p; + p->refc = 0; + } + for (p = first.forw; p!=0; p = p->forw) { + if (p->op==JBR || p->op==CBR || p->op==JSW) { + p->ref = 0; + lp = labhash[p->labno % LABHS]; + if (lp==0 || p->labno!=lp->labno) + for (lp = first.forw; lp!=0; lp = lp->forw) { + if (lp->op==LABEL && p->labno==lp->labno) + break; + } + if (lp) { + hp = nonlab(lp)->back; + if (hp!=lp) { + p->labno = hp->labno; + lp = hp; + } + p->ref = lp; + lp->refc++; + } + } + } + for (p = first.forw; p!=0; p = p->forw) + if (p->op==LABEL && p->refc==0 + && (lp = nonlab(p))->op && lp->op!=JSW) + decref(p); +} + +iterate() +{ + register struct node *p, *rp, *p1; + + nchange = 0; + for (p = first.forw; p!=0; p = p->forw) { + if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) { + rp = nonlab(p->ref); + if (rp->op==JBR && rp->labno && p!=rp) { + nbrbr++; + p->labno = rp->labno; + decref(p->ref); + rp->ref->refc++; + p->ref = rp->ref; + nchange++; + } + } + if (p->op==CBR && (p1 = p->forw)->op==JBR) { + rp = p->ref; + do + rp = rp->back; + while (rp->op==LABEL); + if (rp==p1) { + decref(p->ref); + p->ref = p1->ref; + p->labno = p1->labno; + p1->forw->back = p; + p->forw = p1->forw; + p->subop = revbr[p->subop]; + nchange++; + nskip++; + } + } + if (p->op==JBR || p->op==JMP) { + while (p->forw && p->forw->op!=LABEL + && p->forw->op!=EROU && p->forw->op!=END) { + nchange++; + iaftbr++; + if (p->forw->ref) + decref(p->forw->ref); + p->forw = p->forw->forw; + p->forw->back = p; + } + rp = p->forw; + while (rp && rp->op==LABEL) { + if (p->ref == rp) { + p->back->forw = p->forw; + p->forw->back = p->back; + p = p->back; + decref(rp); + nchange++; + njp1++; + break; + } + rp = rp->forw; + } + xjump(p); + p = codemove(p); + } + } +} + +xjump(ap) +{ + register int *p1, *p2, *p3; + int nxj; + + nxj = 0; + p1 = ap; + if ((p2 = p1->ref)==0) + return(0); + for (;;) { + while ((p1 = p1->back) && p1->op==LABEL); + while ((p2 = p2->back) && p2->op==LABEL); + if (!equop(p1, p2) || p1==p2) + return(nxj); + p3 = insertl(p2); + p1->combop = JBR; + p1->ref = p3; + p1->labno = p3->labno; + p1->code = 0; + nxj++; + nxjump++; + nchange++; + } +} + +insertl(ap) +struct node *ap; +{ + register struct node *lp, *op; + + op = ap; + if (op->op == LABEL) { + op->refc++; + return(op); + } + if (op->back->op == LABEL) { + op = op->back; + op->refc++; + return(op); + } + lp = alloc(sizeof first); + lp->combop = LABEL; + lp->labno = isn++; + lp->ref = 0; + lp->code = 0; + lp->refc = 1; + lp->back = op->back; + lp->forw = op; + op->back->forw = lp; + op->back = lp; + return(lp); +} + +codemove(ap) +struct node *ap; +{ + register struct node *p1, *p2, *p3; + struct node *t, *tl; + int n; + + p1 = ap; + if (p1->op!=JBR || (p2 = p1->ref)==0) + return(p1); + while (p2->op == LABEL) + if ((p2 = p2->back) == 0) + return(p1); + if (p2->op!=JBR && p2->op!=JMP) + goto ivloop; + p2 = p2->forw; + p3 = p1->ref; + while (p3) { + if (p3->op==JBR || p3->op==JMP) { + if (p1==p3) + return(p1); + ncmot++; + nchange++; + p1->back->forw = p2; + p1->forw->back = p3; + p2->back->forw = p3->forw; + p3->forw->back = p2->back; + p2->back = p1->back; + p3->forw = p1->forw; + decref(p1->ref); + return(p2); + } else + p3 = p3->forw; + } + return(p1); +ivloop: + if (p1->forw->op!=LABEL) + return(p1); + p3 = p2 = p2->forw; + n = 16; + do { + if ((p3 = p3->forw) == 0 || p3==p1 || --n==0) + return(p1); + } while (p3->op!=CBR || p3->labno!=p1->forw->labno); + do + if ((p1 = p1->back) == 0) + return(ap); + while (p1!=p3); + p1 = ap; + tl = insertl(p1); + p3->subop = revbr[p3->subop]; + decref(p3->ref); + p2->back->forw = p1; + p3->forw->back = p1; + p1->back->forw = p2; + p1->forw->back = p3; + t = p1->back; + p1->back = p2->back; + p2->back = t; + t = p1->forw; + p1->forw = p3->forw; + p3->forw = t; + p2 = insertl(p1->forw); + p3->labno = p2->labno; + p3->ref = p2; + decref(tl); + if (tl->refc<=0) + nrlab--; + loopiv++; + nchange++; + return(p3); +} + +comjump() +{ + register struct node *p1, *p2, *p3; + + for (p1 = first.forw; p1!=0; p1 = p1->forw) + if (p1->op==JBR && (p2 = p1->ref) && p2->refc > 1) + for (p3 = p1->forw; p3!=0; p3 = p3->forw) + if (p3->op==JBR && p3->ref == p2) + backjmp(p1, p3); +} + +backjmp(ap1, ap2) +struct node *ap1, *ap2; +{ + register struct node *p1, *p2, *p3; + + p1 = ap1; + p2 = ap2; + for(;;) { + while ((p1 = p1->back) && p1->op==LABEL); + p2 = p2->back; + if (equop(p1, p2)) { + p3 = insertl(p1); + p2->back->forw = p2->forw; + p2->forw->back = p2->back; + p2 = p2->forw; + decref(p2->ref); + p2->labno = p3->labno; + p2->ref = p3; + nchange++; + ncomj++; + } else + return; + } +} diff --git a/source/c/c21.c b/source/c/c21.c new file mode 100644 index 0000000..a423f3a --- /dev/null +++ b/source/c/c21.c @@ -0,0 +1,659 @@ +# +/* + * C object code improver-- second part + */ + +#include "c2h.c" + +rmove() +{ + register struct node *p; + register char *cp; + register int r; + int r1, flt; + + for (p=first.forw; p!=0; p = p->forw) { + if (debug) { + for (r=0; r<2*NREG; r++) + if (regs[r][0]) + printf("%d: %s\n", r, regs[r]); + printf("-\n"); + } + flt = 0; + switch (p->op) { + + case MOVF: + case MOVFO: + case MOVOF: + flt = NREG; + + case MOV: + if (p->subop==BYTE) + goto badmov; + dualop(p); + if ((r = findrand(regs[RT1], flt)) >= 0) { + if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR) { + p->forw->back = p->back; + p->back->forw = p->forw; + redunm++; + continue; + } + } + repladdr(p, 0, flt); + r = isreg(regs[RT1]); + r1 = isreg(regs[RT2]); + dest(regs[RT2], flt); + if (r >= 0) + if (r1 >= 0) + savereg(r1+flt, regs[r+flt]); + else + savereg(r+flt, regs[RT2]); + else + if (r1 >= 0) + savereg(r1+flt, regs[RT1]); + else + setcon(regs[RT1], regs[RT2]); + source(regs[RT1]); + setcc(regs[RT2]); + continue; + + case ADDF: + case SUBF: + case DIVF: + case MULF: + flt = NREG; + + case ADD: + case SUB: + case BIC: + case BIS: + case MUL: + case DIV: + case ASH: + badmov: + dualop(p); + repladdr(p, 0, flt); + source(regs[RT1]); + dest(regs[RT2], flt); + if (p->op==DIV && (r = isreg(regs[RT2])>=0)) + regs[r+1][0] = 0; + ccloc[0] = 0; + continue; + + case CLRF: + case NEGF: + flt = NREG; + + case CLR: + case COM: + case INC: + case DEC: + case NEG: + case ASR: + case ASL: + case SXT: + singop(p); + dest(regs[RT1], flt); + if (p->op==CLR && flt==0) + if ((r = isreg(regs[RT1])) >= 0) + savereg(r, "$0"); + else + setcon("$0", regs[RT1]); + setcc(regs[RT1]); + continue; + + case TSTF: + flt = NREG; + + case TST: + singop(p); + repladdr(p, 0, flt); + source(regs[RT1]); + if (equstr(regs[RT1], ccloc)) { + p->back->forw = p->forw; + p->forw->back = p->back; + p = p->back; + nrtst++; + nchange++; + } + continue; + + case CMPF: + flt = NREG; + + case CMP: + case BIT: + dualop(p); + source(regs[RT1]); + source(regs[RT2]); + repladdr(p, 1, flt); + ccloc[0] = 0; + continue; + + case CBR: + case CFCC: + ccloc[0] = 0; + continue; + + case JBR: + redunbr(p); + + default: + clearreg(); + } + } +} + +jumpsw() +{ + register struct node *p, *p1; + register t; + int nj; + + t = 0; + nj = 0; + for (p=first.forw; p!=0; p = p->forw) + p->refc = ++t; + for (p=first.forw; p!=0; p = p1) { + p1 = p->forw; + if (p->op == CBR && p1->op==JBR && p->ref && p1->ref + && abs(p->refc - p->ref->refc) > abs(p1->refc - p1->ref->refc)) { + p->subop = revbr[p->subop]; + t = p1->ref; + p1->ref = p->ref; + p->ref = t; + t = p1->labno; + p1->labno = p->labno; + p->labno = t; + nrevbr++; + nj++; + } + } + return(nj); +} + +addsob() +{ + register struct node *p, *p1; + + for (p = &first; (p1 = p->forw)!=0; p = p1) { + if (p->op==DEC && isreg(p->code)>=0 + && p1->combop==(CBR|JNE<<8)) { + if (p->refc < p1->ref->refc) + continue; + if (p->refc - p1->ref->refc > 50) + continue; + p->labno = p1->labno; + p->combop = SOB; + p1->forw->back = p; + p->forw = p1->forw; + nsob++; + } + } +} + +abs(x) +{ + return(x<0? -x: x); +} + +equop(ap1, p2) +struct node *ap1, *p2; +{ + register char *cp1, *cp2; + register struct node *p1; + + p1 = ap1; + if (p1->combop != p2->combop) + return(0); + if (p1->op>0 && p1->opcode; + cp2 = p2->code; + if (cp1==0 && cp2==0) + return(1); + if (cp1==0 || cp2==0) + return(0); + while (*cp1 == *cp2++) + if (*cp1++ == 0) + return(1); + return(0); +} + +decref(ap) +{ + register struct node *p; + + p = ap; + if (--p->refc <= 0) { + nrlab++; + p->back->forw = p->forw; + p->forw->back = p->back; + } +} + +nonlab(ap) +struct node *ap; +{ + register struct node *p; + + p = ap; + while (p && p->op==LABEL) + p = p->forw; + return(p); +} + +alloc(an) +{ + register int n; + register char *p; + + n = an; + n++; + n =& ~01; + if (lasta+n >= lastr) { + if (sbrk(2000) == -1) { + write(2, "Optimizer: out of space\n", 14); + exit(1); + } + lastr =+ 2000; + } + p = lasta; + lasta =+ n; + return(p); +} + +clearreg() +{ + register int i; + + for (i=0; i<2*NREG; i++) + regs[i][0] = '\0'; + conloc[0] = 0; + ccloc[0] = 0; +} + +savereg(ai, as) +char *as; +{ + register char *p, *s, *sp; + + sp = p = regs[ai]; + s = as; + if (source(s)) + return; + while (*p++ = *s) { + if (s[0]=='(' && s[1]=='r' && s[2]<'5') { + *sp = 0; + return; + } + if (*s++ == ',') + break; + } + *--p = '\0'; +} + +dest(as, flt) +char *as; +{ + register char *s; + register int i; + + s = as; + if ((i = isreg(s)) >= 0) + regs[i+flt][0] = 0; + while ((i = findrand(s, flt)) >= 0) + regs[i][0] = 0; + while (*s) { + if ((*s=='(' && (*(s+1)!='r' || *(s+2)!='5')) || *s++=='*') { + for (i=flt; icode; + p2 = regs[RT1]; + while (*p2++ = *p1++); + regs[RT2][0] = 0; +} + + +dualop(ap) +struct node *ap; +{ + register char *p1, *p2; + register struct node *p; + + p = ap; + p1 = p->code; + p2 = regs[RT1]; + while (*p1 && *p1!=',') + *p2++ = *p1++; + *p2++ = 0; + p2 = regs[RT2]; + *p2 = 0; + if (*p1++ !=',') + return; + while (*p2++ = *p1++); +} + +findrand(as, flt) +char *as; +{ + register int i; + for (i = flt; i='0' && s[1]<='4' && s[2]==0) + return(s[1]-'0'); + return(-1); +} + +check() +{ + register struct node *p, *lp; + + lp = &first; + for (p=first.forw; p!=0; p = p->forw) { + if (p->back != lp) + abort(); + lp = p; + } +} + +source(ap) +char *ap; +{ + register char *p1, *p2; + + p1 = ap; + p2 = p1; + if (*p1==0) + return(0); + while (*p2++); + if (*p1=='-' && *(p1+1)=='(' + || *p1=='*' && *(p1+1)=='-' && *(p1+2)=='(' + || *(p2-2)=='+') { + while (*p1 && *p1++!='r'); + if (*p1>='0' && *p1<='4') + regs[*p1 - '0'][0] = 0; + return(1); + } + return(0); +} + +repladdr(p, f, flt) +struct node *p; +{ + register r; + int r1; + register char *p1, *p2; + static char rt1[50], rt2[50]; + + if (f) + r1 = findrand(regs[RT2], flt); + else + r1 = -1; + r = findrand(regs[RT1], flt); + if (r1 >= NREG) + r1 =- NREG; + if (r >= NREG) + r =- NREG; + if (r>=0 || r1>=0) { + p2 = regs[RT1]; + for (p1 = rt1; *p1++ = *p2++;); + if (regs[RT2][0]) { + p1 = rt2; + *p1++ = ','; + for (p2 = regs[RT2]; *p1++ = *p2++;); + } else + rt2[0] = 0; + if (r>=0) { + rt1[0] = 'r'; + rt1[1] = r + '0'; + rt1[2] = 0; + nsaddr++; + } + if (r1>=0) { + rt2[1] = 'r'; + rt2[2] = r1 + '0'; + rt2[3] = 0; + nsaddr++; + } + p->code = copy(rt1, rt2); + } +} + +movedat() +{ + register struct node *p1, *p2; + struct node *p3; + register seg; + struct node data; + struct node *datp; + + if (first.forw == 0) + return; + datp = &data; + for (p1 = first.forw; p1!=0; p1 = p1->forw) { + if (p1->op == DATA) { + p2 = p1->forw; + while (p2 && p2->op!=TEXT) + p2 = p2->forw; + if (p2==0) + break; + p3 = p1->back; + p1->back->forw = p2->forw; + p2->forw->back = p3; + p2->forw = 0; + datp->forw = p1; + p1->back = datp; + p1 = p3; + datp = p2; + } + } + if (data.forw) { + datp->forw = first.forw; + first.forw->back = datp; + data.forw->back = &first; + first.forw = data.forw; + } + seg = -1; + for (p1 = first.forw; p1!=0; p1 = p1->forw) { + if (p1->op==TEXT||p1->op==DATA||p1->op==BSS) { + if (p1->op == seg || p1->forw&&p1->forw->op==seg) { + p1->back->forw = p1->forw; + p1->forw->back = p1->back; + p1 = p1->back; + continue; + } + seg = p1->op; + } + } +} + +redunbr(ap) +struct node *ap; +{ + register struct node *p, *p1; + register char *ap1; + char *ap2; + + if ((p1 = p->ref) == 0) + return; + p1 = nonlab(p1); + if (p1->op==TST) { + singop(p1); + savereg(RT2, "$0"); + } else if (p1->op==CMP) + dualop(p1); + else + return; + if (p1->forw->op!=CBR) + return; + ap1 = findcon(RT1); + ap2 = findcon(RT2); + p1 = p1->forw; + if (compare(p1->subop, ap1, ap2)) { + nredunj++; + nchange++; + decref(p->ref); + p->ref = p1->ref; + p->labno = p1->labno; + p->ref->refc++; + } +} + +findcon(i) +{ + register char *p; + register r; + + p = regs[i]; + if (*p=='$') + return(p); + if ((r = isreg(p)) >= 0) + return(regs[r]); + if (equstr(p, conloc)) + return(conval); + return(p); +} + +compare(op, acp1, acp2) +char *acp1, *acp2; +{ + register char *cp1, *cp2; + register n1; + int n2; + struct { int i;}; + + cp1 = acp1; + cp2 = acp2; + if (*cp1++ != '$' || *cp2++ != '$') + return(0); + n1 = 0; + while (*cp2 >= '0' && *cp2 <= '7') { + n1 =<< 3; + n1 =+ *cp2++ - '0'; + } + n2 = n1; + n1 = 0; + while (*cp1 >= '0' && *cp1 <= '7') { + n1 =<< 3; + n1 =+ *cp1++ - '0'; + } + if (*cp1=='+') + cp1++; + if (*cp2=='+') + cp2++; + do { + if (*cp1++ != *cp2) + return(0); + } while (*cp2++); + cp1 = n1; + cp2 = n2; + switch(op) { + + case JEQ: + return(cp1 == cp2); + case JNE: + return(cp1 != cp2); + case JLE: + return(cp1.i <= cp2.i); + case JGE: + return(cp1.i >= cp2.i); + case JLT: + return(cp1.i < cp2.i); + case JGT: + return(cp1.i > cp2.i); + case JLO: + return(cp1 < cp2); + case JHI: + return(cp1 > cp2); + case JLOS: + return(cp1 <= cp2); + case JHIS: + return(cp1 >= cp2); + } + return(0); +} + +setcon(ar1, ar2) +char *ar1, *ar2; +{ + register char *cl, *cv, *p; + + cl = ar2; + cv = ar1; + if (*cv != '$') + return; + if (!natural(cl)) + return; + p = conloc; + while (*p++ = *cl++); + p = conval; + while (*p++ = *cv++); +} + +equstr(ap1, ap2) +char *ap1, *ap2; +{ + char *p1, *p2; + + p1 = ap1; + p2 = ap2; + do { + if (*p1++ != *p2) + return(0); + } while (*p2++); + return(1); +} + +setcc(ap) +char *ap; +{ + register char *p, *p1; + + p = ap; + if (!natural(p)) { + ccloc[0] = 0; + return; + } + p1 = ccloc; + while (*p1++ = *p++); +} + +natural(ap) +char *ap; +{ + register char *p; + + p = ap; + if (*p=='*' || *p=='(' || *p=='-'&&*(p+1)=='(') + return(0); + while (*p++); + p--; + if (*--p == '+' || *p ==')' && *--p != '5') + return(0); + return(1); +} diff --git a/source/c/c2h.c b/source/c/c2h.c new file mode 100644 index 0000000..3f37a00 --- /dev/null +++ b/source/c/c2h.c @@ -0,0 +1,125 @@ +/* + * Header for object code improver + */ + +#define JBR 1 +#define CBR 2 +#define JMP 3 +#define LABEL 4 +#define DLABEL 5 +#define EROU 7 +#define JSW 9 +#define MOV 10 +#define CLR 11 +#define COM 12 +#define INC 13 +#define DEC 14 +#define NEG 15 +#define TST 16 +#define ASR 17 +#define ASL 18 +#define SXT 19 +#define CMP 20 +#define ADD 21 +#define SUB 22 +#define BIT 23 +#define BIC 24 +#define BIS 25 +#define MUL 26 +#define DIV 27 +#define ASH 28 +#define XOR 29 +#define TEXT 30 +#define DATA 31 +#define BSS 32 +#define EVEN 33 +#define MOVF 34 +#define MOVOF 35 +#define MOVFO 36 +#define ADDF 37 +#define SUBF 38 +#define DIVF 39 +#define MULF 40 +#define CLRF 41 +#define CMPF 42 +#define NEGF 43 +#define TSTF 44 +#define CFCC 45 +#define SOB 46 +#define JSR 47 +#define END 48 + +#define JEQ 0 +#define JNE 1 +#define JLE 2 +#define JGE 3 +#define JLT 4 +#define JGT 5 +#define JLO 6 +#define JHI 7 +#define JLOS 8 +#define JHIS 9 + +#define BYTE 100 + +struct node { + char op; + char subop; + struct node *forw; + struct node *back; + struct node *ref; + int labno; + char *code; + int refc; +}; + +struct { + int combop; +}; + +struct optab { + char *opstring; + int opcode; +} optab[]; + +char line[512]; +struct node first; +char *curlp; +int nbrbr; +int nsaddr; +int redunm; +int iaftbr; +int njp1; +int nrlab; +int nxjump; +int ncmot; +int nrevbr; +int loopiv; +int nredunj; +int nskip; +int ncomj; +int nsob; +int nrtst; +int nlit; + +int nchange; +int isn; +int debug; +char *lasta; +char *lastr; +char *firstr; +char revbr[]; +char regs[12][20]; +char conloc[20]; +char conval[20]; +char ccloc[20]; + +#define RT1 10 +#define RT2 11 +#define FREG 5 +#define NREG 5 +#define LABHS 127 +#define OPHS 57 + +struct optab *ophash[OPHS]; +struct { char lbyte; }; diff --git a/source/c/cvopt.c b/source/c/cvopt.c new file mode 100644 index 0000000..5b1c3d6 --- /dev/null +++ b/source/c/cvopt.c @@ -0,0 +1,370 @@ +int nofloat; +int peekc; +int obuf[259]; +int tabflg; +int labno 1; + +main(argc, argv) +char **argv; +{ +/* + A1 -> A + A2 B + A O + B1 C + B2 D + BE L + BF P + C1 E + C2 F + F G + H H + R I + R1 J + S K + I M + M N + + * +1 + S +2 + C +4 + 1 +8 + + z -> 4 + c 10 + a 14 + e 20 + n 63 + * +0100 +*/ + + auto c,snlflg,nlflg,t,smode,m,ssmode; + extern fin; + + smode = nlflg = snlflg = ssmode = 0; + if (argc>1) + if ((fin = open(argv[1], 0)) < 0) { + putchar('?\n'); + return; + } + obuf[0] = 1; + if (argc>2) + if ((obuf[0] = creat(argv[2], 0666)) < 0) { + putchar('?\n'); + return; + } +loop: + c = getc(); + if (c!='\n' && c!='\t') nlflg = 0; + if (ssmode!=0 && c!='%') { + ssmode = 0; + printf(".data\nL%d:<", labno++); + } + switch(c) { + + case '\0': + printf(".text; 0\n"); + fflush(obuf); + return; + + case ':': + if (!smode) + printf("=.+2; 0"); else + putchar(':'); + goto loop; + + case 'A': + if ((c=getc())=='1' || c=='2') { + putchar(c+'A'-'1'); + goto loop; + } + putchar('O'); + peekc = c; + goto loop; + + case 'B': + switch (getc()) { + + case '1': + putchar('C'); + goto loop; + + case '2': + putchar('D'); + goto loop; + + case 'E': + putchar('L'); + goto loop; + + case 'F': + putchar('P'); + goto loop; + } + putchar('?'); + goto loop; + + case 'C': + putchar(getc()+'E'-'1'); + goto loop; + + case 'F': + putchar('G'); + goto subtre; + + case 'R': + if ((c=getc()) == '1') + putchar('J'); else { + putchar('I'); + peekc = c; + } + goto loop; + + case 'H': + putchar('H'); + goto subtre; + + case 'I': + putchar('M'); + goto loop; + + case 'S': + putchar('K'); +subtre: + snlflg = 1; + t = 'A'; +l1: + switch (c=getc()) { + + case '*': + t++; + goto l1; + + case 'S': + t =+ 2; + goto l1; + + case 'C': + t =+ 4; + goto l1; + + case '1': + t =+ 8; + goto l1; + + case '2': + t =+ 16; + goto l1; + } + peekc = c; + putchar(t); + goto loop; + + case '#': + if(getc()=='1') + putchar('#'); else + putchar('"'); + goto loop; + + case '%': + if (smode) + printf(".text;"); + if (ssmode==0) { + if ((peekc=getc())=='[') { + peekc = 0; + printf(".data;"); + while((c=getc())!=']') + putchar(c); + getc(); + printf(";.text;"); + goto loop; + } + } +loop1: + switch (c=getc()) { + + case ' ': + case '\t': + goto loop1; + case 'a': + m = 16; + t = flag(); + goto pf; + + case ',': + putchar(';'); + goto loop1; + + case 'i': + m = 12; + t = flag(); + goto pf; + case 'z': + m = 4; + t = flag(); + goto pf; + + case 'r': + m = 9; + t = flag(); + goto pf; + + case '1': + m = 5; + t = flag(); + goto pf; + + case 'c': + t = 0; + m = 8; + goto pf; + + case 'e': + t = flag(); + m = 20; + goto pf; + + case 'n': + t = flag(); + m = 63; +pf: + if ((c=getc())=='*') + m =+ 0100; else + peekc = c; + printf(".byte %o,%o", m, t); + goto loop1; + case '[': + printf("L%d=", labno++); + while ((c=getc())!=']') + putchar(c); + ssmode = 0; + smode = 0; + goto loop; + + case '\n': + printf("\nL%d\n", labno); + ssmode = 1; + nlflg = 1; + smode = 1; + goto loop; + } + putchar(c); + goto loop1; + + case '\t': + if (nlflg) { + nlflg = 0; + goto loop; + } + if (smode) { + tabflg++; + goto loop; + } + putchar('\t'); + goto loop; + + case '\n': + if (!smode) { + putchar('\n'); + goto loop; + } + if (nlflg) { + nlflg = 0; + printf("\\0>\n.text\n"); + smode = 0; + goto loop; + } + if (!snlflg) + printf("\\n"); + snlflg = 0; + printf(">\n<"); + nlflg = 1; + goto loop; + + case 'X': + case 'Y': + case 'T': + snlflg++; + } + putchar(c); + goto loop; +} + +getc() { + auto t, ifcnt; + + ifcnt = 0; +gc: + if (peekc) { + t = peekc; + peekc = 0; + } else + t = getchar(); + if (t==0) + return(0); + if (t=='{') { + ifcnt++; + t = getchar(); + } + if (t=='}') { + t = getc(); + if (--ifcnt==0) + if (t=='\n') + t = getc(); + } + if (ifcnt && nofloat) + goto gc; + return(t); +} + +flag() { + register c, f; + + f = 0; +l1: + switch(c=getc()) { + + case 'w': + f = 1; + goto l1; + + case 'i': + f = 2; + goto l1; + + case 'b': + f = 3; + goto l1; + + case 'f': + f = 4; + goto l1; + + case 'd': + f = 5; + goto l1; + + case 's': + f = 6; + goto l1; + + case 'l': + f = 8; + goto l1; + + case 'p': + f =+ 16; + goto l1; + } + peekc = c; + return(f); +} + +putchar(c) +{ + if (tabflg) { + tabflg = 0; + printf(">;.byte %o;<", c+0200); + } else + putc(c, obuf); +} diff --git a/source/c/run b/source/c/run new file mode 100644 index 0000000..c9f1bca --- /dev/null +++ b/source/c/run @@ -0,0 +1,39 @@ +cc -c -O c0[012345].c +cc -c -O c1[0123].c +as c1t.s; mv a.out c1t.o +cc cvopt.c +a.out table.s table.i +as table.i; mv a.out table.o +cc -c -O c2[01].c + +ed c0t.s +g/fpp =/s/1/0/ +w +q +as c0t.s; mv a.out c0t.o +cc -s -n c0?.o +cmp a.out /lib/c0 +cp a.out /lib/c0 + +ed c0t.s +g/fpp =/s/0/1/ +w +q +as c0t.s; mv a.out c0t.o +cc -f -s -n c0?.o +cmp a.out /lib/fc0 +cp a.out /lib/fc0 + +cc -s -n c1?.o table.o +cmp a.out /lib/c1 +cp a.out /lib/c1 + +cc -f -s -n c1?.o table.o +cmp a.out /lib/fc1 +cp a.out /lib/fc1 + +cc -s -n c2?.o +cmp a.out /lib/c2 +cp a.out /lib/c2 + +rm *.o table.i a.out diff --git a/source/c/table.s b/source/c/table.s new file mode 100644 index 0000000..748563f --- /dev/null +++ b/source/c/table.s @@ -0,0 +1,1255 @@ +/ +/ c code tables-- compile to register +/ + +.globl _regtab + +.data +_regtab=. + 106.; cr106 + 30.; cr70 + 31.; cr70 + 32.; cr32 + 33.; cr32 + 37.; cr37 + 38.; cr37 + 98.; cr100 + 99.; cr100 + 80.; cr80 + 40.; cr40 + 41.; cr40 / - like + + 42.; cr42 + 43.; cr43 + 44.; cr43 + 45.; cr45 + 46.; cr40 + 55.; cr40 + 48.; cr40 + 49.; cr49 + 70.; cr70 + 71.; cr70 + 72.; cr72 + 73.; cr73 + 74.; cr74 + 75.; cr75 + 76.; cr72 + 78.; cr70 + 85.; cr70 + 79.; cr79 + 102.; cr102 + 51.; cr51 + 52.; cr52 + 56.; cr56 + 57.; cr57 + 58.; cr58 + 59.; cr59 + 91.; cr91 + 82.; cr82 + 83.; cr82 + 84.; cr82 + 86.; cr86 + 87.; cr86 + 88.; cr86 + 0 +.text + +/ goto +cr102: +%a,n + jmp A1 + +%n*,n + F* + jmp #1(R) + +/ call +cr100: +%a,n + jsr pc,IA1 + +%n*,n + F* + jsr pc,#1(R) + +%n,n + F + jsr pc,(R) + +/ addressible +cr106: +%z,n + clr R + +%zf,n + clrf R + +%a,n +%ad,n + movB1 A1,R + +%af,n + movof A1,R + +%n*,n +%nd*,n + F* + movB1 #1(R),R + +%nf*,n + F* + movof #1(R),R + +%al,n + mov A1+,R+ + mov A1,R + +%nl*,n + F* + mov #1+2(R),R+ + mov #1(R),R + +/ ++,-- postfix +cr32: +%a,1 + movB1 A1',R + I'B1 A1 + +%aw,n + mov A1',R + I A2,A1 + +%e*,1 + F1* + movB1 #1(R1),R + I'B1 #1(R1) + +%n*,1 + F* + movB1 #1(R),-(sp) + I'B1 #1(R) + movB1 (sp)+,R + +%ew*,n + F1* + mov #1(R1),R + I A2,#1(R1) + +%nw*,n + F* + mov #1(R),-(sp) + I A2,#1(R) + mov (sp)+,R + +%al,1 + F + I $1,A1+ + V A1 + +%el*,1 + F1* + mov #1+2(R1),R+ + mov #1(R1),R + I $1,#1+2(R1) + V #1(R1) + +%nl*,1 + F* + mov #1+2(R),-(sp) + mov #1(R),-(sp) + add $1,#1+2(R) + V #1(R) + mov (sp)+,R + mov (sp)+,R+ + +/ - unary, ~ +cr37: +%n,n +%nf,n + F + IBF R + +%nl,n + F + I R + I R+ + V R + +/ = +cr80: +%a,n +%ad,nf + S + movB1 R,A1 + +%af,nf + S + movfo R,A1 + +%nd*,af + F* + S + movf R,#1(R) + +%n*,a + F* + movB1 A2,#1(R) + movB1 #1(R),R + +%nf*,af + F* + S + movfo R,#1(R) + +%n*,e + F* + S1 + movB1 R1,#1(R) + movB1 R1,R + +%ed*,nf + S + F1* + movf R,#1(R1) + +%ef*,nf + S + F1* + movfo R,#1(R1) + +%n*,n +%nd*,nf + FS* + S + movB1 R,*(sp)+ + +%nf*,nf + FS* + S + movfo R,*(sp)+ + +/ +, -, |, &~, << +cr40: +%n,z + F + +%n,1 + F + I' R + +%[add1:] +%n,aw +%nf,ad + F + IB2 A2,R + +%[add2:] +%n,ew* +%nf,ed* + F + S1* + IB2 #2(R1),R + +%[add3:] +%n,e +%nf,ef + F + S1 + IBF R1,R + +%[add4:] +%n,nw* +%nf,nd* + SS* + F + IB2 *(sp)+,R + +%[add5:] +%n,n +%nf,nf + SS + F + IBF (sp)+,R + +%nl,c + F + I A2,R+ + V R + +%nl,al + F + I A2,R + I A2+,R+ + V R + +%nl,el + F + S1 + I R1+,R+ + V R + I R1,R + +%nl,nl + SS + F + I (sp)+,R + I (sp)+,R+ + V R + +/ ^ -- xor +cr49: +%n,e +% [add3] + +%n,n + FS + S + xor R,(sp) + mov (sp)+,R + +/ >> (all complicated cases taken care of by << -) +cr45: +%n,1 + F + asr R + +/ * -- R must be odd on integers +cr42: +%n,aw +%nf,ad +% [add1] + +%n,ew* +%nf,ed* +% [add2] + +%n,e +%nf,ef +% [add3] + +%n,n +%nf,nf +% [add5] + +/ / R must be odd on integers +cr43: +%n,aw + F + T + sxt R- + div A2,R- + +%n,ew* + F + T + sxt R- + S1* + div #2(R1),R- + +%n,e + F + T + sxt R- + S1 + div R1,R- + +%n,n + SS + F + T + sxt R- + div (sp)+,R- + +%nf,ad +% [add1] + +%nf,ed* +% [add2] + +%nf,ef +% [add3] + +%nf,nf +% [add5] + +/ =+, =-, =|, =&~ +cr70: +%[addq1:] +%aw,aw + I A2,A1' + mov A1,R + +%[addq1a:] +%a,aw +%ad,ad + movB1 A1',R + IBF A2,R + movB1 R,A1 + +%[addq2:] +%aw,nw* + S* + I #2(R),A1' + mov A1,R + +%[addq3:] +%aw,n + S + I R,A1' + mov A1,R + +%[addq4:] +%ew*,nw* + S* + F1* + I #2(R),#1(R1) + mov #1(R1),R + +%[addq4a:] +%ad,ef + movf A1',R + S1 + IBF R1,R + movf R,A1 + +%[addq5:] +%a,n +%ad,nf + SS + movB1 A1',R + IBF (sp)+,R + movB1 R,A1 + +%[addq6:] +%af,nf + SS + movof A1',R + IBF (sp)+,R + movfo R,A1 + +%[addq7:] +%ew*,n + S + F1* + I R,#1(R1) + mov #1(R1),R + +%[addq8:] +%nw*,n + SS + F* + I (sp)+,#1(R) + mov #1(R),R + +%[addq9:] +%n*,n + FS* + SS + movB1 *2(sp),R + IBF (sp)+,R + movB1 R,*(sp)+ + +%[addq9a:] +%nd*,nf + SS + F* + movB1 #1(R),R + IBF (sp)+,R + movB1 R,#1(R) + +%[addq10:] +%nf*,nf + SS + F* + movof #1(R),R1 + IBF (sp)+,R1 + movfo R1,#1(R) + movf R1,R + +/ =*, =<< (for integer multiply, R must be odd) +cr72: +%a,aw +%ad,ad +% [addq1a] + +%af,nf +% [addq6] + +%ad,ef +% [addq4a] + +%a,n +%ad,nf +% [addq5] + +%n*,n +% [addq9] + +%nd*,nf +% [addq9a] + +%nf*,nf +% [addq10] + +/ =/ ; R must be odd on integers +cr73: +%a,aw + movB1 A1',R + sxt R- + divBF A2,R- + movB1 R-,A1 + +%a,n + SS + movB1 A1',R + sxt R- + div (sp)+,R- + movB1 R-,A1 + +%e*,n + SS + F1* + movB1 #1(R1),R + sxt R- + div (sp)+,R- + movB1 R-,#1(R1) + +%n*,n + FS* + SS + movB1 *2(sp),R + sxt R- + div (sp)+,R- + movB1 R-,*(sp)+ + +%ad,ad +% [addq1a] + +%ad,ef +% [addq4a] + +%ad,nf +% [addq5] + +%af,nf +% [addq6] + +%nd*,nf +% [addq9a] + +%nf*,nf +% [addq10] + +/ =mod; R must be odd on integers +cr74: +%a,aw + movB1 A1',R + sxt R- + div A2,R- + movB1 R,A1 + +%a,n + SS + movB1 A1',R + sxt R- + div (sp)+,R- + movB1 R,A1 + +%e*,n + SS + F1* + movB1 #1(R1),R + sxt R- + div (sp)+,R- + movB1 R,#1(R1) + +%n*,n + FS* + SS + movB1 *2(sp),R + sxt R- + div (sp)+,R- + mov R,*(sp)+ + +/ =^ -- =xor +cr79: +%aw,n +% [addq3] + +%ab,n + SS + movb A1',R + xor R,(sp) + mov (sp)+,R + movb R,A1 + +%n*,n + FS* + movB1 *(sp),-(sp) + S + xor R,(sp) + movB1 (sp)+,R + movB1 R,*(sp)+ + +/ =>> (all complicated cases done by =<< -) +cr75: +%a,1 + asrB1 A1' + movB1 A1,R + +%n*,1 + F* + asrB1 #1(R) + movB1 #1(R),R + +/ << for longs +cr91: +%nl,aw +% [add1] + +%nl,ew* +% [add2] + +%nl,e +% [add3] + +%nl,nw* +% [add4] + +%nl,n +% [add5] + +/ int -> float +cr51: +%aw,n + movif A1,R + +%nw*,n + F* + movif #1(R),R + +%n,n + F + movif R,R + +/ float, double -> int +cr52: +%nf,n + F + movfi R,R + +/ double (float) to long +cr56: +%nf,n + F + setl + movfi R,-(sp) + mov (sp)+,R + mov (sp)+,R+ + seti + +/ long to double +cr57: +%al,n + setl + movif A1,R + seti + +%nl*,n + F* + setl + movif #1(R),R + seti + +%nl,n + FS + setl + movif (sp)+,R + seti + +/ integer to long +cr58: +%n,n + F1! + sxt R + +/ long to integer +cr59: +%al,n + mov A1+,R + +%nl*,n + F* + mov #1+2(R),R + +%nl,n + F + mov R+,R + +/ *, /, remainder for longs. +cr82: +%nl,nl + SS + FS + jsr pc,I + add $10,sp + +/ =*, =/, =rem for longs +/ Operands of the form &x op y, so stack space is known. +cr86: +%n,nl + SS + FS + jsr pc,I + add $6,sp + +/ +/ c code tables -- compile for side effects. +/ Also set condition codes properly (except for ++, --) +/ + +.globl _efftab + +.data +_efftab=. + 30.; ci70 + 31.; ci70 + 32.; ci70 + 33.; ci70 + 80.; ci80 + 70.; ci70 + 71.; ci70 / - like + + 78.; ci78 + 85.; ci78 + 75.; ci75 + 76.; ci76 + 92.; ci92 + 0 +.text + +/ = +ci80: +%[move1:] +%a,z +%ad,zf + I'B1 A1 + +%[move2:] +%n*,z +%nd*,zf + F* + I'B1 #1(R) + +%[move3:] +%a,aw +%ab,a + IBE A2,A1 + +%[move4:] +%ab,n* +%a,nw* + S* + IBE #2(R),A1 + +%[move5:] +%a,n + S + IB1 R,A1 + +%[move6:] +%n*,aw +%nb*,a + F* + IBE A2,#1(R) + +%[move7:] +%n*,ew* +%nb*,e* + F* + S1* + IBE #2(R1),#1(R) + +%[move8:] +%n*,e + F* + S1 + IB1 R1,#1(R) + +%[move9:] +%e*,nw* +%eb*,n* + S* + F1* + IBE #2(R),#1(R1) + +%[move10:] +%e*,n + S + F1* + IB1 R,#1(R1) + +%[move11:] +%n*,nw* +%nb*,n* + FS* + S* + IBE #2(R),*(sp)+ + +%[move12:] +%n*,n + FS* + S + IB1 R,*(sp)+ + +%al,z + clr A1 + clr A1+ + +%al,aw + mov A2,A1+ + sxt A1 + +%al,nw* + mov #2(R),A1+ + sxt A1 + +%al,n + S + mov R,A1+ + sxt A1 + +%al,nf + S + setl + movfi R,A1 + seti + +%el*,nf + S + F1* + setl + movfi R,#1(R1) + seti + +%[move13a:] +%al,c + I A2,A1+ + V A1 + +%[move13:] +%al,al + I A2,A1 + I A2+,A1+ + V A1 + +%[move14:] +%al,nl* + S* + I #2(R),A1 + I #2+2(R),A1+ + V A1 + +%[move14a:] +%nl*,c + F* + I A2,2+#1(R) + V #1(R) + +%[move15:] +%al,nl + S + I R,A1 + I R+,A1+ + V A1 + +%nl*,aw + F* + mov A2,#1+2(R) + sxt #1(R) + +%[move16:] +%el*,nl + S + F1* + I R+,#1+2(R1) + V #1(R1) + I R,#1(R1) + +%nl*,n + SS + F* + mov (sp)+,#1+2(R) + sxt #1(R) + +%[move17:] +%nl*,nl + SS + F* + I (sp)+,#1(R) + I (sp)+,#1+2(R) + V #1(R) + +/ =| and =& ~ +ci78: +%a,a +% [move3] + +%a,n +% [move5] + +%n*,a +% [move6] + +%n*,e* +% [move7] + +%n*,e +% [move8] + +%e*,n* +% [move9] + +%e*,n +% [move10] + +%n*,n* +% [move11] + +%n*,n +% [move12] + +%al,c +% [move13a] + +%al,al +% [move13] + +%al,nl* +% [move14] + +%al,nl +% [move15] + +%nl*,c +% [move14a] + +%el*,nl +% [move16] + +%nl*,nl +% [move17] + +/ =+ +ci70: +%n*,z +%a,z + +%a,1 + I'B1 A1 + +%aw,aw +% [move3] + +%aw,nw* +% [move4] + +%aw,n +% [move5] + +%n*,1 +% [move2] + +%ew*,nw* +% [move9] + +%a,nw* + S* + movB1 A1',R1 + I #2(R),R1 + movB1 R1,A1 + +%a,n + S + movB1 A1',R1 + I R,R1 + movB1 R1,A1 + +%ew*,n +% [move10] + +%nw*,n +% [move12] + +%n*,n + SS + F* + movB1 #1(R),R1 + I (sp)+,R1 + movB1 R1,#1(R) + +%al,c +% [move13a] + +%al,al +% [move13] + +%al,nl* +% [move14] + +%al,nl +% [move15] + +%nl*,c +% [move14a] + +%el*,nl +% [move16] + +%nl*,nl +% [move17] + +/ =>> (all harder cases handled by =<< -) +ci75: +%a,1 + asrB1 A1 + +%n*,1 + F* + asrB1 #1(R) + +/ =<< +ci76: +%a,1 + aslB1 A1 + +%n*,1 + F* + aslB1 #1(R) + +%r,aw + ash A2,A1 + +%r,nw* + S* + ash #2(R),A1 + +%r,n + S + ash R,A1 + +/ =<< for longs +ci92: +%al,aw + F + ashc A2,R + mov R,A1 + mov R+,A1+ + +%al,n + SS + F + ashc (sp)+,R + mov R,A1 + mov R+,A1+ + +%nl*,n + FS* + SS + mov 2(sp),R + mov 2(R),R+ + mov (R),R + ashc (sp)+,R + mov R,*(sp) + mov (sp)+,R + mov R+,2(R) + +/ +/ c code tables-- set condition codes +/ + +.globl _cctab + +.data +_cctab=. + 106.; cc60 + 28.; rest + 55.; rest + 34.; rest + 35.; rest + 36.; rest + 37.; rest + 40.; rest + 41.; rest + 42.; rest + 43.; rest + 45.; rest + 46.; rest + 81.; cc81 / & as in "if ((a&b)==0)" + 48.; rest + 60.; cc60 + 61.; cc60 + 62.; cc60 + 63.; cc60 + 64.; cc60 + 65.; cc60 + 66.; cc60 + 67.; cc60 + 68.; cc60 + 69.; cc60 + 72.; rest + 73.; rest + 79.; rest + 0 +.text + +/ relationals +cc60: +%a,z +%ad,zf +% [move1] + +%af,z + movof A1,R + +%n*,z +%nd*,zf +% [move2] + +%nf*,z + F* + movof #1(R),R + +%n,z +%nf,zf + FC + +%aw,aw +%ab,ab +% [move3] + +%nw*,aw +%nb*,ab +% [move6] + +%n,aw +%nf,ad +% [add1] + +%nw*,ew* +%nb*,eb* +% [move7] + +%nw*,e +% [move8] + +%n,ew* +%nf,ed* +% [add2] + +%n,e +%nf,ef +% [add3] + +%nw*,nw* +%nb*,nb* +% [move11] + +%nw*,n +% [move12] + +%n,n +%nf,nf +% [add5] + +/ & as in "if ((a&b) ==0)" +cc81: +%a,a +% [move3] + +%n*,a +% [move6] + +%n,a +% [add1] + +%n,e +% [add3] + +%n,n +% [add5] + +/ set codes right +rest: +%n,n +%nf,nf + H + +/ +/ c code tables-- expression to -(sp) +/ + +.globl _sptab + +.data +_sptab=. + 106.; cs106 + 40.; cs40 + 41.; cs40 + 55.; cs40 + 48.; cs40 + 58.; cs58 + 56.; cs56 + 0 +.text + + +/ name +cs106: +%z,n +%zf,n + clrB1 -(sp) + +%aw,n + mov A1,-(sp) + +%nw*,n + F* + mov #1(R),-(sp) + +%al,n + mov A1+,-(sp) + mov A1,-(sp) + +/ +, -, |, &~ +cs40: +%n,1 + FS + I' (sp) + +%n,aw + FS + I A2,(sp) + +%n,nw* + FS + S* + I #2(R),(sp) + +%n,n + FS + S + I R,(sp) + +/ integer to long +cs58: +%n,n + FS + sxt -(sp) + +/ float to long +cs56: +%nf,n + F + setl + movfi R,-(sp) + seti + diff --git a/source/cref/ccmn.h b/source/cref/ccmn.h new file mode 100644 index 0000000..7ff7e28 --- /dev/null +++ b/source/cref/ccmn.h @@ -0,0 +1,83 @@ +struct tempent { + char *beg; + int ct; + char term; + } temp[30]; + +char lbuf[5]; +int cflag; +int t1; + +int level; +int hlevel; +int dlevel; +int xtrn; + +int tp[5]; + +struct { + int cl[NUMC]; + } tab[NUMS]; + +int coll(); +int save(); +int out(); +int asym(); +int asw(); +int csym(); +int csw(); +int incl(); +int decl(); +int sk2(); +int sk(); +int tabs(); +int semi(); + +char line[132]; +int l; +int lno; +char c; +int cursl; +char curs[9]; +int curfl; +char curf[10]; + +int usw; +int xsw; +int only; +int cross; +int file; +int cs; +int (*flag[8])(); +int fl; +char gch[8]; + +struct htab { + int hsiz; + int ssiz; + int nsym; + int curb; + int *hptr; + char *symt; + }; + +struct htab itab; +struct htab xtab; + +int ipsp[PTRI]; +char issp[CHARI]; +int xpsp[PTRX]; +char xssp[CHARX]; + +int ib1[259]; +int ib2[259]; + +char *ibuf; +char *ibuf1; +char *ibuf2; + +char mone; +int order; +int ssw; +int type; +char *utmp; diff --git a/source/cref/index/ecmn.h b/source/cref/index/ecmn.h new file mode 100644 index 0000000..1cc8d0a --- /dev/null +++ b/source/cref/index/ecmn.h @@ -0,0 +1,76 @@ +int count; +int page; +struct { + char *beg; + int ct; + char term; + } temp[30]; + +int pn; +int word; +int hsw; +int t1; + +int level; +int hlevel; +int dlevel; +int xtrn; + +int tp[2]; + +struct { + int cl[NUMC]; + } tab[NUMS]; + +int coll(); +int save(); +int out(); +int hyphen(); +int hyp1(); +int hyp2(); +int pno(); +int error(); + +char line[300]; +int l; +int lno; +char c; +int cursl; +char curs[9]; +int curfl; +char curf[10]; + +int usw; +int xsw; +int only; +int cross; +int file; +int cs; +int (*flag[8])(); +int fl; +char gch[8]; + +struct htab { + int hsiz; + int ssiz; + int nsym; + int curb; + int *hptr; + char *symt; + }; + +struct htab itab; + +int ipsp[PTRI]; +char issp[CHARI]; + +int ib1[259]; + +char *ibuf; +char *ibuf1; + +char mone; +int order; +int ssw; +int type; +char *utmp; diff --git a/source/cref/index/econs.h b/source/cref/index/econs.h new file mode 100644 index 0000000..328555f --- /dev/null +++ b/source/cref/index/econs.h @@ -0,0 +1,22 @@ +# define NUMA 14 +# define NUMC 128 +# define NUMS 3 +# define SIZA 8 +# define SIZC 2 +# define SIZS 8 +# define PTRI 509 +# define CHARI 4000 +# define PTRX 5147 +# define CHARX 40000 +# define CONT 0 +# define COLL 1 +# define SAVE 2 +# define OUT 3 +# define EGOBL 4 +# define SHARP 5 +# define PNO 6 + +# define SKIP 0 +# define COLLECT 1 +# define SKIP2 2 +#define CREATC 0644 diff --git a/source/cref/index/ind0.c b/source/cref/index/ind0.c new file mode 100644 index 0000000..ad8547a --- /dev/null +++ b/source/cref/index/ind0.c @@ -0,0 +1,363 @@ +# +# include "econs.h" +# include "ecmn.h" +/*int mbuf[1024]; /*INSTR*/ +/*int tbuf[12]; /*INSTR*/ + +int (*acts[])() {0, + &coll, + &save, + &out, + &error, + &hyphen, + &pno + }; + +char *tmp[2] {"/tmp/crt0a", + "/tmp/crt1a" + }; + +char *ignonl "/usr/lib/eign"; +char *gtab "/usr/lib/etab"; + +main(argc,argv) + char *argv[]; +{ + auto i,j,tm1,tm2,tm3; + char *fn,*av[8]; +/* extern etext; /*INSTR*/ + +/* monitor(&main,&etext,&mbuf,1024); /*INSTR*/ + + if(*argv[1] == '-') { + j = flags(argv); + argv =+ j; + argc =- j; + } + + init(); + + i = 0; + if(argc == 1) { + *ibuf1 = 0; + curfl = 2; + curf[0] = '_'; + curf[1] = '\t'; + goto pipe; + } + while(++i < argc) { + curs[4] = '\t'; + + if(fopen(argv[i],ibuf1) < 0) { + printf("Can't open %s\n",argv[i]); + dexit(); + } + + curfl = 0; + while((curf[curfl] = *argv[i]++) != 0 && curfl <=8) + if(curf[curfl++] == '/') curfl = 0; + curf[curfl++] = '\t'; + if(curfl == 8) curf[8] = -1; + +pipe: + ibuf = ibuf1; + lno = 1; + + driver(); + + close(file); + } + flsh(0); + close(tp[0]); + + +/* monitor(0); /*INSTR*/ +/* dexit(); /*INSTR*/ + +/* times(tbuf); /*INSTR*/ +/* tm1 = tbuf[0]/6; /*INSTR*/ +/* tm2 = tbuf[1]/6; /*INSTR*/ +/* printf("Prep: %d %d\n", tm1, tm2); /*INSTR*/ + +/* exit(); /*DEBUG*/ + fn = "/bin/sort"; + av[0] = "sort"; + av[1] = tmp[0]; + av[2] = "-o"; + av[3] = tmp[0]; + av[4] = 0; + + callsys(fn, av); + +/* times(tbuf); /*INSTR*/ +/* tm1 = tbuf[3]/6; /*INSTR*/ +/* tm2 = tbuf[5]/6; /*INSTR*/ +/* printf("Sort: %d %d\n", tm1, tm2); /*INSTR*/ + + if(usw) { + fn = "/usr/bin/upost"; + av[0] = "upost"; + i = 0; + } else if(count) { + fn = "count"; + av[0] = "count"; + i = 0; + } else { + fn = "/usr/bin/crpost"; + av[0] = "crpost"; + av[1] = "-E"; + i = 1; + } + av[++i] = tmp[0]; + av[++i] = 0; + + callsys(fn,av); + +/* times(tbuf); /*INSTR*/ +/* tm1 = tbuf[3]/6 - tm1; /*INSTR*/ +/* tm2 = tbuf[5]/6 - tm2; /*INSTR*/ +/* printf("Post: %d %d\n", tm1, tm2); /*INSTR*/ + + dexit(); +} + +driver() +{ + auto p; + +top: + l = -1; + while((c = line[++l] = getc(ibuf)) != -1) { +/* printf("driver: c = %o l = %d\n",c,l); /*DEBUG*/ + if(l >= 299) { + printf("Line too long: %d.\n",lno); + dexit(); + } + + if(c & 0200) { + printf("Illegal character: %o line %d\n",c,lno); + dexit(); + } + + if(fl) { + if((*flag[fl])()) + continue; + } + +/*printf("cs = %d cc = %c ca = %d\n",cs,c,tab[cs].cl[c]); /*DEBUG*/ + + if(p = tab[cs].cl[c]) + (*acts[p])(); + continue; + } + if(ibuf == ibuf1) return; + ibuf = ibuf1; + goto top; + +} + +init() +{ + int b[3]; + auto fi,i; + extern coll(),save(),out(),asym(),asw(),csym(),csw(); + extern incl(),decl(),sk(),sk2(); + extern dexit(); + + ibuf1 = &ib1; + + + + if((fi = open(gtab,0)) < 0) { + printf("Cannot open grammar table; see lem\n"); + dexit(); + } + + i = -1; + while(++i < NUMS) + if(read(fi,tab[i].cl,256) < 256) { + printf("Bad grammar table; see lem\n"); + dexit(); + } + + close(fi); + + + + if(signal(1,1) != 1) signal(1,&dexit); + if(signal(2,1) != 1) signal(2,&dexit); + if(signal(3,1) != 1) signal(3,&dexit); + while((tp[1] = creat(tmp[1],0)) < 0) + tmp[1][9]++; + close(tp[1]); + tmp[0][9] = tmp[1][9]; + tp[0] = creat(tmp[0],CREATC); + + if(count) return; + + itab.hptr = &ipsp; + itab.symt = &issp; + itab.hsiz = PTRI; + itab.ssiz = CHARI; + itab.nsym = 0; + itab.curb = 1; + + if((fi = open(ignonl,0)) < 0) { + printf("Cannot open ignore/only file.\n"); + dexit(); + } + if((read(fi,b,6) == 6) && (b[0] == 0100200)) { + if(read(fi,itab.hptr,b[1]) < b[1]) { + printf("Cannot read ignore/only file.\n"); + dexit(); + } + if(read(fi,itab.symt,b[2]) < b[2]) { + printf("Cannot read ignor/only file.\n"); + dexit(); + } + close(fi); + } else { + close(fi); + compile(); + } + return; +} + +error(a) +{ + printf("Error %d\n",a); + dexit(); +} + +dexit() +{ + extern nflush; + +/* printf("nflush = %d\n",nflush); /*DEBUG*/ + if(tp[0] > 0 && utmp == 0) { + unlink(tmp[0]); + unlink(tmp[1]); + } + exit(); +} + +callsys(f,v) + char f[],*v[]; +{ + int t,status,i; + + if((t = fork()) == 0) { + for(i = 1; i <= 12; i++) signal(i,0); + execv(f,v); + printf("Can't find %s\n",f); + exit(1); + } else { + if(t == -1) { + printf("Try again\n"); + return(1); + } + } + + while(t != wait(&status)); +/* printf("Status = %o, %s\n",status,f); /*DEBUG*/ + if((t = (status & 0377)) != 0) { + if(t != 2) { + printf("Fatal error in %s\n",f); + printf("t = %d\n",t); + } + dexit(); + } + return((status>>8) & 0377); +} + +flags(argv) + char *argv[]; +{ + int j,xx; + char *ap; + + j = 1; + ap = argv[1]; + while(*++ap != '\0') { + switch(*ap) { + + default: + printf("Unrecognized flag: %c\n",*ap); + dexit(); + + case 'c': + count = 1; + continue; + + case 'i': /* Ignore file */ + if(!xx) { + xx = 1; + only = 0; + ignonl = argv[++j]; + } + continue; + + case 'o': /*only file*/ + if(!xx) { + xx = 1; + only = 1; + ignonl = argv[++j]; + } + continue; + + case 'p': + page = 1; + continue; + + case 't': + utmp = argv[++j]; + tmp[0] = argv[j]; + continue; + + case 'u': /* Unique symbols only */ + usw = 1; + continue; + + case 'w': /* Word list only */ + word = 1; + continue; + + } + } + return(j); +} + + +compile() +{ + char buf[40],*b; + int i,v; + + fopen(ignonl,ibuf1); + + b = buf - 1; + while((*++b = getc(ibuf1)) != -1) { + if(*b == '\n') { + *b = '\0'; + search(buf,b - buf,&itab,1); + b = buf - 1; + } else { + if(*b == '\t') { + v = 0; + while((i = getc(ibuf1)) != -1) { + if(i == '\n') break; + v = v*10 + (i - '0'); + } + search(buf,b - buf,&itab,v); + b = buf - 1; + } else { + if((b - buf) > 39) { + printf("Ignore/only symbol too long.\n"); + dexit(); + } + } + } + } + close(ibuf1); + return; +} diff --git a/source/cref/index/ind1.c b/source/cref/index/ind1.c new file mode 100644 index 0000000..08830a8 --- /dev/null +++ b/source/cref/index/ind1.c @@ -0,0 +1,259 @@ +# +# include "econs.h" +# include "ecmn.h" +# define SKIP 0 +# define COLLECT 1 +# define SKIP2 2 + +char mone -1; +int tlno 1; + +coll() +{ + cs = COLLECT; + temp[t1].beg = &line[l]; + return; +} + +save() +{ + extern only; + char *pt1,*pt2,cbuf[30]; + int a,tt,val; + + cs = SKIP; + line[l] = '\0'; + temp[t1].ct = &line[l] - temp[t1].beg; + if(!count) + if(temp[t1].ct == 1) goto no; + pt1 = temp[t1].beg-1; + pt2 = cbuf-1; + + while(*++pt2 = *++pt1) + if(*pt2 >= 'A' && *pt2 <= 'Z') + *pt2 =| 040; + + if(count) + goto yes; + val = search(cbuf,temp[t1].ct,&itab,0); + + if(!val == !only) goto yes; +no: + line[l] = c; + return(0); +yes: + if(count == 0) { + tt = t1; + while(tt) + if(comp(temp[t1].beg,temp[--tt].beg)) goto no; + } + temp[t1++].term = c; + return(1); +} + +out() +{ + auto i,ct,t2; + char *b,*e; + if(cs == COLLECT) save(); + ct = t1; + while(ct--) + temp[ct].beg[temp[ct].ct] = temp[ct].term; + t2 = t1 - 1; + while(t1--) { +/*printf("t1 = %d beg = %o ct = %d\n",t1,temp[t1].beg,temp[t1].ct); /* DEBUG */ + if((ct = temp[t1].ct) >= 15) { + ct = 15; + } + put(temp[t1].beg,ct); + if(count) { + put("\n", 1); + continue; + } + + put("\t",1); + + if(!page) { + put(curf,curfl); + conf(lno,4,curs); + put(curs,4); + } else { + conf(pn,4,curs); + put(curs,4); + } + if(word == 0) { + put("\t",1); + if(t1 >= 1) + b = temp[t1-1].beg; + else + b = line; + if(t2 > t1) + e = temp[t1+1].beg + temp[t1+1].ct; + else + e = &line[l]; +/*printf("e = %o b = %o\n",e,b); /*DEBUG*/ + put(b,e-b); + } + put("\n",1); + } + t1 = 0; + l = -1; + lno =+ tlno; + tlno = 1; + cs = SKIP; + return; +} + + +search(symbol,length,params,install) + char *symbol; + int length; + struct htab *params; + int install; +{ + char *sp,*p; + static int *hptr,hsiz,nsym; + static char *ssiz; + static int curb; + static char *symt; + auto h,i,j,k; + + if(hptr != params->hptr) { + hptr = params->hptr; + hsiz = params->hsiz; + symt = params->symt; + ssiz = params->ssiz; + curb = params->curb; + nsym = params->nsym; + } + + symbol[length] = '\0'; +/*printf("ssiz = %d; nsym = %d; %s\n", ssiz, nsym, symbol);/*DEBUG*/ + sp = symbol; + + i = length; + h = 1; + while(i--) + h =* *sp++; + + if(h == 0100000) { + h = 1; + } else { + h = h<0?(-h)%hsiz:h%hsiz; + } + if(h == 0) h++; +/* printf("%s %d\n",symbol,h); /*DEBUG*/ + + while((p = &symt[hptr[h]]) > symt) { + j = length + 2; + sp = symbol; + while(--j) { + if(*p++ != *sp++) goto no; + } + return(*p); +no: + h = (h + h)%hsiz; + } + if(install) { + if(++nsym >= hsiz) { + printf("Too many symbols in ignore/only file.\n"); + dexit(); + } + + hptr[h] = curb; + length++; + if((curb + length) >= ssiz) { + printf("i/o file too big; ssiz = %d\n", ssiz); + dexit(); + } + + while(length--) + symt[curb++] = *symbol++; + symt[curb++] = install; + params->curb = curb; + params->nsym = nsym; + } + return(0); +} + +conf(n,width,buf) + char *buf; +{ + auto i,a; + + i = width; + while(i--) buf[i] = ' '; + + buf[(a = n/10)?conf(a,--width,buf):--width] = n%10 + '0'; + + return(++width); +} + +comp(a,b) + char *a; + char *b; +{ + a--; + b--; + while(*++a == *++b) + if(*a == '\0') return(1); + return(0); +} + + +hyphen() +{ +/* printf("hyphen\n"); /*DEBUG*/ + if(gch[fl] == 0) + flag[++fl] = &hyp1; + return(1); +} + +hyp1() +{ +/* printf("hyp1 c = %o\n",c); /*DEBUG*/ + if(c != '\n') { + fl--; + return(0); + } else { + l =- 2; + flag[fl] = &hyp2; + hsw = 1; + return(1); + } +} + +hyp2() +{ +/* printf("hyp2 c = %o l = %d\n",c,l); /*DEBUG*/ + if(hsw && (tab[2].cl[c] == 0)) { + l--; + if(c == 3) pno(); + if(c == '\n') tlno++; + return(1); + } + hsw = 0; + if(tab[cs].cl[c]) { + line[l] = '\n'; + out(); + fl--; + return(0); + } + return(1); +} + +pno() +{ + if(flag[fl] != &pno) { + flag[++fl] = &pno; + pn = 0; + return(1); + } + if(c == '\n') { + fl--; + out(); + return(1); + } + pn = pn*10 + c - '0'; + return(1); +} diff --git a/source/cref/index/ind2.c b/source/cref/index/ind2.c new file mode 100644 index 0000000..d0f82bf --- /dev/null +++ b/source/cref/index/ind2.c @@ -0,0 +1,49 @@ +int optr; + +char obuf[512]; + +int nflush; + +put(string,n) + char *string; +{ + extern utmp; + int i; + char *o; + +/*printf("%d %c %d\n",fil,*string,n);/*DEBUG*/ + + string--; + + if((i = optr + n - 512) >= 0) { + n =- i; + o = &obuf[optr] -1; + while(--n >= 0) + *++o = *++string; + optr = 512; + flsh(1); + n = i; + } + + o = &obuf[optr] - 1; + optr =+ n; + + while(--n >= 0) { + *++o = *++string; + } + return(0); +} + +flsh(fil) +{ + extern tp[],utmp; + + if(optr <= 0) return(optr); + + nflush++; + if(write(tp[0],obuf,optr) != optr) + return(-1); + optr = 0; + return(0); +} + diff --git a/source/cref/mcons.h b/source/cref/mcons.h new file mode 100644 index 0000000..f543ee1 --- /dev/null +++ b/source/cref/mcons.h @@ -0,0 +1,30 @@ +# define NUMA 14 +# define NUMC 128 +# define NUMS 3 +# define SIZA 8 +# define SIZC 2 +# define SIZS 8 +# define PTRI 509 +# define CHARI 4000 +# define PTRX 509 +# define CHARX 4000 +# define CONT 1 +# define COLL 2 +# define SAVE 3 +# define OUT 4 +# define ASYM 5 +# define ASW 6 +# define CSYM 7 +# define CSW 8 +# define INCL 9 +# define DECL 10 +# define SK2 11 +# define SK 12 +# define TABS 13 +# define SEMI 14 +# define SHARP 15 + +# define SKIP 0 +# define COLLECT 1 +# define SKIP2 2 +#define CREATC 0644 diff --git a/source/cref/run b/source/cref/run new file mode 100644 index 0000000..b1d8bbc --- /dev/null +++ b/source/cref/run @@ -0,0 +1,30 @@ +chdir tab +cc mtab.c +a.out atable atab +a.out ctable ctab +a.out etable etab +cmp atab /usr/lib/atab +cp atab /usr/lib/atab +cmp ctab /usr/lib/ctab +cp ctab /usr/lib/ctab +cmp etab /usr/lib/etab +cp etab /usr/lib/etab +rm a.out atab ctab etab + +chdir ../src +cc -s -O upost.c +cmp a.out /usr/bin/upost +cp a.out /usr/bin/upost +cc -s -O crpost.c +cmp a.out /usr/bin/crpost +cp a.out /usr/bin/crpost +cc -s -O dr.c acts.c put.c +cmp a.out /usr/bin/cref +cp a.out /usr/bin/cref +rm a.out *.o + +chdir ../index +cc -s -O ind?.c +cmp a.out /usr/bin/index +cp a.out /usr/bin/index +rm a.out *.o diff --git a/source/cref/src/acts.c b/source/cref/src/acts.c new file mode 100644 index 0000000..03f5b19 --- /dev/null +++ b/source/cref/src/acts.c @@ -0,0 +1,484 @@ +# +# include "../mcons.h" +# include "../ccmn.h" +# define SKIP 0 +# define COLLECT 1 +# define SKIP2 2 + +int cross 1; +int order 1; +char mone -1; + +coll() +{ + cs = COLLECT; + temp[t1].beg = &line[l]; + return; +} + +save() +{ + extern wspace(); + + line[l] = '\0'; + temp[t1].ct = &line[l] - temp[t1].beg; + temp[t1].term = c; + + if((c == ' ' || c == '\t') && cflag) { + gch[++fl] = mone; + flag[fl] = &wspace; + } else { + sav1(); + } + return; +} + +sav1() +{ + extern only; + struct tempent *ptr; + int a,tt,val; + + if(cflag && c == '(' && level == 0) csym(); + + cs = SKIP; + + ptr = &temp[t1]; + val = search(ptr->beg,ptr->ct,&itab,0); + + if(xsw) { + switch(val) { + case 0: + if((!level&&!hlevel)||(c == '(')||xtrn + || ssw) { + search(ptr->beg,ptr->ct,&xtab,1); + goto yes; + } else { + if(search(ptr->beg,ptr->ct,&xtab,0)) + goto yes; + } + goto no; + + case 1: + goto no; + + case 2: + xtrn = 1; + goto no; + + case 3: + if(hlevel) type = 1; + if(!level&&!hlevel) ssw = 1; + goto no; + + case 4: + if(hlevel) type = 1; + goto no; + } + } + + if(hlevel && (val == 4 || val == 3)) type = 1; + if(!val == !only) goto yes; +no: + *(ptr->beg + ptr->ct) = ptr->term; + return(0); +yes: + tt = t1; + while(tt) + if(comp(ptr->beg,temp[--tt].beg)) goto no; + t1++; + return(1); +} + +out() +{ + auto i,ct; + if(cs == COLLECT) save(); + + ct = t1; + while(ct--) + temp[ct].beg[temp[ct].ct] = temp[ct].term; + + while(t1--) { +/*printf("t1 = %d beg = %d ct = %d\n",t1,temp[t1].beg,temp[t1].ct); /* DEBUG */ + + switch(order) { + + case 1: + if(utmp) + i = 0; + else + i = dfile(temp[t1].beg); + + if((ct = temp[t1].ct) >= 8) { + ct = 8; + *curf = -1; + } else { + *curf = '\t'; + } + + put(i,temp[t1].beg,ct); + put(i,curf,curfl); + if(cross) put(i,curs,cursl); + conf(lno,4,lbuf); + put(i,lbuf,5); + break; + + case 2: + i = dfile(curf+1); + put(i,curf+1,curfl-1); + if(cross) put(i,curs,cursl); + else { + conf(lno,4,lbuf); + put(i,lbuf,5); + } + if((ct = temp[t1].ct) >= 8) { + put(i,temp[t1].beg,8); + put(i,&mone,1); + } else { + put(i,temp[t1].beg,ct); + put(i,"\t",1); + } + if(cross) { + conf(lno,4,lbuf); + put(i,lbuf,5); + } + break; + + case 3: + i = dfile(curs); + put(i,curs,cursl); + if((ct = temp[t1].ct) >= 8) { + put(i,temp[t1].beg,8); + *curf = -1; + } else { + put(i,temp[t1].beg,ct); + *curf = '\t'; + } + put(i,curf,curfl); + conf(lno,4,lbuf); + put(i,lbuf,5); + } + put(i,line,l + 1); + + } + t1 = 0; + l = -1; + lno++; + cs = SKIP; + + return; +} + + +asym() +{ + int i; + char *p; + + if(cs == COLLECT) { + if(cross) { + p = temp[t1].beg; + cursl = &line[l] - p; + cursl = cursl>8?8:cursl; + i = -1; + while(++i < cursl) + curs[i] = *p++; + if(cursl < 8) + curs[cursl++] = '\t'; + else + curs[cursl++] = -1; + } + save(); + } + cs = SKIP; +} + +asw() +{ + switch(gch[fl]) { + + case 0: + if(cs == COLLECT) save(); + cs = SKIP; + flag[++fl] = &asw; + gch[fl] = c; + return(1); + + case '\'': + if(c == '\\') { + gch[fl] = c; + return(1); + } + break; + + case '"': + gch[fl] = '\''; + + if(c == '\\') { + flag[++fl] = &asw; + gch[fl] = c; + return(1); + } + return(1); + + case '<': + if(c == '\n') out(); + if(c == '\\') { + flag[++fl] = &asw; + gch[fl] = c; + return(1); + } + if(c != '>') return(1); + break; + + case '/': + if(c != '\n') return(1); + + case '\\': + if(c == '\n') out(); + + } + fl--; + return(1); + +} + +csw() +{ + if(cs == COLLECT) save(); + + switch(gch[fl]) { + + case 0: + if(c == '*') + if(line[l - 1] != '/') + return(1); + gch[++fl] = c; + flag[fl] = &csw; + return(1); + + case '*': + if(c == '\n') out(); + if(c == '/' && line[l - 1] == '*') + break; + return(1); + + case '\'': + case '"': + if(c == gch[fl]) + break; + if(c == '\\') { + gch[++fl] = c; + flag[fl] = &csw; + } + return(1); + + case '\\': + break; + } + fl--; + return(1); +} + +incl() +{ +/* printf("incl: l = %d hl = %d dl = %d\n",level,hlevel,dlevel);/*DEBUG*/ + if(cs == COLLECT) save(); + if(hlevel) { + hlevel = 0; + level++; + } else { + dlevel++; + } + + cs = SKIP; +} + +decl() +{ +/* printf("decl: l = %d hl = %d dl = %d\n",level,hlevel,dlevel);/*DEBUG*/ + if(cs == COLLECT) save(); + cs = SKIP; + if(dlevel) { + dlevel--; + return; + } + if(--level > 0) return; + curs[0] = '_'; + curs[1] = '\t'; + cursl = 2; + level = 0; + return; +} + +csym() +{ + int i; + char *p; + +/* printf("csym: l = %d hl = %d dl = %d\n",level,hlevel,dlevel);/*DEBUG*/ + p = temp[t1].beg; + if(cs == COLLECT && level == 0) { + if(cross) { + cursl = temp[t1].ct; + cursl = cursl>8?8:cursl; + i = -1; + while(++i < cursl) + curs[i] = *p++; + if(cursl < 8) + curs[cursl++] = '\t'; + else + curs[cursl++] = -1; + } + hlevel = 1; + } + cs = SKIP; +} + +dfile(a) + char *a; +{ + if(*a < 'c') return(0); + if(*a < 'h') return(1); + if(*a < 'r') return(2); + return(3); +} + + +sk2() +{ + cs = SKIP2; +} + +sk() +{ + cs = SKIP; +} + +tabs() +{ + if(l == 0) l = -1; +} + + +search(symbol,length,params,install) + char *symbol; + int length; + struct htab *params; + int install; +{ + char *sp,*p; + static int curb,*hptr,hsiz,nsym,ssiz; + static char *symt; + auto h,i,j,k; + + if(hptr != params->hptr) { + hptr = params->hptr; + hsiz = params->hsiz; + symt = params->symt; + ssiz = params->ssiz; + curb = params->curb; + nsym = params->nsym; + } + + symbol[length] = '\0'; + sp = symbol; + + i = length; + h = 1; + while(i--) + h =* *sp++; + + if(h == 0100000) { + h = 1; + } else { + h = h<0?(-h)%hsiz:h%hsiz; + } + if(h == 0) h++; +/* printf("%s %d\n",symbol,h); /*DEBUG*/ + + while((p = &symt[hptr[h]]) > symt) { + j = length + 2; + sp = symbol; + while(--j) { + if(*p++ != *sp++) goto no; + } + return(*p); +no: + h = (h + h)%hsiz; + } + if(install) { + if(++nsym >= hsiz) { + printf("Too many symbols.\n"); + dexit(); + } + + hptr[h] = curb; + length++; + if((curb + length) >= ssiz) { + printf("Too many characters in symbols.\n"); + dexit(); + } + + while(length--) + symt[curb++] = *symbol++; + symt[curb++] = install; + params->curb = curb; + params->nsym = nsym; + } + return(0); +} + +conf(n,width,buf) + char *buf; +{ + auto i,a; + + i = width; + while(i--) buf[i] = ' '; + + buf[(a = n/10)?conf(a,--width,buf):--width] = n%10 + '0'; + + return(++width); +} + + +comp(a,b) + char *a; + char *b; +{ + a--; + b--; + while(*++a == *++b) + if(*a == '\0') return(1); + return(0); +} + +semi() +{ + if(cs == COLLECT) save(); + if(only) return; + xtrn = 0; + if(!level) { + ssw = 0; + if(!type) { + hlevel = 0; + curs[0] = '_'; + curs[1] = '\t'; + cursl = 2; + } + type = 0; + } + cs = SKIP; +} + +wspace() +{ + if(c == ' ' || c == '\t') + return(1); + sav1(); + fl--; + return(0); +} + diff --git a/source/cref/src/crpost.c b/source/cref/src/crpost.c new file mode 100644 index 0000000..203de67 --- /dev/null +++ b/source/cref/src/crpost.c @@ -0,0 +1,265 @@ +/*int mbuf[1024]; /*INSTR*/ +int ig 100; +int esw; +int initf 1; +char ssp[270]; +char *sym[9] {ssp, + ssp + 30, + ssp + 60, + ssp + 90, + ssp + 120, + ssp + 150, + ssp + 180, + ssp + 210, + ssp + 240, + ssp + 270 + }; + +main(argc, argv) + char *argv[]; +{ + auto f,fct,file,i; + + if(argc < 2) { + printf("Usage: crpost [-d] file1 file2 ...\n"); + exit(); + } + + if(*argv[1] == '-') { + if(argv[1][1] == 'E') { + fct = 3; + esw = 1; + goto on; + } + fct = argv[1][1] - '0'; + if((fct < 1) || (fct > 9)) { + printf("-d: 0 < d < 10\n"); + exit(); + } + if(argv[1][2] == 'x') { + ig = fct-1; + } +on: + argv++; + argc--; + } else { + fct = 3; + } + + f = 0; + while(++f < argc) { + file = open(argv[f], 0); + + edf(file, fct); + + close(file); + } + flsh(0); + + exit(); +} + +int lno 1; + +edf(file, fct) +{ + auto i,j,l; + extern lno,etext; + char brk,*buf,bufsp[150],line[150]; + char extern *sym[]; + +/* monitor(&main,&etext,&mbuf,1024); /*INSTR*/ + for(i = 0; i < fct; i++) + *sym[i] = 0200; +fields: + l = -1; + buf = &bufsp; + + for(i = 0; i < fct; ++i) { + buf--; + +swt: + + switch(*++buf = get(file)) { + + default: + if(esw && *buf >= 'A' && *buf <= 'Z' + && i == 0) + *buf =| 040; + goto swt; + + case -1: + *buf = ' '; + case '\t': + if(i == ig) continue; + brk = *buf; + *buf = '\0'; + buf = &bufsp; + if(comp(buf, sym[i])) { + if(esw && i == 0) { + line[0] = line[1] = '\t'; + l = 1; + goto rest; + } + line[++l] = '\t'; + continue; + } else { + copy(buf, sym[i]); + l =+ copy(buf, &line[++l]); + line[--l] = brk; + if(l < 8 && esw && i == 0) + line[++l] = '\t'; + j = i; + while(++j < fct) + *sym[j] = 0200; + continue; + } + + case '\n': + lno++; + brk = *buf; + *buf = '\0'; + buf = &bufsp; + if(comp(buf, sym[i])) { + goto fields; + } else { + copy(buf, sym[i]); + l =+ copy(buf, &line[++l]); + line[--l] = '\n'; + j = i; + while(++j < fct) + *sym[j] = 0; + goto out; + } + + case '\0': + goto fexit; + } + } + +rest: + while((line[++l] = get(file)) != '\n') + if(line[l] == '\0') goto fexit; + + lno++; +out: + if(*line != '\t') { + put(0,"\n",1); + lno++; + } + + put(0,line,++l); + + goto fields; + +fexit: +/* monitor(0); /*INSTR*/ + return(0); + +} + + +copy(a, b) + char *a,*b; +{ + char *c; + + b--; + c = --a; + while(*++b = *++a); + return(a - c); +} + +comp(a, b) + char *a, *b; +{ +/* printf("comp: %s %s\n",a,b); /*DEBUG*/ + a--; + b--; + while(*++a == *++b) { + if(*a == '\0') return(1); + } + return(0); +} + + +char buf[512]; +int nread 1; + +get(ifile) int ifile; +{ + + char static *ibuf; + + if(--nread){ + return(*ibuf++); + } + + if(nread = read(ifile,buf,512)){ + if(nread < 0)goto err; + + ibuf = buf; + return(*ibuf++); + } + + nread = 1; + return(0); + +err: + nread = 1; + printf("read error\n"); + return(0); + +} + + +int tp[1] 1; +int optr[4]; +char bsp[512]; + +char *obuf[1] bsp; + +int nflush; + +put(fil,string,n) + char *string; +{ + int i; + char *o; + +/*printf("%d %c %d\n",fil,*string,n);/*DEBUG*/ + + string--; + + if((i = optr[fil] + n - 512) >= 0) { + n =- i; + o = &obuf[fil][optr[fil]] -1; + while(--n >= 0) + *++o = *++string; + optr[fil] = 512; + flsh(fil); + n = i; + } + + o = &obuf[fil][optr[fil]] - 1; + optr[fil] =+ n; + + while(--n >= 0) { + *++o = *++string; + } + return(0); +} + +flsh(fil) +{ + extern tp[]; + + if(optr[fil] <= 0) return(optr[fil]); + + nflush++; + if(write(tp[fil],obuf[fil],optr[fil]) != optr[fil]) + return(-1); + optr[fil] = 0; + return(0); +} + diff --git a/source/cref/src/dr.c b/source/cref/src/dr.c new file mode 100644 index 0000000..a604989 --- /dev/null +++ b/source/cref/src/dr.c @@ -0,0 +1,441 @@ +# +# include "../mcons.h" +# include "../ccmn.h" +/*int mbuf[1024]; /*INSTR*/ +/*int tbuf[36]; /*INSTR*/ + +int (*acts[])() {0, + &coll, + &save, + &out, + &asym, + &asw, + &csym, + &csw, + &incl, + &decl, + &sk2, + &sk, + &tabs, + &semi + }; + +char *tmp[5] {"/tmp/crt0a", + "/tmp/crt1a", + "/tmp/crt2a", + "/tmp/crt3a", + "/tmp/crt4a" + }; + +char *ignonl "/usr/lib/aign"; +char *gtab "/usr/lib/atab"; + +main(argc,argv) + char *argv[]; +{ + auto i,j,tm1,tm2,tm3; + char *fn,*av[8]; +/* extern etext; /*INSTR*/ + +/* monitor(&main,&etext,&mbuf,1024); /*INSTR*/ + if(argc < 2) { + printf("Usage: cref [-aceilosux] file1 ...\n"); + exit(); + } + + lbuf[4] = '\t'; + if(*argv[1] == '-') { + j = flags(argv); + argv =+ j; + argc =- j; + } + + init(); + + i = 0; + while(++i < argc) { + curs[0] = '_'; + curs[1] = '\t'; + curs[4] = '\t'; + cursl = 2; + + if(fopen(argv[i],ibuf1) < 0) { + printf("Can't open %s\n",argv[i]); + dexit(); + } + ibuf = ibuf1; + + curf[0] = '\t'; + curfl = 1; + while((curf[curfl] = *argv[i]++) != 0 && curfl <= 8) + if(curf[curfl++] == '/') curfl = 1; + + curf[curfl++] = '\t'; + if(curfl == 10) curf[9] = -1; +/* printf("%s %d\n",curf,curfl);/*DEBUG*/ + + lno = 1; + + driver(); + + close(file); + } + for(j = 0; j < 4;) { + flsh(j,0); + close(tp[j++]); + } + +/* monitor(0); /*INSTR*/ +/* dexit(); /*INSTR*/ + +/* times(tbuf); /*INSTR*/ +/* tm1 = tbuf[15]/6; /*INSTR*/ +/* tm2 = tbuf[19]/6; /*INSTR*/ +/* tm3 = tbuf[23]/6; /*INSTR*/ +/* printf("Prep: %d %d %d\n",tm1,tm2,tm3); /*INSTR*/ + + if(utmp) exit(); + fn = "/bin/sort"; + av[0] = "sort"; + av[1] = "-a"; + av[3] = "-o"; + av[5] = 0; + for(i = 0; i < 4; i++) { + av[4] = av[2] = tmp[i]; + callsys(fn,av); + if(utmp) break; + } + +/* times(tbuf); /*INSTR*/ +/* tm1 = tbuf[27]/6; /*INSTR*/ +/* tm2 = tbuf[31]/6; /*INSTR*/ +/* tm3 = tbuf[35]/6; /*INSTR*/ +/* printf("Sort: %d %d %d\n",tm1,tm2,tm3); /*INSTR*/ + + if(usw) { + fn = "/usr/bin/upost"; + av[0] = "upost"; + i = 0; + } else { + fn = "/usr/bin/crpost"; + av[0] = "crpost"; + av[1] = cross? "-4x": "-3"; + i = 1; + } + j = -1; + while(++j < 4) { + av[++i] = tmp[j]; + if(utmp) break; + } + av[++i] = 0; + + callsys(fn,av); + +/* times(tbuf); /*INSTR*/ +/* tm1 = tbuf[27]/6 - tm1; /*INSTR*/ +/* tm2 = tbuf[31]/6 - tm2; /*INSTR*/ +/* tm3 = tbuf[35]/6 - tm3; /*INSTR*/ +/* printf("Post: %d %d %d\n",tm1,tm2,tm3); /*INSTR*/ + + dexit(); +} + +driver() +{ + auto p; + +top: + l = -1; + while((c = line[++l] = getc(ibuf)) != -1) { + if(l >= 131) { + printf("Line too long: %d %s\n",lno,curf); + dexit(); + } + + if(c & 0200) { + printf("Illegal character: %o line %d\n",c,lno); + dexit(); + } + + if(fl) { + if((*flag[fl])()) + continue; + } + +/*printf("cs = %d cc = %c ca = %d\n",cs,c,tab[cs].cl[c]); /*DEBUG*/ + + if(p = tab[cs].cl[c]) + (*acts[p])(); + continue; + } + if(ibuf == ibuf1) return; + ibuf = ibuf1; + goto top; + +} + +init() +{ + int b[3]; + auto fi,i; + extern coll(),save(),out(),asym(),asw(),csym(),csw(); + extern incl(),decl(),sk(),sk2(); + extern dexit(); + + ibuf1 = &ib1; + ibuf2 = &ib2; + + xtab.hptr = &xpsp; + xtab.symt = &xssp; + xtab.hsiz = PTRX; + xtab.ssiz = CHARX; + xtab.nsym = 0; + xtab.curb = 1; + + itab.hptr = &ipsp; + itab.symt = &issp; + itab.hsiz = PTRI; + itab.ssiz = CHARI; + itab.nsym = 0; + itab.curb = 1; + + if((fi = open(gtab,0)) < 0) { + printf("Cannot open grammar table; see lem\n"); + dexit(); + } + + i = -1; + while(++i < NUMS) + if(read(fi,tab[i].cl,256) < 256) { + printf("Bad grammar table.\n"); + dexit(); + } + + close(fi); + + + if((fi = open(ignonl,0)) < 0) { + printf("Cannot open ignore/only file: %s\n",ignonl); + dexit(); + } + if((read(fi,b,6) == 6) && (b[0] == 0100200)) { + if(read(fi,itab.hptr,b[1]) < b[1]) { + printf("Cannot read ignore/only file: %s\n",ignonl); + dexit(); + } + if(read(fi,itab.symt,b[2]) < b[2]) { + printf("Cannot read ignore/only file: %s\n",ignonl); + dexit(); + } + close(fi); + } else { + close(fi); + compile(); + } + + if((signal(1,1) & 1) == 0) signal(1,&dexit); + if((signal(2,1) & 1) == 0) signal(2,&dexit); + if((signal(3,1) & 1) == 0) signal(3,&dexit); +/* signal(4,&dexit); + signal(5,&dexit); + signal(6,&dexit); + signal(7,&dexit); + signal(8,&dexit); + signal(10,&dexit); + signal(11,&dexit); + signal(12,&dexit); +*/ + if(utmp == 0) { + while((tp[4] = creat(tmp[4],0)) < 0) + tmp[4][9]++; + close(tp[4]); + tmp[0][9] = tmp[4][9]; + tmp[1][9] = tmp[4][9]; + tmp[2][9] = tmp[4][9]; + tmp[3][9] = tmp[4][9]; + tp[0] = creat(tmp[0],CREATC); + tp[1] = creat(tmp[1],CREATC); + tp[2] = creat(tmp[2],CREATC); + tp[3] = creat(tmp[3],CREATC); + } else { + if((tp[0] = creat(utmp,CREATC)) < 0) { + printf("Can't create user's temp file.\n"); + exit(); + } + } + + return; +} + +error(a) +{ + printf("Error %d\n",a); + dexit(); +} + +dexit() +{ + extern nflush; + +/* printf("nflush = %d\n",nflush); /*DEBUG*/ + if(tp[0] > 0 && utmp == 0) { + unlink(tmp[0]); + unlink(tmp[1]); + unlink(tmp[2]); + unlink(tmp[3]); + unlink(tmp[4]); + } + exit(); +} + +callsys(f,v) + char f[],*v[]; +{ + int t,status,i; + + if((t = fork()) == 0) { + execv(f,v); + printf("Can't find %s\n",f); + exit(1); + } else { + if(t == -1) { + printf("Try again\n"); + return(1); + } + } + + while(t != wait(&status)); +/* printf("Status = %o, %s\n",status,f); /*DEBUG*/ + if((t = (status & 0377)) != 0) { + if(t != 2) { + printf("Fatal error in %s\n",f); + printf("t = %d\n",t); + } + dexit(); + } + return((status>>8) & 0377); +} + +flags(argv) + char *argv[]; +{ + int j,xx; + char *ap; + + j = 1; + ap = argv[1]; + while(*++ap != '\0') { + switch(*ap) { + + default: + printf("Unrecognized flag: %c\n",*ap); + dexit(); + + case '1': /* Symbol first */ + order = 1; + continue; + + case '2': /* Current file first */ + order = 2; + continue; + + case '3': /* Current symbol first */ + order = 3; + continue; + + case 'a': /* Assembler */ + cflag = 0; + continue; + + case 'c': /* C */ + gtab = "/usr/lib/ctab"; + if(!xx) + ignonl = "/usr/lib/cign"; + cflag = 1; + continue; + + case 'e': /* English */ + gtab = "/usr/lib/etab"; + if(!xx) + ignonl = "/usr/lib/eign"; + continue; + + case 'i': /* Ignore file */ + if(!xx) { + xx = 1; + only = 0; + ignonl = argv[++j]; + } + continue; + + case 'l': /* Line numbers in col. 3 */ + cross = 0; + continue; + + case 'o': /* Only file */ + if(!xx) { + xx = 1; + only = 1; + ignonl = argv[++j]; + } + continue; + + case 's': /* Symbols in col. 3 */ + cross = 1; + continue; + + case 't': + utmp = argv[++j]; + tmp[0] = argv[j]; + continue; + + case 'u': /* Unique symbols only */ + usw = 1; + continue; + + case 'x': /* C externals */ + xsw = 1; + gtab = "/usr/lib/ctab"; + if(!xx) + ignonl = "/usr/lib/cign"; + cflag = 1; + continue; + } + } + return(j); +} + + +compile() +{ + char buf[40],*b; + int i,v; + + fopen(ignonl,ibuf1); + + b = buf - 1; + while((*++b = getc(ibuf1)) != -1) { + if(*b == '\n') { + *b = '\0'; + search(buf,b - buf,&itab,1); + b = buf - 1; + } else { + if(*b == '\t') { + v = 0; + while((i = getc(ibuf1)) != -1) { + if(i == '\n') break; + v = v*10 + (i - '0'); + } + search(buf,b - buf,&itab,v); + b = buf - 1; + } else { + if((b - buf) > 39) { + printf("Ignore/only symbol too long"); + dexit(); + } + } + } + } + close(ibuf1); + return; +} diff --git a/source/cref/src/put.c b/source/cref/src/put.c new file mode 100644 index 0000000..8967b10 --- /dev/null +++ b/source/cref/src/put.c @@ -0,0 +1,59 @@ +int bct[4]; +int optr[4]; +char bsp[2048]; + +char *obuf[4] {bsp, + bsp + 512, + bsp + 1024, + bsp + 1536 + }; + +int nflush; + +put(fil,string,n) + char *string; +{ + extern utmp; + int i; + char *o; + +/*printf("%d %c %d\n",fil,*string,n);/*DEBUG*/ + + string--; + + if((i = optr[fil] + n - 512) >= 0) { + n =- i; + o = &obuf[fil][optr[fil]] -1; + while(--n >= 0) + *++o = *++string; + optr[fil] = 512; + flsh(fil); + n = i; + } + + o = &obuf[fil][optr[fil]] - 1; + optr[fil] =+ n; + + while(--n >= 0) { + *++o = *++string; + } + return(0); +} + +flsh(fil) +{ + extern tp[],utmp; + + if(optr[fil] <= 0) return(optr[fil]); + + if(bct[fil]++ >= 128 && utmp == 0) { + printf("Wraparound temp file %d\n",fil); + dexit(); + } + nflush++; + if(write(tp[fil],obuf[fil],optr[fil]) != optr[fil]) + return(-1); + optr[fil] = 0; + return(0); +} + diff --git a/source/cref/src/upost.c b/source/cref/src/upost.c new file mode 100644 index 0000000..d75dc63 --- /dev/null +++ b/source/cref/src/upost.c @@ -0,0 +1,214 @@ +/*int mbuf[1024]; /*INSTR*/ +int psw 1; +int initf 1; + +main(argc, argv) + char *argv[]; +{ + auto f,fct,file; + + if(argc < 2) { + printf("Usage: cpost [-d] file1 file2 ...\n"); + exit(); + } + + if(*argv[1] == '-') { + fct = argv[1][1] - '0'; + if((fct < 1) || (fct > 9)) { + printf("-d: 0 < d < 10\n"); + exit(); + } + argv++; + argc--; + } else { + fct = 1; + } + + f = 0; + while(++f < argc) { + file = open(argv[f], 0); + + edl(file, fct); + + close(file); + psw = 0; + } + flsh(0); + + exit(); +} + +int lno 1; + +edl(file) +{ + auto t,l; + char static buf[20],fld[20],line[200]; + char c; +field: + t = -1; + while(((buf[++t] = get(file)) != '\t') && (buf[t] != -1)) + if(buf[t] == '\0') goto done; + + if((c = buf[t]) == -1) c = ' '; + buf[t] = '\0'; + if(comp(buf,fld)) { + lno++; + goto junk; + } else { + if(lno == 0) { + put(0,line,++l); + } + l = copy(buf,line); + copy(buf,fld); + line[--l] = c; + lno = 0; + goto fill; + } + +fill: + while((line[++l] = get(file)) != '\n') { + if(line[l] == -1) line[l] = ' '; + if(line[l] == '\0') goto done; + } + + goto field; + +junk: + while((*line = get(file)) != '\n') + if(*line == '\0') goto done; + + goto field; + +done: + if(lno == 0) + put(0,line,++l); + lno = 1; + return(0); + +} + + + +gfld(file, buf) + char *buf; +{ + char c; + + buf--; + while(*++buf = get(file)) { + if((*buf == '\t') || (*buf == '\n')) { + c = *buf; + *buf = '\0'; + return(c); + } else { + continue; + } + } + return('\0'); +} + +copy(a, b) + char *a,*b; +{ + char *c; + + b--; + c = --a; + while(*++b = *++a); + return(a - c); +} + +comp(a, b) + char *a, *b; +{ +/* printf("comp: %s %s\n",a,b); /*DEBUG*/ + a--; + b--; + while(*++a == *++b) { + if(*a == '\0') return(1); + } + return(0); +} + + +char buf[512]; +int nread 1; + +get(ifile) int ifile; +{ + + char static *ibuf; + + if(--nread){ + return(*ibuf++); + } + + if(nread = read(ifile,buf,512)){ + if(nread < 0)goto err; + + ibuf = buf; + return(*ibuf++); + } + + nread = 1; + return(0); + +err: + nread = 1; + printf("read error\n"); + return(0); + +} + + +int tp[1] 1; +int optr[4]; +char bsp[512]; + +char *obuf[1] bsp; + +int nflush; + +put(fil,string,n) + char *string; +{ + int i; + char *o; + +/*printf("%d %c %d\n",fil,*string,n);/*DEBUG*/ + + string--; + + if((i = optr[fil] + n - 512) >= 0) { + n =- i; + o = &obuf[fil][optr[fil]] -1; + while(--n >= 0) + *++o = *++string; + optr[fil] = 512; + flsh(fil); + n = i; + } + + o = &obuf[fil][optr[fil]] - 1; + optr[fil] =+ n; + + while(--n >= 0) { + *++o = *++string; + } + return(0); +} + +flsh(fil) +{ + extern tp[]; + + if(optr[fil] <= 0) return(optr[fil]); + + nflush++; + if(write(tp[fil],obuf[fil],optr[fil]) != optr[fil]) + return(-1); + optr[fil] = 0; + return(0); +} + diff --git a/source/cref/tab/atable b/source/cref/tab/atable new file mode 100644 index 0000000..36cafa9 --- /dev/null +++ b/source/cref/tab/atable @@ -0,0 +1,214 @@ +skip +collect save +skip2 sk + +cont coll save out asym agobl csym cgobl incl decl sk2 sk + +collect/'/agobl; +collect/"/agobl; +collect/= NUMA) error(4); + bfl = nlfl = 0; + act[t1][++t2<8?t2:7] = c; + continue; + + case '\n': + if(nlfl) break; + nlfl = 1; + + case ' ': + if(bfl) continue; + bfl = 1; + act[t1][++t2<8?t2:7] = '\0'; + ac[t1] = &act[t1]; + t1++; + t2 = -1; + continue; + } + break; + } + if(c == '\0') exit(); + + i = -1; + while(++i < NUMS) { + if(df[i]) { + cd = find(ac,df[i],NUMA); + j = -1; + while(++j < NUMC) + tab[i].cl[j] = cd; + } + } + + + fl = 0; + i = -1; + while(c = getchar()) { + + switch(c) { + + case '\\': + temp[++i] = getchar(); + continue; + + case '\n': + if(fl != 1) continue; + + default: + temp[++i] = c; + continue; + + case '/': + temp[++i] = '\0'; + i = -1; + switch(fl) { + case 0: + cs = find(st,temp,NUMS); + fl = 1; + continue; + + case 1: + cc = find(cl,temp,NUMC); + fl = 2; + continue; + + default: + error(1); + + } + + case ';': + + if(fl != 2) error(2); + + temp[++i] = '\0'; + i = -1; + ca = find(ac,temp,NUMA); + +/*printf("%o %o %o\n",cs,cc,ca); /*DEBUG*/ + tab[cs].cl[cc] = ca; + + fl = 0; + continue; + + + } + } + + i = -1; + while(++i < NUMS) + write(fo,tab[i].cl,256); + +} + +error(a) +{ + + printf("Error %d\n",a); + exit(); + +} + +find(a,b,c) char (*a[])[]; + char b[]; + int c; +{ + int i,j; + +/* printf("%s\n",b); /*DEBUG*/ + i = -1; + while(++i < c) { +/* printf(" %s\n",a[i]); /*DEBUG*/ + j = 0; +/* printf("b = %c\ta = %c\n",b[0],(*a[i])[0]); /*DEBUG*/ + while(b[j] == (*a[i])[j]) { + if(b[j] == '\0') goto found; + j++; + } + } +found: + return(i); +} + +rword() { + + char c; + int ct; + + ct = -1; + while(c = getchar()) { + switch(c) { + + default: + temp[++ct] = c; + continue; + + case '\n': + if(ct == -1) return('\0'); + case ' ': + temp[++ct] = '\0'; + return(c); + } + } +} + +move(a,b) char *a; + char *b; +{ + while((*b++ = *a++) != '\0'); + return; +} + diff --git a/source/fort/f1/f11.s b/source/fort/f1/f11.s new file mode 100644 index 0000000..945ef54 --- /dev/null +++ b/source/fort/f1/f11.s @@ -0,0 +1,150 @@ +/ +/ + +/ f11 -- fortran command +/ + +.globl pass1 + +.globl fptrap +.globl getline +.globl flush +.globl perror +.globl lookup +.globl getype +.globl ssubr +.globl sfunc +.globl sbloc +.globl sextr +.globl sdime +.globl scomm +.globl sequi +.globl sdata +.globl sform +.globl simpl +.globl stype +.globl isagn +.globl ptemp +.globl funok +.globl signoff +.globl fopen +.globl fcreat +.globl lookid +.globl tfil1, tfil2 +.globl tfildiag + +pass1: + sys signal; 4; fptrap + cmp (sp)+,$2 + bge 1f +2: + mov $1,r0 + sys write; mes2; emes2-mes2 + clr r0 + sys seek; 0; 2 + mov $-1,r0 / bad status + sys exit +1: + tst (sp)+ + mov (sp)+,r0 + jsr r5,fopen; ibuf + bcs 2b + mov $tfil1,r0 + jsr r5,fcreat; obuf + bcs 2f + mov $tfil2,r0 + jsr r5,fcreat; tbuf + bcc 1f +2: + jmp tfildiag +1: + +/ data segment initialization + + mov $2,nxtaloc + mov $errb,errp + mov $esymtab,esymp + mov $namebuf,namep + movb $'_,symbuf-1 + jsr r5,lookid; blankc + bis $40,symtab(r3) + mov $imptab,r3 +1: + mov $realcon,r0 / real*4 + cmp r3,$imptab+[2*['i-'a]] + blo 2f + cmp r3,$imptab+[2*['n-'a]] + bhi 2f + mov $intcon,r0 / integer*4 +2: + mov r0,[2*26.](r3) / lower case + mov r0,(r3)+ / upper case + cmp r3,$imptab+[2*26.] + blo 1b + +/ call pass1 + +/ main scan loop for pass1 +/ picks up non executable statements +/ + +scan1: + jsr r5,getline + mov $line,r1 + jsr r5,isagn + br 2f + mov r1,r2 + jsr r5,lookup; stmtab + br 1f + mov r2,r1 + jsr r5,*sublst(r0) + mov pc,funok + jsr r5,perror + br scan1 +1: + jsr r5,getype + br 2f + mov r2,r1 + jsr r5,stype + jsr r5,perror + mov pc,funok + br scan1 +2: + jsr r5,ptemp; 'l; efno; line + jsr r5,flush; tbuf + jsr r5,signoff; 1 + +sublst: + ssubr + sfunc + sbloc + sextr + sdime + scomm + sequi + sdata + sform + simpl + +stmtab: + + + + + + + + + + + <\0> + .even + + +mes2: + +emes2: +blankc: + <_\n\0> + .even + diff --git a/source/fort/f1/f12.s b/source/fort/f1/f12.s new file mode 100644 index 0000000..6e54e00 --- /dev/null +++ b/source/fort/f1/f12.s @@ -0,0 +1,94 @@ +/ +/ + +/ f12 -- type statements and type getter subroutine +/ +/ + +.globl stype +.globl getype +.globl typtab + +.globl sfunc1 +.globl lookup +.globl getsym +.globl error +.globl sdime1 + +stype: + mov r0,-(sp) + mov r1,r2 + jsr r5,lookup; funtab + br 1f + mov r2,r1 + mov (sp)+,r0 + jmp sfunc1 +1: + jsr r5,getsym + tst r0 + bne 3f / junk error if not identifier + mov symtab(r3),r0 + bic $![377\<8+7],r0 / size,type + beq 2f + cmp r0,(sp) / redefined, but same + beq 2f + jsr r5,error; 3. +2: + bic $377\<8+7,symtab(r3) + bis (sp),symtab(r3) / set in type and size + mov r3,-(sp) + jsr r5,getsym + cmp r0,$32. / ( for dimension + bne 2f + mov (sp),r3 + jsr r5,sdime1 + jsr r5,getsym +2: + tst (sp)+ + cmp r0,$36. / , for another list element + beq 1b + cmp r0,$40. / eos + beq 1f +3: + jsr r5,error; 2. / junk +1: + tst (sp)+ + rts r5 + +funtab: + + <\0> + +getype: + mov r1,r2 + jsr r5,lookup; typtab + br 1f + mov tvaltab(r0),r0 + tst (r5)+ +1: + rts r5 + +tvaltab: + log1con + logcon + int1con + int2con + intcon + dcplxcon + dblcon + cplxcon + dblcon + realcon + +typtab: + + + + + + + + + + + <\0> diff --git a/source/fort/f1/f13.s b/source/fort/f1/f13.s new file mode 100644 index 0000000..22e290e --- /dev/null +++ b/source/fort/f1/f13.s @@ -0,0 +1,101 @@ +/ +/ + +/ f13 -- dimension and array declarator +/ +/ dimension +/ +/ +.globl sdime +.globl sdime1 + +.globl getsym +.globl error +.globl geti +.globl dimu + +sdime: + jsr r5,getsym + tst r0 + bne 3f / junk error + mov r3,-(sp) + jsr r5,getsym + mov (sp)+,r3 + cmp r0,$32. / ( + beq 2f + jsr r5,error; 4. / no ( in dimension + rts r5 +2: + jsr r5,sdime1 + jsr r5,getsym + cmp r0,$36. / , + beq sdime + cmp r0,$40. + beq 1f +3: + jsr r5,error; 5. +1: + rts r5 + +/ get dimension info and store in +/ symbol table entry +/ r3 points at symbol table +/ r1 points just beyond ( +sdime1: + bit $70,symtab(r3) / class + beq 1f + jsr r5,error; 6. / already classed +1: + mov r3,-(sp) + bic $70,symtab(r3) + bis $20,symtab(r3) / set as array + clr -(sp) / marker +1: + jsr r5,getsym + cmp r0,$2 / constant + bne 2f + cmp r3,$intcon / integer*4 + bne 3f + jsr r5,geti + tst r0 + ble 3f + mov r0,-(sp) + br 4f +2: + tst r0 + bne 3f / identifer + tstb symtab(r3) + bge 3f / not parameter + neg r3 + mov r3,-(sp) + mov sp,r0 +2: + tst (r0)+ + bne 2b + mov (r0),r0 + tstb symtab(r0) + bge 3f / array not a param +4: + jsr r5,getsym + cmp r0,$36. / , + beq 1b + cmp r0,$34. / ) + beq 1f +3: + jsr r5,error; 7. +1: + mov esymp,r0 + clr r2 + mov dimu,-(r0) + inc dimu / unique number +1: + inc r2 + mov (sp)+,-(r0) + bne 1b + dec r2 + mov r2,(r0) + mov r0,esymp + mov (sp)+,r3 + mov r0,symtab+2(r3) + rts r5 + diff --git a/source/fort/f1/f14.s b/source/fort/f1/f14.s new file mode 100644 index 0000000..88bb4ff --- /dev/null +++ b/source/fort/f1/f14.s @@ -0,0 +1,85 @@ +/ +/ + +/ f14 -- common statement +/ + +.globl scomm + +.globl getsym +.globl sdime1 +.globl error +.globl getid +.globl lookid + +scomm: + mov r5,-(sp) + jsr r5,getsym + cmp r0,$6 / / for named common + beq ncom +3: + tst r0 + bne 9f + mov r3,-(sp) + clr r5 + br 2f + +ncom: + cmpb (r1),$'/ + bne 3f + inc r1 + jsr r5,getsym + br 3b +3: + jsr r5,getid + br 9f / not identifier + jsr r5,lookid; symbuf-1 + bis $40,symtab(r3) / set named common + mov r3,r5 + jsr r5,getsym + cmp r0,$6 / / + bne 9f +1: + jsr r5,getsym + tst r0 + bne 9f + mov r3,-(sp) +2: + jsr r5,getsym + cmp r0,$32. / ( + bne 2f + mov (sp),r3 + jsr r5,sdime1 + jsr r5,getsym +2: + mov (sp)+,r3 + bit $300,symtab(r3) / test param/common + beq 2f + jsr r5,error; 9. / not commonable or already commoned + br 3f +2: + mov r0,-(sp) + mov symtab+4(r5),r0 + beq 2f + mov r3,symtab+4(r0) / next ptr of old last block +2: + mov (sp)+,r0 + mov r3,symtab+4(r5) / new last ptr of head block + tst symtab+2(r5) + bne 3f + mov r3,symtab+2(r5) / first ptr if first block +3: + bis $100,symtab(r3) + cmp r0,$36. / , + beq 1b + cmp r0,$6 / another / + beq ncom + cmp r0,$40. / =| + beq 8f +9: + jsr r5, error; 10. / common syntax error +8: + mov (sp)+,r5 + rts r5 + + diff --git a/source/fort/f1/f15.s b/source/fort/f1/f15.s new file mode 100644 index 0000000..f0eb35a --- /dev/null +++ b/source/fort/f1/f15.s @@ -0,0 +1,86 @@ +/ +/ + +/ f15 -- subroutine/function + +.globl ssubr +.globl sfunc +.globl sbloc +.globl sfunc1 +.globl funok + +.globl getsym +.globl error + +ssubr: + mov $2,progt + br 1f + +sfunc: + mov $4,progt +1: + clr r0 + br 2f + +sfunc1: + mov $4,progt +2: + tst funok + beq 1f + jsr r5,error; 11. +1: + add $10,r0 / class=simple + mov r0,-(sp) + jsr r5,getsym + mov (sp)+,r2 + tst r0 + beq 1f +2: + jsr r5,error; 12. + rts r5 +1: + mov r2,symtab(r3) + jsr r5,getsym + cmp r0,$32. / ( + beq 1f + cmp r0,$40. / eos + bne 2b + rts r5 +1: + clr -(sp) +1: + add $2,(sp) + jsr r5,getsym + tst r0 + beq 3f + tst (sp)+ + br 2b +3: + bis $200,symtab(r3) / param + mov (sp),symtab+6(r3) / param number + jsr r5,getsym + cmp r0,$36. / , + beq 1b + tst (sp)+ + cmp r0,$34. / ) + bne 2b + jsr r5,getsym + cmp r0,$40. + bne 2b + rts r5 + +sbloc: + mov $6,progt + jsr r5,getsym + tst funok + beq 1f + jsr r5,error; 11. +1: + cmp r0,$40. + beq 1f + jsr r5,error; 13. +1: + rts r5 + +.data +funok: 0 diff --git a/source/fort/f1/f16.s b/source/fort/f1/f16.s new file mode 100644 index 0000000..995ccd6 --- /dev/null +++ b/source/fort/f1/f16.s @@ -0,0 +1,37 @@ +/ +/ + +/ f16 -- extrn, equiv, data + +.globl sextr +.globl sequi + +.globl getsym +.globl putc +.globl error +.globl ptemp + +sextr: + jsr r5,getsym + tst r0 + bne 1f + bit $70,symtab(r3) + beq 2f + jsr r5,error; 14. +2: + bis $30,symtab(r3) + jsr r5,getsym + cmp r0,$36. / , + beq sextr + cmp r0,$40. / eos + beq 2f +1: + jsr r5,error; 15. +2: + rts r5 + +sequi: + jsr r5,ptemp; 'e; efno; line + rts r5 + + diff --git a/source/fort/f1/f17.s b/source/fort/f1/f17.s new file mode 100644 index 0000000..5348c1d --- /dev/null +++ b/source/fort/f1/f17.s @@ -0,0 +1,70 @@ +/ +/ + +/ f17 -- implicit statement + +.globl simpl + +.globl getype +.globl chrtab +.globl error + +simpl: + jsr r5,getype + br 9f + mov r2,r1 + mov r0,-(sp) + movb (r1)+,r0 + cmp r0,$'( + beq 1f + cmpb r0,$'/ + bne 8f +1: + movb (r1)+,r0 + cmpb chrtab(r0),$2 + bne 8f + cmpb r0,$'a + blo 2f + sub $6,r0 / map 'a into 'Z+1 +2: + movb (r1)+,r2 + cmpb r2,$'- + bne 2f + movb (r1)+,r2 + cmpb chrtab(r2),$2 + bne 8f + cmp r2,$'a + blo 3f + sub $6,r2 / map 'a into 'Z+1 + br 3f +2: + mov r0,r2 + dec r1 +3: + cmp r0,r2 + bhi 8f + asl r0 + asl r2 +3: + mov (sp),imptab-[2*'A](r0) + add $2,r0 + cmp r0,r2 + blos 3b + movb (r1)+,r0 + cmp r0,$', + beq 1b + tst (sp)+ + cmp r0,$') + beq 1f + cmp r0,$'/ + bne 9f +1: + tstb (r1) + bne simpl + rts r5 +8: + tst (sp)+ +9: + jsr r5,error; 16. / implicit syntax error + rts r5 + diff --git a/source/fort/f2/f21.s b/source/fort/f2/f21.s new file mode 100644 index 0000000..95b4977 --- /dev/null +++ b/source/fort/f2/f21.s @@ -0,0 +1,24 @@ +/ +/ + +/ f21 -- storage allocation +/ + +.globl pass2 + +.globl signon +.globl signoff +.globl calloc +.globl salloc +.globl equiv +.globl entry + +pass2: + jsr r5,signon; 2 + mov $errb,errp + jsr r5,calloc + jsr r5,equiv + jsr r5,salloc + jsr r5,entry + jsr r5,signoff; 2 + diff --git a/source/fort/f2/f22.s b/source/fort/f2/f22.s new file mode 100644 index 0000000..65c99f9 --- /dev/null +++ b/source/fort/f2/f22.s @@ -0,0 +1,125 @@ +/ +/ + +/ f22 -- allocate common + +.globl calloc +.globl entry + +.globl declimpl +.globl size +.globl getc +.globl getw +.globl xbuf +.globl code +.globl typ + +calloc: + clr r3 +1: + cmp r3,symtp + bhis 1f + mov symtab(r3),r0 + bic $!70,r0 / class + cmp r0,$40 / common block + bne 3f + mov r3,-(sp) + mov symtab+2(r3),r3 + clr r2 / byte offset +2: + tst r3 + beq 2f + jsr r5,declimpl + mov symtab+4(r3),-(sp) + mov 2(sp),symtab+4(r3) + mov r2,symtab+6(r3) + jsr r5,size + add r0,r2 + mov (sp)+,r3 + br 2b +2: + mov (sp)+,r3 + clr symtab+2(r3) + mov r2,symtab+6(r3) / common block size +3: + add $8,r3 + br 1b +1: + rts r5 + +entry: + mov progt,r0 + jmp *1f(r0) +1: + main + subr + funct + blocd + +main: + jsr r5,code + ; .even + rts r5 + +subr: +funct: + jsr r5,code + <%n.: %n_\n\0>; .even + 8 + 8 + clr r3 +1: + cmp r3,symtp + bhis 1f + mov symtab+2(r3),r0 + beq 2f + mov (r0)+,r1 / num dims + asl r1 + add r0,r1 / ptr to last dim + mov r3,-(sp) + mov (r1),-(sp) / dope id + clr r2 / dope offset +3: + add $2,r2 + mov -(r1),r3 + cmp r0,r1 + bhi 3f + neg r3 / adjustable dimension + ble 3b + mov r0,-(sp) + jsr r5,declimpl + mov symtab(r3),r0 + clrb r0 + swab r0 + jsr r5,code + < rval%dp; %n_\n\0>; .even + r0 + r3 + mov symtab(r3),r3 + bic $![377\<8+7],r3 + cmp r3,$2\<8+1 / is it i*2 + beq 4f + bic $!7,r3 + movb typ(r3),r3 + jsr r5,code + < %c%di2\n\0>; .even + r3 + r0 +4: + mov 2(sp),r0 + jsr r5,code + < stst; d%d+%d.\n\0>; .even + r0 + r2 + mov (sp)+,r0 + br 3b +3: + tst (sp)+ + mov (sp)+,r3 +2: + add $8,r3 + br 1b +1: +blocd: + rts r5 + diff --git a/source/fort/f2/f23.s b/source/fort/f2/f23.s new file mode 100644 index 0000000..dae8b4e --- /dev/null +++ b/source/fort/f2/f23.s @@ -0,0 +1,120 @@ +/ +/ + +/ f23 -- do equivalence statements + +.globl equiv + +.globl getsym +.globl consub +.globl eqvtab +.globl error +.globl declimpl +.globl perror +.globl setln +.globl getln + +/ equivalence statements, part 1 +/ destroys all registers + +equiv: + jsr r5,setln +1: + jsr r5,getln + rts r5 + cmp r0,$'e + bne 1b + mov $line+11.,r1 + mov r5,-(sp) +2: / start equivalence group + cmpb (r1)+,$'( / check ( + bne 9f / syntax error + jsr r5,getsym + tst r0 + bne 9f / not identifier + mov r3,r5 + jsr r5,equset + movb (r1)+,r2 + clr r4 / offset + cmp r2,$', + beq 3f + cmp r2,$'( / subscripted vble + bne 9f / syntax error + jsr r5,consub / get subscript + mov r0,r4 + cmpb (r1)+,$', + bne 9f +3: / rest of group + jsr r5,getsym / next ident + tst r0 + bne 9f / syntax + jsr r5,equset + clr r0 + mov r3,r2 + cmpb (r1),$'( / subscript? + bne 4f + inc r1 + jsr r5,consub +4: + mov eqvtab+2(r2),r2 + cmp r2,r5 + beq 5f / already in same group + cmp r2,r3 + bne 4b / not yet in different group + sub r4,r0 / adjust offsets + sub eqvtab+4(r5),r0 / left vble's offset + add eqvtab+4(r3),r0 / new vble's offset +4: + sub r0,eqvtab+4(r2) + mov eqvtab+2(r2),r2 + cmp r2,r3 + bne 4b + mov eqvtab+2(r3),r0 / link up groups + mov eqvtab+2(r5),eqvtab+2(r3) + mov r0,eqvtab+2(r5) / link groups + br 6f +5: / here already in same group + cmp r0,r4 / offset must be same + beq 6f + jsr r5,error; 23. / inconsistency! +6: + movb (r1)+,r0 + cmp r0,$', + beq 3b + cmp r0,$') + bne 9f + movb (r1)+,r0 + bne 3f + jsr r5,perror + mov (sp)+,r5 + br 1b +3: + cmp r0,$', + beq 2b +9: + jsr r5,error; 24. / equivalence syntax + jsr r5,perror + mov (sp)+,r5 + br 1b + +/ initialize member of equivalence group + +equset: + jsr r5,declimpl / declare if necessary + mov symtab(r3),r0 + bit $200,r0 / test parameter + bne 2f + bic $!70,r0 + cmp r0,$10 / simple + beq 1f + cmp r0,$20 / array + beq 1f +2: + jsr r5,error; 31. / non-equivalencable variable +1: + tst eqvtab+2(r3) / see if mentioned yet + bne 1f + mov r3,eqvtab+2(r3) / points to itself +1: + rts r5 + diff --git a/source/fort/f2/f24.s b/source/fort/f2/f24.s new file mode 100644 index 0000000..da133f8 --- /dev/null +++ b/source/fort/f2/f24.s @@ -0,0 +1,130 @@ +/ +/ + +/ f24 -- allocate storage for non-common variables +/ called after common and equivalence have been done + +.globl salloc + +.globl eqvtab +.globl error +.globl declimpl +.globl size +.globl perror + +/ destroys all registers + +salloc: + mov r5,-(sp) + clr r3 / loop over symbol table + br 2f +1: + add $8.,r3 / next variable +2: + + cmp r3,symtp + blo 2f + mov (sp)+,r5 + mov $line,r1 + jsr r5,perror / flush errors + rts r5 +2: + bit $70,symtab(r3) + beq 1b / unclassed + jsr r5,declimpl / just in case + tst eqvtab(r3) / test for already allocated + bne 1b / yes + mov symtab(r3),r0 + bic $!70,r0 + cmp r0,$10 / test class=simple + beq 2f + cmp r0,$20 / test array + bne 1b / no, not a variable +2: + bit $200,symtab(r3) / test parameter + bne 1b + tst eqvtab+2(r3) / test for equivalence + bne 2f / yes + bit $100,symtab(r3) / test common + bne 1b / yes, nothing to do + mov nxtaloc,symtab+6(r3) / offset + jsr r5,size / get byte count + add r0,nxtaloc + inc eqvtab(r3) / mark allocated + br 1b +2: + clr r4 / common variable of group + mov $77777,r1 / infinity to smallest offset + mov r3,r5 +2: + cmp eqvtab+4(r3),r1 + bgt 3f + mov eqvtab+4(r3),r1 / replace smallest offset +3: + bit $100,symtab(r3) / test common + beq 3f + mov r3,r4 / yes +3: + mov eqvtab+2(r3),r3 / next group member + cmp r3,r5 + bne 2b + tst r4 + bne 2f / *there was a common in group + / equivalence group w/o common + sub nxtaloc,r1 / get -(group offset) +3: + inc eqvtab(r3) / mark allocated + mov eqvtab+4(r3),r2 + sub r1,r2 / compute offset + mov r2,symtab+6(r3) / enter offset + jsr r5,size + add r0,r2 / highest loc of variable + cmp r2,r4 + ble 4f + mov r2,r4 / extends storage +4: + mov eqvtab+2(r3),r3 / next of group + cmp r3,r5 + bne 3b + mov r4,nxtaloc / account for space + br 1b / done! +2: / equivalence group w/ common + mov symtab+6(r4),r1 / actual common offset + sub eqvtab+4(r4),r1 / virtual common offset +2: + inc eqvtab(r3) / mark allocated + bit $100,symtab(r3) / is variable already in common + beq 3f / *no + cmp symtab+4(r4),symtab+4(r3) + beq 4f + jsr r5,error; 25. / different blocks equiv. +4: + mov r1,r0 + add eqvtab+4(r3),r0 + cmp r0,symtab+6(r3) + beq 4f / ok + jsr r5,error; 27. / same variable, different offsets + br 4f +3: + bis $100,symtab(r3) / mark common now + mov symtab+4(r4),symtab+4(r3)/ get right common block + mov r1,r0 + add eqvtab+4(r3),r0 + bge 3f + jsr r5,error; 26. / block extended leftward + clr r0 +3: + mov r0,symtab+6(r3) / get proper offset + mov r0,-(sp) + jsr r5,size / see if size is extended + add (sp)+,r0 + mov symtab+4(r3),r2 / common block + cmp symtab+6(r2),r0 + bge 4f / ok + mov r0,symtab+6(r2) / extend size +4: + mov eqvtab+2(r3),r3 + cmp r3,r5 + bne 2b + jmp 1b + diff --git a/source/fort/f3/f31.s b/source/fort/f3/f31.s new file mode 100644 index 0000000..741c3d5 --- /dev/null +++ b/source/fort/f3/f31.s @@ -0,0 +1,179 @@ +/ +/ + +/ f31 - pass3 dispatcher +/ +/ main scan loop for pass3 +/ picks up executable statements +/ + +.globl pass3 +.globl ifstmt + +.globl isagn +.globl signon +.globl signoff +.globl getline +.globl lookup +.globl sasgn +.globl error +.globl perror +.globl doend +.globl sform +.globl sdata +.globl sdo +.globl sassi +.globl scall +.globl scont +.globl sretu +.globl sgoto +.globl sif +.globl spaus +.globl sstop +.globl sread +.globl sprin +.globl swrit +.globl srewi +.globl sback +.globl sendf +.globl blocks +.globl blockp +.globl code +.globl ptemp +.globl dotabp + +pass3: + jsr r5,signon; 3 + br 2f + +scan3: + jsr r5,getline +2: + mov $blocks,blockp + mov $line,r1 + mov r1,r2 + jsr r5,lookup; fmttab + br 2f + mov r0,-(sp) + jsr r5,isagn + br 1f + mov (sp)+,r0 + jsr r5,*fmtlst(r0) + br scan3 +1: + tst (sp)+ +2: + mov efno,r0 + beq 1f + jsr r5,ptemp; 's; efno; line + jsr r5,code + <.%d:\n\0>; .even + r0 +1: + jsr r5,isagn + br 1f + mov r1,r2 + jsr r5,lookup; stmtab + br 2f + mov r2,r1 + jsr r5,*sublst(r0) + br 3f +1: + jsr r5,sasgn + br 3f +2: + jsr r5,error; 101. +3: + cmp progt,$6 + bne 1f + jsr r5,error; 50. / execut in block data +1: + jsr r5,perror + mov efno,r0 + beq scan3 + jsr r5,doend + br scan3 + +ifstmt: + mov $blocks,blockp + jsr r5,isagn + br 1f + mov r1,r2 + jsr r5,lookup; stmtab1 + br 2f + mov r2,r1 + cmp r0,$4 / don't allow end + beq 2f + jmp *sublst1(r0) +1: + jmp sasgn +2: + jsr r5,error; 101. + rts r5 + +send: + tst dotabp + beq 1f + clr r0 + jsr r5,doend + br send +1: + tst progt + bne 1f + jsr r5,sstop + br 2f +1: + cmp progt,$6 / block data + beq 2f + jsr r5,sretu +2: + jsr r5,perror + jsr r5,signoff; 3 + +sublst: + sdo +sublst1: + sif + sendf + send + sassi + scall + scont + sretu + sgoto + spaus + sstop + sread + sprin + swrit + srewi + sback +fmtlst: + sform + sdata +stmtab: + +stmtab1: + + + / keep in this spot!!! + + + + + + + + + + + + + <\0> + +fmttab: + + + <\0> + .even + diff --git a/source/fort/f3/f32.s b/source/fort/f3/f32.s new file mode 100644 index 0000000..ba0ccaa --- /dev/null +++ b/source/fort/f3/f32.s @@ -0,0 +1,227 @@ +/ +/ + +/ f32 -- expression to tree + +.globl e1 +.globl e2 +.globl e11 + +.globl error +.globl getsym +.globl blockp +.globl blocks +.globl declimpl +.globl conu +.globl ptemp +.globl functn +.globl funimpl + +/ e1: e2[,e1] +/ e2: e2[.or.e3] +/ e3: e3[.and.e4] +/ e4: [.not.]e5 +/ e5: e6[.rel.e6] +/ e6: [+-]e7[+-e6] +/ e7: e7[*/e8] +/ e8: e9[**e9] +/ e9: constant +/ name[(e1)] +/ (e2) +e1: + jsr r5,e2 + cmp r0,$36. / , + bne 1f + jsr r5,block; e1 + rts r5 + +e2: + jsr r5,e3 +2: + cmp r0,$30. / or + bne 1f + jsr r5,block; e3 + br 2b + +e3: + jsr r5,e4 +2: + cmp r0,$28. / and + bne 1f + jsr r5,block; e4 + br 2b + +e4: + jsr r5,getsym + cmp r0,$26. / not + bne e5 + clr r2 + jsr r5,block; e5a + rts r5 + +e5a: + jsr r5,getsym +e5: + jsr r5,e6 + cmp r0,$14. / .lt. + blo 1f + cmp r0,$24. / .ge. + bhi 1f + jsr r5,block; e6a + rts r5 + +e6a: + jsr r5,getsym +e6: + cmp r0,$12. / + + beq e6a + cmp r0,$10. / - + bne 2f + clr r2 + jsr r5,block; e7a + br 3f +2: + jsr r5,e7 +3: + cmp r0,$10. / - + blo 1f + cmp r0,$12. / + + bhi 1f + jsr r5,block; e7a + br 3b + +e7a: + jsr r5,getsym +e7: + jsr r5,e8 +2: + cmp r0,$6. / / + blo 1f + cmp r0,$8. / * + bhi 1f + jsr r5,block; e8a + br 2b + +e8a: + jsr r5,getsym +e8: + jsr r5,e9 + cmp r0,$4 / ** + bne 1f + jsr r5,block; e9a +1: + rts r5 + +e9a: + jsr r5,getsym +e9: + cmp r0,$2 / constant + beq 3f +/ (e2) + cmp r0,$32. / ( + bne 1f + jsr r5,e2 + br 2f +e10: + jsr r5,e1 +2: + cmp r0,$34. / ) + beq 2f + jsr r5,error; 29. + rts r5 +2: + jsr r5,getsym + rts r5 +1: + tst r0 + beq e11 +/ unknown + jsr r5,error; 30. + rts r5 + +/ name +e11: + mov r3,r2 + jsr r5,getsym + cmp r0,$32. / ( + bne 1f + jsr r5,appl + jsr r5,block; e10 + rts r5 +1: + mov r2,r3 + mov r0,-(sp) + jsr r5,declimpl + mov symtab(r3),r0 + bic $!70,r0 + cmp r0,$30 / class =| funct + bne 1f + jsr r5,appl + mov $42.,r3 / just function name + br 2f +1: + clr r3 +2: + mov (sp)+,r0 + mov r2,-(sp) + mov blockp,r2 + add $6,blockp + mov r3,(r2) + mov (sp)+,2(r2) + clr 4(r2) + rts r5 + +/ number +3: + mov blockp,r2 + add $6,blockp + mov r0,(r2) + mov r3,2(r2) + cmpb 2(r2),$5 / const->int + bne 4f + movb $1,2(r2) +4: + mov r3,temp + mov conu,4(r2) + inc conu + jsr r5,ptemp; 'c; temp; symbuf + jsr r5,getsym + rts r5 + +appl: + clr functn + bit $70,symtab(r2) / class + bne 1f + bis $30,symtab(r2) + jsr r5,funimpl +1: + mov r2,r3 + jsr r5,declimpl + mov symtab(r2),r0 + bic $!70,r0 / class again + cmp r0,$20 / array + beq 1f + cmp r0,$30 / funct + beq 2f + jsr r5,error; 33. + bic $70,symtab(r2) + br appl +1: + mov $32.,r0 + rts r5 +2: + mov $34.,r0 + rts r5 + +block: + mov blockp,r3 + add $6,blockp + mov r0,(r3)+ + mov r2,(r3)+ + mov r3,-(sp) + jsr r5,*(r5)+ + mov r2,*(sp) + mov (sp)+,r2 + sub $4,r2 + rts r5 + diff --git a/source/fort/f3/f33.s b/source/fort/f3/f33.s new file mode 100644 index 0000000..f39035e --- /dev/null +++ b/source/fort/f3/f33.s @@ -0,0 +1,143 @@ +/ +/ + +/ f33 -- do, etal + +.globl sdo +.globl dobeg +.globl doend + +.globl getlab +.globl e2 +.globl error +.globl lvalue +.globl rvalue +.globl code +.globl convrt +.globl dou +.globl dotabp +.globl edotab +.globl dotab + +sdo: + jsr r5,getlab + br 9f + jsr r5,dobeg + cmp r0,$40. + bne 9f + rts r5 + +7: + tst (sp)+ +8: + tst (sp)+ +9: + jsr r5,error; 42. + rts r5 + +dobeg: + mov dotabp,r2 + cmp r2,$edotab + blo 1f + jsr r5,error; 44. + rts r5 +1: + mov dou,dotab(r2) + inc dou + mov r0,dotab+2(r2) + add $4,dotabp + jsr r5,e2 + cmp r0,$38. / = + bne 9b + mov r2,-(sp) + jsr r5,lvalue + mov r3,-(sp) + bic $!7,r3 + cmp r3,$1 / integer + bne 7b + jsr r5,e2 + cmp r0,$36. / , + bne 7b + jsr r5,rvalue + mov (sp),r2 + jsr r5,convrt + mov (sp),r3 + clrb r3 + swab r3 + jsr r5,code + < gas%d\n goto; 2f\n\0>; .even + r3 + mov dotabp,r2 + mov dotab-4(r2),r0 + jsr r5,code + ; .even + r0 + mov (sp)+,r3 + mov (sp)+,r2 + mov r0,-(sp) + mov r3,-(sp) + jsr r5,lvalue + jsr r5,e2 + mov r0,-(sp) + jsr r5,rvalue + mov 2(sp),r2 + jsr r5,convrt + cmp (sp)+,$36. / , + bne 1f + jsr r5,e2 + mov r0,-(sp) + jsr r5,rvalue + mov 2(sp),r2 + jsr r5,convrt + mov (sp)+,r0 + jsr r5,code + < do2\0>; .even + br 2f +1: + jsr r5,code + < do1\0>; .even +2: + mov (sp)+,r3 + clrb r3 + swab r3 + mov (sp)+,r2 + jsr r5,code + <%d; o%d\n2:\n\0>; .even + r3 + r2 + rts r5 + +doend: + tst r0 + bne 1f + jsr pc,gen + rts r5 +1: + clr r2 +1: + cmp r2,dotabp + bhis 1f + add $4,r2 + cmp r0,dotab-2(r2) + bne 1b + jsr pc,gen + br doend +1: + rts r5 + +gen: + mov r0,-(sp) + mov dotabp,r2 + cmp r0,dotab-2(r2) + beq 1f + jsr r5,error; 43. +1: + mov dotab-4(r2),r0 + sub $4,dotabp + jsr r5,code + < goto; t%d\no%d:\n\0>; .even + r0 + r0 + mov (sp)+,r0 + rts pc + diff --git a/source/fort/f3/f34.s b/source/fort/f3/f34.s new file mode 100644 index 0000000..6c6953a --- /dev/null +++ b/source/fort/f3/f34.s @@ -0,0 +1,65 @@ +/ +/ + +/ f34 -- if statement + +.globl sif + +.globl e2 +.globl error +.globl rvalue +.globl code +.globl ifstmt +.globl iserror +.globl getsym +.globl geti +.globl genop +.globl getlab +.globl newline + +sif: + jsr r5,e2 / expression + jsr r5,iserror + br 9f + cmp r0,$34. / ) + bne 9f + jsr r5,rvalue + mov $"if,r0 + jsr r5,genop + bic $!7,r3 + cmp r3,$3 / logical + bne 1f + jsr r5,code + <; 1f\n\0>; .even + jsr r5,ifstmt + jsr r5,code + <1:\n\0>; .even + rts r5 +1: + mov $3,-(sp) +1: + jsr r5,getlab + br 8f + jsr r5,code + <; .%d\0>; .even + r0 + dec (sp) + beq 1f + jsr r5,getsym + cmp r0,$36. + beq 1b +8: + tst (sp)+ + br 9f +1: + tst (sp)+ + jsr r5,newline + jsr r5,getsym + cmp r0,$40. + bne 9f + rts r5 + +9: + jsr r5,error; 40. + rts r5 + diff --git a/source/fort/f3/f35.s b/source/fort/f3/f35.s new file mode 100644 index 0000000..7b5b8f4 --- /dev/null +++ b/source/fort/f3/f35.s @@ -0,0 +1,87 @@ +/ +/ + +/ f35 -- assignment statement + +.globl sasgn +.globl sassi + +.globl error +.globl e2 +.globl lvalue +.globl rvalue +.globl code +.globl convrt +.globl geti +.globl getsym +.globl getlab +.globl genop +.globl newline +.globl name + +sasgn: + jsr r5,e2 + cmp r0,$38. / = + bne 9f + mov r2,-(sp) + jsr r5,e2 + cmp r0,$40. / =| + bne 8f + tst *(sp) + bne 1f / too hard for simple as + jsr r5,rvalue + mov (sp)+,r2 + mov 2(r2),r2 + mov r2,-(sp) + mov symtab(r2),r2 + jsr r5,convrt + mov r2,r3 + bis $7,r3 + mov $"mv,r0 + jsr r5,genop + mov (sp)+,r3 + jsr r5,name + rts r5 +1: + mov r2,r3 + mov (sp)+,r2 + mov r3,-(sp) + jsr r5,lvalue + mov (sp)+,r2 + mov r3,-(sp) + jsr r5,rvalue +1: + mov (sp)+,r2 + jsr r5,convrt + mov r2,r3 + bis $7,r3 / type 'g' + mov $"as,r0 + jsr r5,genop + jsr r5,newline + rts r5 + +sassi: + jsr r5,getlab + br 9f + mov r0,-(sp) + cmpb (r1)+,$'t + bne 8f + cmpb (r1)+,$'o + bne 8f + jsr r5,e2 + cmp r0,$40. / =| + bne 8f + jsr r5,lvalue + mov (sp)+,r0 + mov r3,-(sp) + jsr r5,code + < lval; .%d\n\0>; .even + r0 + mov $int2con,r3 + br 1b +8: + tst (sp)+ +9: + jsr r5,error; 39. + rts r5 + diff --git a/source/fort/f3/f36.s b/source/fort/f3/f36.s new file mode 100644 index 0000000..dc4774c --- /dev/null +++ b/source/fort/f3/f36.s @@ -0,0 +1,467 @@ +/ +/ + +/ f36 -- expression code generation + +.globl lvalue +.globl rvalue +.globl convrt +.globl type +.globl funcappl +.globl name + +.globl error +.globl lookup +.globl code +.globl iserror +.globl genop +.globl typ +.globl newline +.globl functn +.globl size + +lvalue: + jsr r5,iserror + rts r5 + tst (r2) + bne 1f + mov 2(r2),r3 + jsr r5,code + < lval>; .even + br name +1: + mov r2,-(sp) + cmp (r2),$32. / array appl + bne 1f + jsr r5,aryappl + dec r0 + bne 2f / dim =| 1 + tstb symtab(r3) + blt 2f / p-bit, not simple + mov $"al,r0 + br simpary +2: + jsr r5,code + < alval\0>; .even + +arydope: + jsr r5,pbit + mov symtab+2(r3),r2 + mov (r2)+,r0 + asl r0 + add r0,r2 + mov (r2),r0 + jsr r5,code + <; d%d\0>; .even + r0 + br 2f +1: + jsr r5,error; 54. + mov (sp)+,r2 + rts r5 + +simpary: + mov r3,-(sp) + mov symtab(r3),r3 + bis $7,r3 + jsr r5,genop + mov (sp)+,r3 + jsr r5,size + jsr r5,code + <; %d.\0>; .even + r0 + br 2f + +name: + mov r2,-(sp) + jsr r5,pbit +2: + jsr r5,code + <; \0>; .even + bit $100,symtab(r3) / common + beq 1f + mov symtab+4(r3),r2 + jsr r5,code + <%n+\0>; .even + r2 +1: + movb symtab(r3),r2 + bic $!70,r2 + cmp r2,$30 / external + bne 1f + jsr r5,code + <%n.\n\0>; .even + r3 + br 2f +1: + jsr r5,code + <%n_\n\0>; .even + r3 +2: + mov symtab(r3),r3 + mov (sp)+,r2 + rts r5 + +rvalue: + jsr r5,iserror + rts r5 + mov r2,-(sp) + tst (r2) + bne 1f + mov 2(r2),r3 + movb symtab+1(r3),r2 + jsr r5,code + < rval%d>; .even + r2 + mov (sp)+,r2 + br name +1: + cmp (r2),$32. + bne 1f + jsr r5,aryappl + dec r0 + bne 3f + tstb symtab(r3) + blt 3f + mov $"ar,r0 + br simpary +3: + jsr r5,code + < arval\0>; .even + br arydope +1: + cmp (r2),$34. / array appl + bne 1f + jsr r5,funcappl + mov (sp)+,r2 + mov 2(r2),r3 + movb symtab+1(r3),r0 + jsr r5,code + <%d.\n\0>; .even + r0 + mov symtab(r3),r3 + rts r5 +1: + cmp (r2),$2 + bne 1f + movb 3(r2),r3 + mov 4(r2),r2 + jsr r5,code + < rval%d; c%d\n\0>; .even + r3 + r2 + mov (sp)+,r2 + mov 2(r2),r3 + rts r5 +1: + cmp (r2),$24. / arith or relat + bhi 1f + mov 2(r2),r2 + bne 3f + mov (sp),r2 + sub $10.,(r2) / - bin -> - unary + mov 4(r2),r2 + jsr r5,rvalue + br 2f +3: + jsr r5,rvalue + mov (sp),r2 + mov r3,-(sp) + mov 4(r2),r2 + jsr r5,type + cmp *2(sp),$4 / ** + bne 3f + mov r3,r2 + bic $!7,r2 + cmp r2,$1 / ** integer + bne 3f + mov 2(sp),r2 + sub $2,(r2) / pr -> pi + mov 4(r2),r2 + jsr r5,rvalue + mov $intcon,r2 + jsr r5,convrt + mov (sp)+,r3 + br 2f +3: + mov (sp),r2 + jsr pc,maxtyp + mov (sp)+,r3 + mov r2,-(sp) + jsr r5,convrt + mov 2(sp),r2 + mov 4(r2),r2 + jsr r5,rvalue + mov (sp)+,r2 + jsr r5,convrt + mov r2,r3 + br 2f +1: + cmp (r2),$30. / and or not + bhi 1f + mov 2(r2),r2 + beq 3f + jsr r5,rvalue + mov $logcon,r2 + jsr r5,convrt +3: + mov (sp),r2 + mov 4(r2),r2 + jsr r5,rvalue + mov $logcon,r2 + jsr r5,convrt +2: + mov (sp)+,r2 + mov (r2),r0 + cmp r0,$4 + bhis 2f + add $10.,(r2) / back to binary + tst r0 + beq 2f + sub $8,(r2) / back to pr +2: + mov optab(r0),r0 + jsr r5,genop + jsr r5,newline + cmp (r2),$14. / relat + blo 2f + mov $logcon,r3 +2: + rts r5 +1: + jsr r5,error; 54. + mov (sp)+,r2 + rts r5 + +pbit: + tstb symtab(r3) + bge 1f + jsr r5,code + +1: + rts r5 + +funcappl: + mov r2,-(sp) + mov functn,r3 + jsr r5,code + < stsp; ft+%d.\n\0>; .even + r3 + mov r3,-(sp) + add $2,r3 + mov r3,functn + clr -(sp) / nargs +1: + mov 4(r2),r2 + beq 2f + inc (sp) + cmp (r2),$36. / , + bne 1f + mov r2,-(sp) + mov 2(r2),r2 + mov 6(sp),r3 + jsr r5,fapp1 + mov (sp)+,r2 + br 1b +1: + mov 4(sp),r3 + jsr r5,fapp1 +2: + mov (sp)+,r0 / nargs + mov (sp)+,r2 + mov (sp)+,r3 + mov 2(r3),r3 + jsr r5,code + < call\0>; .even + jsr r5,pbit + jsr r5,code + <; %n.; ft+%d.; %d.; \0>; .even + r3 + r2 + r0 + cmp functn,functm + ble 1f + mov functn,functm +1: + mov r2,functn + rts r5 + +fapp1: + mov 2(r3),r3 / fetch out function name + mov symtab+2(r3),r3 / arg conversion + bne 2f + tst (r2) + beq 1f + cmp (r2),$32. + beq 4f + cmp (r2),$42. / lv if funct or name or arry app + beq 1f + cmp (r2),$2 / lv if const + bne 2f + mov 4(r2),r3 + jsr r5,code + < lval; c%d\n\0> + r3 + br 3f +2: + mov r3,-(sp) + jsr r5,rvalue + mov (sp)+,r2 + beq 2f + jsr r5,convrt +2: + mov functn,r3 + jsr r5,code + < stsp; ft+%d.\n\0>; .even + r3 + add $2,functn + rts r5 +1: + clr (r2) / turn func/array names into lvs +4: + jsr r5,lvalue +3: + mov functn,r3 + jsr r5,code + < stst; ft+%d.\n\0>; .even + r3 + add $2,functn + rts r5 + +aryappl: + mov r2,-(sp) + clr -(sp) / arg count +2: + inc (sp) + mov 4(r2),r2 + cmp (r2),$36. / , + bne 2f + mov r2,-(sp) + mov 2(r2),r2 + jsr r5,rvalue + mov $intcon,r2 + jsr r5,convrt + mov (sp)+,r2 + br 2b +2: + jsr r5,rvalue + mov $intcon,r2 + jsr r5,convrt + mov (sp)+,r0 + mov (sp)+,r2 + mov 2(r2),r3 + cmp r0,*symtab+2(r3) + beq 1f + jsr r5,error; 53. / dimension mismatch +1: + rts r5 + +/ converts stack from type in r3 to type in r2 +convrt: + mov r2,-(sp) + mov r3,-(sp) + bic $![377\<8+7],r2 + bic $![377\<8+7],r3 + cmp r2,r3 + beq 1f + jsr r5,code + < \0>; .even + jsr pc,2f + mov r2,r3 + jsr pc,2f + jsr r5,code + <\n\0>; .even +1: + mov (sp)+,r3 + mov (sp)+,r2 + rts r5 +2: + mov r2,-(sp) + mov r3,r2 + clrb r3 + swab r3 + bic $!7,r2 + movb typ(r2),r2 + jsr r5,code + <%c%d\0>; .even + r2 + r3 + mov (sp)+,r2 + rts pc + +type: + cmp (r2),$32. + beq 2f + cmp (r2),$34. + beq 2f + tst (r2) + bne 1f +2: + mov 2(r2),r3 + mov symtab(r3),r3 + rts r5 +1: + cmp (r2),$2 + bne 1f + mov 2(r2),r3 + rts r5 +1: + cmp (r2),$14. + blo 1f + mov $logcon,r3 + rts r5 +1: + mov r2,-(sp) + mov 2(r2),r2 + bne 1f + mov (sp),r2 + mov 4(r2),r2 + jsr r5,type + br 2f +1: + jsr r5,type + mov (sp),r2 + mov r3,-(sp) + mov 4(r2),r2 + jsr r5,type + mov (sp)+,r2 + jsr pc,maxtyp + mov r2,r3 +2: + mov (sp)+,r2 + rts r5 + +maxtyp: + mov r2,r0 + cmp r2,r3 + bhis 2f + mov r3,r2 +2: + clrb r2 + bic $!7,r0 + bic $!7,r3 + cmp r0,r3 + bhis 2f + mov r3,r0 +2: + bis r0,r2 + rts pc + +optab: + + + + + + + + + + + + + + + + + diff --git a/source/fort/f3/f37.s b/source/fort/f3/f37.s new file mode 100644 index 0000000..37a02e8 --- /dev/null +++ b/source/fort/f3/f37.s @@ -0,0 +1,96 @@ +/ +/ + +/ f37 -- goto statements of all kinds + +.globl sgoto +.globl intexp + +.globl e2 +.globl code +.globl getsym +.globl error +.globl getlab +.globl rvalue +.globl convrt +.globl chrtab + +sgoto: + movb (r1),r0 + cmpb chrtab(r0),$4 / test digit + bne 1f / not constant + jsr r5,getlab + br 8f + jsr r5,code + < goto; .%d\n\0>; .even + r0 + br 9f +1: + cmpb (r1),$'( + beq 1f + jsr r5,intexp + cmp r0,$36. / , + beq 2f + jsr r5,code + < agoto\n\0>; .even + br 9f +2: + jsr r5,code + < cagoto\n\0>; .even + cmpb (r1)+,$'( + bne 8f / syntax + jsr pc,stmlist + br 9f +1: + mov r1,r4 +1: + movb (r1)+,r0 + beq 8f + cmp r0,$') + bne 1b + cmpb (r1)+,$', + bne 8f + jsr r5,intexp + mov r1,-(sp) + jsr r5,code + < cgoto\n\0>; .even + mov r4,r1 + tstb (r1)+ + jsr pc,stmlist + mov (sp)+,r1 +9: + tstb (r1) + beq 1f +8: + jsr r5,error; 35. +1: + rts r5 + +stmlist: + jsr r5,getlab + br 9f + jsr r5,code + < .%d\n\0>; .even + r0 + movb (r1)+,r0 + cmp r0,$', + beq stmlist + cmp r0,$') + bne 8f + jsr r5,code + < 0\n\0>; .even + rts pc +8: + jsr r5,error; 35. +9: + rts pc + +intexp: + jsr r5,e2 + mov r0,-(sp) + jsr r5,rvalue + mov $intcon,r2 + jsr r5,convrt + mov (sp)+,r0 + rts r5 + diff --git a/source/fort/f3/f38.s b/source/fort/f3/f38.s new file mode 100644 index 0000000..2907f74 --- /dev/null +++ b/source/fort/f3/f38.s @@ -0,0 +1,95 @@ +/ +/ + +/ f38 -- wierdo statements + +.globl sstop +.globl scall +.globl spaus +.globl sretu +.globl scont +.globl iserror + +.globl ptemp +.globl code +.globl geti +.globl getsym +.globl error +.globl declimpl +.globl e11 +.globl funcappl + +sstop: + clr r0 + tstb (r1) + beq 1f + jsr r5,getsym + cmp r0,$2. / const + bne 7f + cmp r3,$intcon + bne 7f + jsr r5,geti +1: + jsr r5,code + < stop; %d\n\0>; .even + r0 + br 8f + +spaus: + jsr r5,getsym + cmp r0,$2 + bne 7f + cmp r3,$intcon + bne 7f + jsr r5,geti + jsr r5,code + < paus; %d\n\0>; .even + r0 + br 8f + +sretu: + tst progt + bne 1f + jsr r5,error; 37. / return in main + br sstop +1: + jsr r5,code + < retrn\n\0>; .even +8: +scont: + tstb (r1) + bne 7f + rts r5 +7: + jsr r5,error; 38. + rts r5 + +iserror: + cmp errp,$errb + bne 1f + tst (r5)+ +1: + rts r5 + +scall: + jsr r5,getsym + tst r0 + bne 7b + bit $70,symtab(r3) + bne 1f + bis $30,symtab(r3) +1: + jsr r5,declimpl + jsr r5,e11 + cmp r0,$40. + bne 7b + cmp (r2),$34. + beq 1f + cmp (r2),$42. + bne 7b +1: + jsr r5,funcappl + jsr r5,code + <0\n\0>; .even + br 8b + diff --git a/source/fort/f3/f39.s b/source/fort/f3/f39.s new file mode 100644 index 0000000..4bcf9fa --- /dev/null +++ b/source/fort/f3/f39.s @@ -0,0 +1,258 @@ +/ +/ + +/ f39 -- i/o statements + +.globl sread +.globl swrit +.globl sprin +.globl sback +.globl srewi +.globl sendf + +.globl getsym +.globl error +.globl geticon +.globl e2 +.globl lvalue +.globl rvalue +.globl iserror +.globl convrt +.globl code +.globl chrtab +.globl blocks +.globl blockp +.globl doend +.globl genop +.globl levzer +.globl dobeg +.globl intexp +.globl ptemp +.globl blocks +.globl blockp +.globl intexp +.globl newline +.globl nelem + +sprin: + mov $8.,-(sp) + jsr r5,getfmt + br 9f + cmp r0,$36. / , + beq 1f + cmp r0,$40. / =| + bne 8f + clrb (r1) +1: + mov $34.,r0 / simulate ) + br 2f + +sread: + mov $2,-(sp) + br 1f + +swrit: + clr -(sp) + +1: + cmpb (r1)+,$'( + bne 8f + jsr r5,intexp + mov $blocks,blockp + cmp r0,$34. / ), implies unformatted + beq 2f + cmp r0,$36. / , + bne 8f + jsr r5,getfmt + br 9f + add $4,(sp) + cmp r0,$34. / ) + bne 8f +2: + mov (sp),r0 + mov iotype(r0),r0 + jsr r5,code + < %s\n\0>; .even + r0 +1: + tstb (r1) + beq 9f +1: + jsr r5,list + cmp r0,$40. / |= + beq 9f +8: + jsr r5,error; 41. +9: + jsr r5,code + < endio\n\0>; .even + tst (sp)+ + rts r5 + +iotype: + 1f + 2f + 3f + 4f + 5f + +1: + +2: + +3: + +4: + +5: + + .even + +getfmt: + movb (r1),r0 + cmpb chrtab(r0),$4 / digit + beq 1f + jsr r5,e2 + jsr r5,iserror + rts r5 + mov r0,-(sp) + jsr r5,lvalue + mov $blocks,blockp + br 8f +1: + jsr r5,geticon + br 8f + mov r0,temp + jsr r5,ptemp; 'i; temp; line / register use of format + jsr r5,code + < lval; .%d\n\0>; .even + r0 + jsr r5,getsym + mov r0,-(sp) +8: + mov (sp)+,r0 + tst (r5)+ + rts r5 + +list: + jsr r5,lstitm + cmp r0,$36. / , + beq list + rts r5 + +lstitm: + mov $blocks,blockp + cmpb (r1),$'( / test for sublist + beq 1f + jsr r5,e2 + jsr r5,iserror + rts r5 + mov r0,-(sp) + clr -(sp) + tst (r2) + bne 2f / test for name + mov 2(r2),r3 + mov symtab(r3),r0 + bic $!70,r0 + cmp r0,$20 / test for short list + bne 2f + mov pc,(sp) + mov symtab+2(r3),r3 + mov (r3)+,-(sp) + asl (sp) + add (sp)+,r3 + mov (r3),r3 + jsr r5,code + < slist1; d%d\n2:\0>; .even + r3 +2: + jsr r5,lvalue + tst (sp) + beq 3f + jsr r5,code + < slist3\n\0>; .even +3: + mov $"io,r0 + jsr r5,genop + tst (sp)+ + beq 2f + jsr r5,code + <\n slist2; 2b\0>; .even +2: + jsr r5,newline + mov (sp)+,r0 + rts r5 +1: + inc r1 + jsr r5,levzer; '= + br 1f / yes, implied do + jsr r5,list + jsr r5,chkel + jsr r5,getsym + rts r5 +1: + cmp r1,r0 + bhis 8f + cmpb -(r0),$', / look backwards + bne 1b + mov r0,-(sp) + mov r1,-(sp) + movb $'),(r0) / fake!! + mov r0,r1 + inc r1 + clr r0 + jsr r5,dobeg / get do + jsr r5,chkel + mov (sp)+,r0 + mov r1,-(sp) + mov r0,r1 + jsr r5,list + jsr r5,chkel + clr r0 + jsr r5,doend + mov (sp)+,r1 + movb $',,*(sp)+ / unfake!! + jsr r5,getsym + rts r5 + +chkel: + cmp r0,$34. / ) + beq 1f +8: + jsr r5,error; 41. +1: + rts r5 + +sback: + mov $bksp,r2 + br 1f + +srewi: + mov $rewi,r2 + br 1f + +sendf: + mov $enfl,r2 + +1: + mov r2,-(sp) + jsr r5,intexp + mov (sp),r2 + jsr r5,code + < %s\n\0>; .even + r2 + cmp r0,$40. / =| + beq 9f +8: + jsr r5,error; 41. +9: + tst (sp)+ + rts r5 + +bksp: + +rewi: + +enfl: + + diff --git a/source/fort/f4/f41.s b/source/fort/f4/f41.s new file mode 100644 index 0000000..119082c --- /dev/null +++ b/source/fort/f4/f41.s @@ -0,0 +1,40 @@ +/ +/ + +/ f41 -- everything else + +.globl pass4 + +.globl signon +.globl flush +.globl dope +.globl formts +.globl globls +.globl constn +.globl fopen +.globl bsss +.globl tfil2 + +pass4: + setd + jsr r5,signon; 4 + mov ibuf,r0 + sys close + jsr r5,flush; obuf + jsr r5,flush; tbuf + + jsr r5,dope + jsr r5,formts + jsr r5,constn + jsr r5,bsss + jsr r5,globls / uses r4 from bsss + jsr r5,flush; obuf + sys unlink; tfil2 + clr r0 + tst nerror + beq 1f + sys seek; 0; 2 + mov $1,r0 / syntax errors +1: + sys exit + diff --git a/source/fort/f4/f42.s b/source/fort/f4/f42.s new file mode 100644 index 0000000..e5a3ffe --- /dev/null +++ b/source/fort/f4/f42.s @@ -0,0 +1,97 @@ +/ +/ + +/ 42 -- definition + +.globl bsss + +.globl code +.globl size +.globl declimpl +.globl cdata +.globl dodata +.globl dattab + +bsss: + jsr r5,cdata + cmp progt,$6 / test block common + bne 1f + rts r5 +1: + jsr r5,code + <.bss\n\0>; .even + mov functm,r3 + beq 1f + jsr r5,code + ; .even + r3 +1: + cmp r4,$dattab / any data? + beq 1f + jsr r5,code + <.data\n\0>; .even +1: + jsr r5,code + ; .even + clr r3 +1: + cmp r3,symtp + bhis pass2 + bit $70,symtab(r3) / test classed + bne 2f + jsr r5,declimpl +2: + mov symtab(r3),r0 + mov symtab+6(r3),r2 + bic $!70,r0 / class + cmp r0,$10 / simple + beq 1f + cmp r0,$20 / array + beq 1f + cmp r0,$30 / extrn + bne 2f + bit $200,symtab(r3) / param + beq 2f + jsr r5,code + <%n. = %d.\n\0>; .even + r3 + r2 +2: + cmp r0,$40 / common block + bne 2f + mov symtab+6(r3),r2 / size + beq 2f + jsr r5,code + <.comm %n,%d.\n\0>; .even + r3 + r2 +2: + add $8,r3 + br 1b + +1: + bit $300,symtab(r3) + beq 1f + jsr r5,code + <%n_ = %d.\n\0>; .even + r3 + r2 + br 2b +1: + tst r2 + bne 1f + jsr r5,size + mov nxtaloc,r2 + mov r2,symtab+6(r3) + add r0,nxtaloc +1: + jsr r5,code + <%n_ = base+%d.\n\0>; .even + r3 + r2 + br 2b + +pass2: + jsr r5,dodata + rts r5 + diff --git a/source/fort/f4/f43.s b/source/fort/f4/f43.s new file mode 100644 index 0000000..b0a15e2 --- /dev/null +++ b/source/fort/f4/f43.s @@ -0,0 +1,83 @@ +/ +/ + +/ f43 -- output globals and bdata bss's + +.globl globls + +.globl code +.globl dattab +.globl onedata +.globl error +.globl perror + +globls: + mov progt,r0 + jmp *1f(r0) +1: + 1f + 2f + 3f + 4f +1: + jsr r5,code + <.globl main\n\0>; .even + rts r5 +2: +3: + jsr r5,code + <.globl %n.\n\0>; .even + 8 + rts r5 +4: +1: + clr r3 +1: + cmp r3,symtp + blo 2f + rts r5 +2: + mov symtab(r3),r0 + bic $!270,r0 + cmp r0,$40 / common block + bne 2f + mov symtab+6(r3),r2 + beq 2f + mov $dattab,r1 +3: + cmp r1,r4 + bhis 3f + cmp (r1),r3 + beq 4f + add $8.,r1 + br 3b +3: + jsr r5,code + <.bss\n.globl %n\n%n: .=.+%d.\n.text\n\0>; .even + r3 + r3 + r2 + br 2f +4: + jsr r5,code + <.data\n.globl %n\n%n:\n\0>; .even + r3 + r3 + mov r2,-(sp) + mov r3,-(sp) + mov r1,r3 + jsr r5,onedata + mov (sp)+,r3 + mov (sp)+,r2 + sub r1,r2 + bge 9f + jsr r5,error; 22. / data overrun + jsr r5,perror +9: + jsr r5,code + <.=.+%d.\n.text\n\0>; .even + r2 +2: + add $8,r3 + br 1b + diff --git a/source/fort/f4/f44.s b/source/fort/f4/f44.s new file mode 100644 index 0000000..f16e88d --- /dev/null +++ b/source/fort/f4/f44.s @@ -0,0 +1,110 @@ +/ +/ + +/ f44 -- formats + +.globl formts +.globl strout + +.globl setln +.globl getln +.globl code +.globl error +.globl perror +.globl putc +.globl xbuf + +formts: + jsr r5,setln + mov $2,r3 + clr xbuf+518. / pick up zero efn formats +1: + jsr r5,getln + br 1f + cmp r0,$'s + beq 2f + cmp r0,$'f + bne 1b + mov efno,r0 + jsr r5,code + <.%d: <\0>; .even + r0 + mov $line+6,r1 + jsr r5,strout + mov efno,r0 + neg r0 + br 3f +2: + mov efno,r0 +3: + clr r2 +2: + cmp r2,r3 + bhis 2f + cmp r0,xbuf+518.(r2) + beq 3f + neg r0 + cmp r0,xbuf+518.(r2) + beq 3f + add $2,r2 + neg r0 + br 2b +3: + jsr r5,error; 51. + jsr r5,perror +2: + mov r0,xbuf+518.(r3) + add $2,r3 + br 1b +1: + jsr r5,code + < .even\n>; .even + jsr r5,setln +1: + jsr r5,getln + br 1f + cmp r0,$'r + beq 2f + cmp r0,$'i + bne 1b + mov efno,r0 + neg r0 + br 3f +2: + mov efno,r0 +3: + mov $2,r2 / not zero +2: + cmp r2,r3 + bhis 2f + cmp r0,xbuf+518.(r2) + beq 1b + add $2,r2 + br 2b +2: + jsr r5,error; 52. + jsr r5,perror + br 1b +1: + rts r5 + +strout: + movb (r1)+,r0 + beq 3f + cmp r0,$'> + beq 4f + cmp r0,$'\\ + bne 5f +4: + mov r0,-(sp) + mov $'\\,r0 + jsr r5,putc; obuf + mov (sp)+,r0 +5: + jsr r5,putc; obuf + br strout +3: + jsr r5,code + <\\0\>\n\0>; .even + rts r5 + diff --git a/source/fort/f4/f45.s b/source/fort/f4/f45.s new file mode 100644 index 0000000..db9558d --- /dev/null +++ b/source/fort/f4/f45.s @@ -0,0 +1,144 @@ +/ +/ + +/ f45 -- constant pool + +.globl constn +.globl evalcon + +.globl error +.globl perror +.globl code +.globl getcon +.globl setln +.globl getln +.globl xbuf +.globl symbuf +.globl negflg + +constn: + jsr r5,setln + mov $xbuf+518.,r3 / pool max pointer + mov $ibuf+518.,r4 / pool pointer pointer +1: + jsr r5,getln + br 1f + cmp r0,$'c + bne 1b + jsr r5,packcon + mov r2,-(r4) / put p ptr in p p ptr + cmp r3,r4 + blo 1b + jsr r5,error; 99. + jsr r5,perror +1: + mov $xbuf+518.,r2 +1: + cmp r2,r3 + bhis 1f + mov $ibuf+518.,r1 +2: + cmp r1,r4 + blo 2f + cmp -(r1),r2 + bne 2b + mov r1,r0 + sub $ibuf+516.,r0 + asr r0 + neg r0 + jsr r5,code + ; .even + r0 + br 2b +2: + mov (r2)+,r0 + jsr r5,code + < %o\n\0>; .even + r0 + br 1b +1: + rts r5 + +packcon: + mov $line,r1 + jsr r5,evalcon + mov r1,-(sp) + mov r3,-(sp) + sub r2,(sp) + asr (sp) + mov r2,-(sp) + mov $xbuf+518.,r2 +1: + mov (sp),r3 + mov r2,r1 + tst (r2)+ + mov 2(sp),r0 +2: + cmp (r1)+,(r3)+ + bne 1b + dec r0 + bgt 2b + tst -(r2) + mov (sp)+,r3 + asl (sp) + add r2,(sp) + cmp (sp),r3 + blos 1f + mov (sp),r3 / eureka +1: + tst (sp)+ + mov (sp)+,r1 + rts r5 + +evalcon: + cmpb efno,$5 + bne 2f + movb efno+1,r0 + mov r3,r2 + br 1f +2: + jsr r5,getcon + tst negflg + beq 2f + negf fr0 + negf fr1 +2: + mov r3,r2 + mov efno,r0 + mov r0,r1 + clrb r0 + swab r0 + bic $!7,r1 + cmpb r1,$realcon + beq 3f + cmpb r1,$cplxcon + beq 2f + setl + movfi r0,symbuf+1 + seti + mov $symbuf+5,r1 + sub r0,r1 + br 1f +2: + mov $symbuf+1,r1 + movf fr1,symbuf+1 + cmp r0,$8 + beq 2f + movf fr0,symbuf+9. + br 1f +2: + movf fr0,symbuf+5 + br 1f +3: + movf fr0,symbuf+1 + mov $symbuf+1,r1 +1: + movb (r1)+,(r3)+ + dec r0 + bgt 1b + bit $1,r3 + beq 1f + clrb (r3)+ +1: + rts r5 + diff --git a/source/fort/f4/f46.s b/source/fort/f4/f46.s new file mode 100644 index 0000000..49e8356 --- /dev/null +++ b/source/fort/f4/f46.s @@ -0,0 +1,166 @@ +/ +/ + +/ f46 -- constant evaluation + +.globl getcon +.globl dope + +.globl code + +getcon: + mov r0,-(sp) + mov r2,-(sp) + clr r2 / dec . counter + clrf fr0 + movif $10.,fr1 + clr -(sp) / - flag + cmpb (r1)+,$'+ + beq 1f + cmpb -(r1),$'- + bne 1f + inc r1 + inc (sp) +1: + movb (r1)+,r0 + sub $'0,r0 + cmp r0,$9 + blos 2f + cmp r0,$'.-'0 + bne 1f + dec r2 + br 1b +2: + tst r2 + beq 2f + dec r2 +2: + mulf fr1,fr0 + movif r0,fr2 + addf fr2,fr0 + br 1b +1: + tst r2 + bne 1f + dec r2 +1: + cmp r0,$'e-'0 + beq 2f + cmp r0,$'d-'0 + bne 1f +2: + mov r3,-(sp) + clr r3 + clr -(sp) + cmpb (r1),$'- + bne 3f + inc r1 + inc (sp) + br 2f +3: + cmpb (r1),$'+ + bne 2f + inc r1 +2: + movb (r1)+,r0 + sub $'0,r0 + cmp r0,$9 + bhi 2f + mpy $10.,r3 + add r0,r3 + br 2b +2: + tst (sp)+ + beq 2f + neg r3 +2: + add r3,r2 + mov (sp)+,r3 +1: + movf fr1,fr2 + add $1,r2 + beq 1f + blt 2f + clr -(sp) + br 3f +2: + mov pc,-(sp) + neg r2 +3: + sub $1,r2 + ble 2f + mulf fr1,fr2 + br 3b +2: + tst (sp)+ + bne 2f + mulf fr2,fr0 + br 1f +2: + divf fr2,fr0 +1: + tst (sp)+ + beq 1f + negf fr0 +1: + cmpb -(r1),$', + bne 1f + movf fr0,-(sp) + inc r1 + jsr r5,getcon + movf (sp)+,fr1 / a,b -> r1,r0 +1: + mov (sp)+,r2 + mov (sp)+,r0 + rts r5 + +dope: + cmp progt,$6 / test "block data" + bne 1f + rts r5 +1: + clr r3 +1: + cmp r3,symtp + bhis 1f + mov symtab(r3),r0 + bic $!70,r0 + cmp r0,$20 + bne 2f + mov symtab+2(r3),r0 + beq 2f + mov (r0)+,r1 + mov r1,r2 + asl r2 + add r0,r2 + mov (r2),r0 + jsr r5,code + ; .even + r0 + r1 +3: + dec r1 + blt 3f + mov -(r2),r0 + bge 4f + jsr r5,code + <..; \0>; .even + br 3b +4: + jsr r5,code + <%d.; \0>; .even + r0 + br 3b +3: + mov symtab(r3),r2 + clrb r2 + swab r2 + jsr r5,code + <%d.\n\0>; .even + r2 +2: + add $8,r3 + br 1b +1: + rts r5 + diff --git a/source/fort/f4/f47.s b/source/fort/f4/f47.s new file mode 100644 index 0000000..8f0435e --- /dev/null +++ b/source/fort/f4/f47.s @@ -0,0 +1,298 @@ +/ +/ + +/ f47 -- analysis of data statements + +.globl cdata +.globl dodata +.globl onedata +.globl compare + +.globl code +.globl getcon +.globl error +.globl getsym +.globl consub +.globl size +.globl geti +.globl setln +.globl getln +.globl declimpl +.globl evalcon +.globl dattab +.globl contab +.globl efno +.globl perror +.globl qsort +.globl negflg +.globl repfact +.globl geti +.globl holround + +cdata: + mov r5,-(sp) + jsr r5,setln + mov $dattab,r4 + mov $contab,r5 +dloop: + jsr r5,getln + br 2f + br 1f +2: + mov r4,-(sp) + mov $dattab,r1 + mov r4,r2 + mov $8.,r3 + jsr pc,qsort + mov (sp)+,r4 + mov (sp)+,r5 + rts r5 +1: + cmp r0,$'d + bne dloop + mov $line+4,r1 +/ loop per specification-set +1: + clr repfact + mov r1,r2 +2: + jsr r5,getsym + cmp r0,$40. / =| + bne 3f +8: + jmp 8f +9: + jmp 9f +3: + cmp r0,$6 / / + bne 2b + mov r1,-(sp) + mov r2,r1 + mov (sp)+,r2 +/ loop per specification +2: + cmp r4,r5 + blo 3f + jmp 7f +3: + jsr r5,getsym + tst r0 + bne 8b + bit $70,symtab(r3) / test classed + bne 3f + jsr r5,declimpl +3: + mov symtab(r3),r0 + mov r0,holquo / temp storage + incb holquo+1 / round size + bicb $1,holquo+1 + bit $200,r0 / test parameter + bne 9b + bic $!70,r0 + cmp r0,$10 / simple + beq 3f + cmp r0,$20 / array + bne 9b +3: + bit $100,symtab(r3) / test common + beq 3f + cmp progt,$6 / test block data + bne 9b + mov symtab+4(r3),(r4)+ / common block + br 4f +3: + cmp progt,$6 / test block data + beq 9b + clr (r4)+ + tst symtab+6(r3) / test allocated + bne 4f + mov nxtaloc,symtab+6(r3) + jsr r5,size + add r0,nxtaloc +4: + clr (r4) / offset slot + cmpb (r1),$'( / test subscript + bne 3f + inc r1 + jsr r5,consub + bic $70,holquo + bis $10,holquo / array -> scalar + mov r0,(r4) +3: + movb symtab+1(r3),r0 / width of item + inc r0 + bic $1,r0 + mov r0,holround + add symtab+6(r3),(r4)+ + tst repfact + beq 3f + dec repfact + movb efno+1,r3 + mov r3,(r4)+ + mov r5,(r4)+ + br 4f +3: + mov r1,-(sp) + mov r2,r1 + mov (sp)+,r2 +5: + jsr r5,getsym + cmp r0,$2 / constant + beq 3f + cmp r0,$10. / - + bne 8f + inc negflg + jsr r5,getsym + cmp r0,$2 / constant + bne 8f +3: + cmpb (r1)+,$'* + bne 3f + cmp r3,$intcon + bne 8f + jsr r5,geti + dec r0 + bmi 8f + mov r0,repfact + br 5b +3: + dec r1 + mov r1,-(sp) + mov r2,-(sp) + mov r3,efno + clrb r3 + swab r3 + mov r3,(r4)+ + sub r3,r5 + mov r5,(r4)+ / ptr to const + mov r5,r3 + mov $symbuf,r1 + jsr r5,evalcon + clr negflg + mov (sp)+,r1 + mov (sp)+,r2 / note r1 <=> r2 +4: + cmpb efno+1,holquo+1 / compare sizes + blt 9f / constant too small + beq 3f + bicb $!77,holquo + cmp holquo,$int2con+10 / simple int*2? + bne 4f + sub $2,-4(r4) / reduce const length + cmpb efno,$5 + beq 3f / hollerith, OK + add $2,-2(r4) / get least sig. + br 3f +4: + bit $20,holquo / test array + beq 9f + cmpb efno,$5 / test hollerith + bne 9f +3: + cmpb (r1),$'/ + beq 3f + cmpb (r1)+,$', + bne 8f + tst repfact + bne 4f + cmpb (r2)+,$', + bne 8f +4: + jmp 2b +3: + cmpb (r2)+,$'/ + bne 8f + tstb (r2) + beq 1f + cmpb (r2),$', + bne 3f + inc r2 +3: + mov r2,r1 + tst repfact + bne 8f + jmp 1b +7: + jsr r5,error; 28. / data table overflow + br 2f +8: + jsr r5,error; 21. / data syntax error + br 2f +9: + jsr r5,error; 22. / data semantic error +2: + mov $dattab,r4 / reset ptrs + mov $contab,r5 + jsr r5,perror +1: + jmp dloop + +dodata: + cmp progt,$6 + beq 1f / block data + mov $dattab,r3 + cmp r3,r4 + bne 2f / is data + mov nxtaloc,r0 + jsr r5,code + <.=.+%d.\n.text\n\0>; .even + r0 + rts r5 +2: + jsr r5,onedata + sub nxtaloc,r1 + neg r1 + blt 9b + jsr r5,code + <.=.+%d.\n.text\n\0>; .even + r1 +1: + rts r5 + +onedata: + clr r1 +2: + mov 2(r3),r0 + sub r1,r0 + bmi 9f + beq 3f + jsr r5,code + <.=.+%d.\n\0>; .even + r0 + add r0,r1 +3: + mov 4(r3),r0 + add r0,r1 + asr r0 + mov r0,-(sp) + mov 6(r3),r2 +3: + mov (r2)+,r0 + jsr r5,code + <%o\n\0>; .even + r0 + dec (sp) + bne 3b + tst (sp)+ + add $8.,r3 + cmp r3,r4 + bhis 1f + cmp (r3),-8(r3) / any more in this block + beq 2b +1: + rts r5 +9: + clr line + jsr r5,error; 32. / overlapping data init + jsr r5,perror + rts r5 + +/ comparison routine for qsort + +compare: + cmp (r0),(r4) + bne 1f + cmp 2(r0),2(r4) +1: + rts pc + diff --git a/source/fort/fx/fhd.s b/source/fort/fx/fhd.s new file mode 100644 index 0000000..399da7a --- /dev/null +++ b/source/fort/fx/fhd.s @@ -0,0 +1,53 @@ +/ +/ + +/ fhd -- data segment header +/ + + symsize = 1600. + linsize = 800. + namsize = 1200. + smblsize = 399. + + intcon = 4\<8+1 / type of integer constant + realcon = 4\<8+2 + logcon = 2\<8+3 / type of logical constant + log1con = 1\<8+3 + int1con = 1\<8+1 + int2con = 2\<8+1 + dblcon = 10\<8+2 + dcplxcon = 20\<8+4 + cplxcon = 10\<8+4 + +.globl data +.globl ibuf +.globl obuf +.globl tbuf +.globl line +.globl eline +.globl ifno +.globl efno +.globl errp +.globl errb +.globl eerrb +.globl symtab +.globl esymtab +.globl esymp +.globl symtp +.globl namebuf +.globl enamebuf +.globl namep +.globl symbuf +.globl esymbuf +.globl ch +.globl ch1 +.globl progt +.globl holquo +.globl nxtaloc +.globl imptab +.globl nerror +.globl temp +.globl functm +.globl edata +.globl dsize + diff --git a/source/fort/fx/fx1.s b/source/fort/fx/fx1.s new file mode 100644 index 0000000..4b25019 --- /dev/null +++ b/source/fort/fx/fx1.s @@ -0,0 +1,40 @@ +/ +/ + +/ fx1 -- utility + +.globl lookup +/ lookup +/ lookup string pointed at by r2 +/ in table pointed at by arg1 +/ r0 returns symbol number*2 +/ r2 is advanced by matched string +/ registers used: r0,r2 +lookup: + mov r1,-(sp) + clr r0 + mov r2,-(sp) + mov (r5)+,r1 +1: + mov (sp),r2 + tstb (r1) + beq 1f +2: + cmpb (r2)+,(r1)+ + bne 2f + tstb (r1) + bne 2b + asl r0 + cmp (r5)+,(sp)+ + mov (sp)+,r1 + rts r5 +2: + tstb (r1)+ + bne 2b + inc r0 + br 1b +1: + mov (sp)+,r2 + mov (sp)+,r1 + rts r5 + diff --git a/source/fort/fx/fx2.s b/source/fort/fx/fx2.s new file mode 100644 index 0000000..78ae087 --- /dev/null +++ b/source/fort/fx/fx2.s @@ -0,0 +1,134 @@ +/ +/ + +/ fx2 -- error setting and printing + +.globl error +.globl perror + +.globl tput +.globl tdecml + +error: + inc nerror + mov r0,-(sp) + mov r2,-(sp) + mov (r5)+,r0 + mov $errb,r2 +1: + cmp r2,errp + bhis 1f + cmp r0,(r2)+ + beq 2f + tst (r2)+ + br 1b +1: + cmp r2,$eerrb + bhis 2f + mov r0,(r2)+ + mov r1,(r2) + dec (r2)+ / r1 is often 1 too far + mov r2,errp +2: + mov (sp)+,r2 + mov (sp)+,r0 + rts r5 + +perror: + cmp errp,$errb + beq 1f + mov r1,-(sp) + mov r2,-(sp) + mov ifno,r0 + jsr r5,tdecml + mov $'\t,r0 + jsr r5,tput + mov $line,r1 +2: + movb (r1),r0 + beq 2f + jsr r5,tput + mov $errb+2,r2 +3: + cmp r1,(r2)+ + bne 4f + mov $1,r0 + sys write; mes2; 2 / bs, _ + br 3f +4: + cmp r2,errp + blo 3b +3: + inc r1 + br 2b +2: + mov $errb,r1 +2: + mov $1,r0 + sys write; mes1; 4 +3: + sys open; errfil; 0 + bec 3f + mov (r1)+,r0 + tst (r1)+ + jsr r5,tdecml + cmp r1,errp + bhis 2f + mov $',,r0 + jsr r5,tput + br 3b +3: + mov r0,-(sp) + mov (r1)+,r2 + tst (r1)+ +3: + dec r2 + ble 3f +4: + mov (sp),r0 + sys read; ich; 1 + bes 4f + tst r0 + beq 4f + cmpb ich,$'\n + bne 4b + br 3b +3: + mov (sp),r0 + sys read; ich; 1 + bes 4f + tst r0 + beq 4f + movb ich,r0 + cmp r0,$'\n + beq 3f + jsr r5,tput + br 3b +4: + mov $1,r0 + sys write; mes3; 18. +3: + mov (sp)+,r0 + sys close + cmp r1,$errp + blo 2b +2: + mov $'\n,r0 + jsr r5,tput + mov $errb,errp + mov (sp)+,r2 + mov (sp)+,r1 +1: + rts r5 + +mes1: + <\n** > +mes2: + .byte 010, '_ +mes3: + +errfil: + +.even +.bss +ich: .=.+2 diff --git a/source/fort/fx/fx3.s b/source/fort/fx/fx3.s new file mode 100644 index 0000000..17fdf23 --- /dev/null +++ b/source/fort/fx/fx3.s @@ -0,0 +1,49 @@ +/ +/ + +/ fx3 -- get integer + +.globl geti +.globl ptemp + +.globl putc +.globl putw + +geti: + mov r1,-(sp) + mov r3,-(sp) + clr r3 + mov $symbuf,r0 +1: + movb (r0)+,r1 + sub $'0,r1 + cmp r1,$9 + bhi 1f + mpy $10.,r3 + add r1,r3 + br 1b +1: + mov r3,r0 + mov (sp)+,r3 + mov (sp)+,r1 + rts r5 + +ptemp: + mov r0,-(sp) + mov r1,-(sp) + mov (r5)+,r0 / character + jsr r5,putc; tbuf + mov *(r5)+,r0 / word + jsr r5,putw; tbuf + mov ifno,r0 + jsr r5,putw; tbuf + mov (r5)+,r1 / string +1: + movb (r1),r0 + jsr r5,putc; tbuf + tstb (r1)+ + bne 1b + mov (sp)+,r1 + mov (sp)+,r0 + rts r5 + diff --git a/source/fort/fx/fx4.s b/source/fort/fx/fx4.s new file mode 100644 index 0000000..3b72faf --- /dev/null +++ b/source/fort/fx/fx4.s @@ -0,0 +1,364 @@ +/ +/ + +/ fx4 -- get symbol + +.globl getsym +.globl getid +.globl lookid +.globl chrtab + +.globl lookup +.globl error +.globl geti +.globl holround +/ getsym returns the next basic symbol + +/ 0 name (symbol table entry in r3) +/ 2 number (type in r3) +/ 4 ** +/ 6 / +/ 8 * +/ 10 - +/ 12 + +/ 14 .lt. +/ 16 .le. +/ 18 .eq. +/ 20 .ne. +/ 22 .gt. +/ 24 .ge. +/ 26 .not. +/ 28 .and. +/ 30 .or. +/ 32 ( +/ 34 ) +/ 36 , +/ 38 = +/ 40 =| +/ +getsym: + mov r2,-(sp) + mov r1,r2 + jsr r5,lookup; bastab + br 1f + mov r2,r1 + cmp r0,$4 + bhis 2f + asr r0 + add $'0,r0 + movb r0,symbuf + movb $12,symbuf+1 + clrb symbuf+2 + mov $logcon,r3 / logical*2 + mov $2,r0 +2: + cmp r0,$32. + bne 2f + +/ check for possible complex constant + + mov r1,-(sp) + movb -2(r1),r0 + movb chrtab(r0),r0 + beq 4f + cmp r0,$4 + blos 3f +4: + jsr r5,srconst + br 3f + mov r3,r2 + cmpb (r1)+,$', + bne 3f + jsr r5,srconst + br 3f + cmp r3,r2 + bhis 4f + mov r2,r3 +4: + cmpb (r1)+,$') + bne 3f + mov (sp)+,r1 + mov $symbuf,r2 +4: + movb (r1)+,(r2) + cmpb (r2)+,$') + bne 4b + clrb -(r2) + mov $2,r0 + br 2f +3: + mov (sp)+,r1 + mov $32.,r0 +2: + mov (sp)+,r2 + rts r5 +1: + clr lstchr + cmp r1,$line + blos 1f + movb -1(r1),lstchr +1: + mov $symbuf,r2 + movb (r1)+,r0 + movb r0,(r2)+ + bic $!177,r0 + movb chrtab(r0),r0 + jmp *1f(r0) +1: + eos + let + num + per + +eos: + mov $40.,r0 + tstb -(r1) + beq 2b + jsr r5,error; 8. + br 2b + +let: + dec r1 + jsr r5,getid + br .+2 / cannot happen + jsr r5,lookid; symbuf + mov (sp)+,r2 + clr r0 + rts r5 + +num: + mov $intcon,r3 / integer*4 + jsr r5,numst + cmpb (r1),$'. + bne 2f + mov r2,-(sp) + mov r1,r2 + jsr r5,lookup; bastab + br 1f + mov (sp)+,r2 + br 3f +1: + mov (sp)+,r2 + movb (r1)+,(r2)+ + br 1f +2: + cmpb (r1),$'h / hollerith const? + bne 2f + mov lstchr,r0 + cmpb chrtab(r0),$2 / letter? + beq 2f / not h, then + cmp r0,$'* + beq 2f / e.g. real*4 h... + clrb (r2) + jsr r5,geti + mov $symbuf,r2 + inc r1 + mov holround,-(sp) + dec (sp) + clr -(sp) +4: + movb (r1)+,(r2)+ + bne 5f + jsr r5,error; 55. + br 6f +5: + inc (sp) + dec r0 + bgt 4b +6: + bit (sp),2(sp) + beq 6f + movb $' ,(r2)+ + inc (sp) + br 6b +6: + mov (sp)+,r3 + tst (sp)+ + swab r3 + clrb r3 + bis $5,r3 + mov $2,r0 + mov (sp)+,r2 + rts r5 + +.bss +lstchr: .=.+2 +.text + +per: + jsr r5,isnum + br eos +1: + mov $realcon,r3 / real*4 + jsr r5,numst +2: + jsr r5,expon +3: + clrb (r2) + mov $2,r0 + mov (sp)+,r2 + rts r5 + +isnum: + movb (r1),r0 + cmpb chrtab(r0),$4 + bne 1f + tst (r5)+ +1: + rts r5 + +numst: + jsr r5,isnum + br 1b + inc r1 + movb r0,(r2)+ + br numst + +expon: + cmpb (r1)+,$'e + beq 1f + cmpb -1(r1),$'d + beq 1f +2: + dec r1 + rts r5 +1: + cmpb (r1),$'+ + beq 1f + cmpb (r1),$'- + beq 1f + jsr r5,isnum + br 2b +1: + mov $realcon,r3 / real*4 + cmpb -(r1),$'e + beq 1f + mov $dblcon,r3 / real*8 +1: + movb (r1)+,(r2)+ + movb (r1)+,(r2)+ + jsr r5,numst + rts r5 + +getid: + mov r0,-(sp) + mov r2,-(sp) + movb (r1),r0 + cmpb chrtab(r0),$2 + bne 3f + tst (r5)+ + mov $symbuf,r2 +1: + movb (r1)+,r0 + movb r0,(r2)+ + movb chrtab(r0),r0 + cmp r0,$2 + beq 1b + cmp r0,$4 + beq 1b + dec r1 + clrb (r2) + movb $12,-(r2) +3: + mov (sp)+,r2 + mov (sp)+,r0 + rts r5 + +lookid: + mov r0,-(sp) + mov r2,-(sp) +2: + mov (r5),r2 + jsr r5,lookup; namebuf + br 1f + asl r0 + asl r0 + mov r0,r3 + mov (sp)+,r2 + mov (sp)+,r0 + tst (r5)+ + rts r5 +1: + mov namep,r0 + add $8.,symtp +1: + movb (r2)+,(r0)+ + bne 1b + mov r0,namep + cmp r0,$enamebuf + bhis 1f + mov symtp,r0 + add $symtab,r0 + cmp r0,esymp + blo 2b +1: + mov $1,r0 + sys write; ovfl; eovfl-ovfl + clr r0 + sys seek; 0; 2 + mov $-1,r0 + sys exit + +ovfl: + +eovfl: +.even + +srconst: + cmpb (r1)+,$'+ + beq 1f + cmpb -(r1),$'- + bne 1f + inc r1 +1: + jsr r5,getsym + cmp r0,$2 + bne 1f + clrb r3 + add r3,r3 + bisb $cplxcon,r3 + tst (r5)+ +1: + rts r5 + +chrtab: + .byte 0,0,0,0,0,0,0,0 + .byte 0,0,0,0,0,0,0,0 + .byte 0,0,0,0,0,0,0,0 + .byte 0,0,0,0,0,0,0,0 + .byte 0,0,0,0,0,0,0,0 + .byte 0,0,0,0,0,0,6,0 + .byte 4,4,4,4,4,4,4,4 + .byte 4,4,0,0,0,0,0,0 + .byte 0,2,2,2,2,2,2,2 + .byte 2,2,2,2,2,2,2,2 + .byte 2,2,2,2,2,2,2,2 + .byte 2,2,2,0,0,0,0,0 + .byte 0,2,2,2,2,2,2,2 + .byte 2,2,2,2,2,2,2,2 + .byte 2,2,2,2,2,2,2,2 + .byte 2,2,2,0,0,0,0,0 + +bastab: + <.false.\0> + <.true.\0> + <**\0> + + <*\0> + <-\0> + <+\0> + <.lt.\0> + <.le.\0> + <.eq.\0> + <.ne.\0> + <.gt.\0> + <.ge.\0> + <.not.\0> + <.and.\0> + <.or.\0> + <(\0> + <)\0> + <,\0> + <=\0> + <\0> + diff --git a/source/fort/fx/fx5.s b/source/fort/fx/fx5.s new file mode 100644 index 0000000..9fe0b6f --- /dev/null +++ b/source/fort/fx/fx5.s @@ -0,0 +1,46 @@ +/ +/ + +/ fx5 -- declare implicit + +.globl declimpl +.globl getname + +declimpl: + bit $7,symtab(r3) + bne 1f / already declared + jsr r5,getname + movb symbuf,r0 + cmp r0,$'a + blo 2f + sub $6,r0 / map 'a -> 'Z+1 +2: + asl r0 + bis imptab-[2*'A](r0),symtab(r3) +1: + bit $70,symtab(r3) / class + bne 1f + bis $10,symtab(r3) / simple +1: + rts r5 + +getname: + mov r3,-(sp) + clr r3 + mov $namebuf,r0 +1: + cmp r3,(sp) + bhis 1f +2: + tstb (r0)+ + bne 2b + add $8,r3 + br 1b +1: + mov $symbuf,r3 +2: + movb (r0)+,(r3)+ + bne 2b + mov (sp)+,r3 + rts r5 + diff --git a/source/fort/fx/fx6.s b/source/fort/fx/fx6.s new file mode 100644 index 0000000..c72283d --- /dev/null +++ b/source/fort/fx/fx6.s @@ -0,0 +1,31 @@ +/ +/ + +/ fx6 -- teletype + +.globl tput +.globl tdecml + +tdecml: + mov r1,-(sp) + jsr r5,td + mov (sp)+,r1 + rts r5 + +td: + mov r0,r1 + clr r0 + dvd $10.,r0 + mov r1,-(sp) + tst r0 + beq 1f + jsr r5,td +1: + mov (sp)+,r0 + add $'0,r0 + +tput: + movb r0,ch+1 + mov $1,r0 + sys write; ch+1; 1 + rts r5 diff --git a/source/fort/fx/fx7.s b/source/fort/fx/fx7.s new file mode 100644 index 0000000..3cfb157 --- /dev/null +++ b/source/fort/fx/fx7.s @@ -0,0 +1,34 @@ +/ +/ + +/ fx7 -- passes advancement + +.globl signon +.globl signoff + + +.globl pass2 +.globl pass3 +.globl pass4 + +signon: + tst (r5)+ + rts r5 + +signoff: + mov (r5)+,r0 + tst (sp)+ + dec r0 + asl r0 + jmp *passtab(r0) + +passtab: + pass2 + pass3 + pass4 + +.data + + + + diff --git a/source/fort/fx/fx8.s b/source/fort/fx/fx8.s new file mode 100644 index 0000000..afcc99e --- /dev/null +++ b/source/fort/fx/fx8.s @@ -0,0 +1,269 @@ +/ +/ + +/ fx8 -- read source line + +.globl getline +.globl isagn +.globl levzer + +.globl error +.globl getc +.globl chrtab + +getline: + mov r3,-(sp) + clr holquo + clr r3 / line number + clr line + mov $line,r1 +1: + jsr pc,get + sub $'0,r0 + cmp r0,$9 + bhi 1f + mpy $10.,r3 + add r0,r3 + br 1b +1: + add $'0,r0 + movb r0,ch + mov r3,efno +1: + mov lino, ifno + inc ifno + jsr pc,get + cmp r0,$'\n / nl + beq 1f + cmp r0,$'' + beq 2f + cmp r0,$'" + bne 3f +2: + mov r0,holquo + add $4,r1 / room for h count + mov r1,-(sp) +2: + jsr pc,get + cmp r0,$'\n + beq 4f + cmp r0,holquo + beq 2f + bis $200,r0 + movb r0,(r1)+ + cmp r1,$eline-1 + blo 2b +4: + tst (sp)+ + br err1 +2: + mov (sp)+,r3 + mov r1,-(sp) + sub r3,r1 + movb $'h,-(r3) + clr r0 + div $10.,r0 + add $'0,r1 + movb r1,-(r3) + mov r0,r1 + clr r0 + div $10.,r0 + add $'0,r1 + movb r1,-(r3) + add $'0,r0 + movb r0,-(r3) + mov (sp)+,r1 + clr holquo + br 1b +3: + cmp r0,$'h + bne 2f + clr r3 / quote count + mov r1,-(sp) +3: + cmp r1,$line + blos 4f + movb -(r1),r0 + cmpb chrtab(r0),$4 / digit? + beq 3b + cmpb chrtab(r0),$2 / test letter + beq 3f + cmp r0,$'* + beq 3f + inc r1 +4: + cmp r1,(sp) + bhis 4f + movb (r1)+,r0 + sub $'0,r0 + mpy $10.,r3 + add r0,r3 + br 4b +4: + mov r3,r0 + beq 3f + mov r0,holquo + mov (sp)+,r1 + movb $'h,(r1)+ +4: + jsr pc,get + cmp r0,$'\n + bne 5f + mov r0,ch + mov $' ,r0 +5: + bis $200,r0 + movb r0,(r1)+ + cmp r1,$eline-1 + bhis err1 + dec holquo + bne 4b + br 1b +3: + mov (sp)+,r1 + mov $'h,r0 +2: + movb r0,(r1)+ + cmp r1,$eline-1 + blo 1b +err1: + jsr r5,error; 1. +1: + clrb (r1)+ + mov (sp)+,r3 + tstb line + bne 1f + jmp getline +1: + rts r5 + +isagn: + jsr r5,levzer; '= + br 1f + br 3f +1: + mov r0,-(sp) + jsr r5,levzer; ', + br 4f + jsr r5,levzer; '( + br 1f + tst (sp)+ +2: + rts r5 +1: + cmp (sp)+,r0 + blt 2b + mov r1,-(sp) + mov r0,r1 + inc r1 + jsr r5,levzer; ') + br 1f +1: + mov (sp)+,r1 + cmpb 1(r0),$'= + bne 3f + rts r5 + +levzer: + mov r1,r0 + clr -(sp) +1: + tst (sp) + bne 2f + cmpb (r0),(r5) + beq 1f +2: + cmpb (r0),$'( + bne 2f + inc (sp) +2: + cmpb (r0),$') + bne 2f + dec (sp) + blt 5f +2: + tstb (r0)+ + bne 1b +5: + tst (r5)+ +1: +4: + tst (sp)+ +3: + tst (r5)+ + rts r5 + +get: + movb ch,r0 + beq 1f + clrb ch + rts pc +1: + jsr pc,get1 + cmp r0,$'\n + bne 2f + jsr pc,get1 + cmp r0,$'& + beq 1b + movb r0,ch1 + mov $'\n,r0 +2: + tst holquo + bne 1f + cmp $' ,r0 + beq 1b + cmp $'\t,r0 + beq 1b +1: + cmp r0,$4 / test EOT + bne 1f + mov $1,r0 + sys write; mes; emes-mes + mov $1,r0 / syntax errors detected + sys exit +1: + rts pc + +get1: + movb ch1,r0 + beq 1f + clrb ch1 + br 2f +1: + jsr r5,getc; ibuf + bcs 1f + bic $!177,r0 + beq 1b + cmp r0,$'\n + bne 2f + inc lino +2: + tst nlflg + beq 2f + clr nlflg + cmp r0,$'c + bne 2f +3: + jsr pc,get1 + cmp r0,$'\n + beq 1b + cmp r0,$4 + bne 3b +2: + cmp r0,$'\n + bne 2f + inc nlflg +2: + rts pc +1: + mov $4,r0 + rts pc + +.data +nlflg: 1 +.text +mes: + +emes: +.bss +lino: .=.+2 diff --git a/source/fort/fx/fx9.s b/source/fort/fx/fx9.s new file mode 100644 index 0000000..1443692 --- /dev/null +++ b/source/fort/fx/fx9.s @@ -0,0 +1,125 @@ +/ +/ + +/ fx9 -- code + +/ jsr r5,code; ; .even +/ arg1 +/ arg2 +/ ... +/ +/ args specified by % in string. +/ %s: string +/ %d: decimal number +/ %o: octal number +/ %c: character +/ +/ args are addresses +/ or registers r0-r4 + +.globl code + +.globl putc +.globl getname + +code: + mov r4,-(sp) + mov r3,-(sp) + mov r2,-(sp) + mov r1,-(sp) + mov r0,-(sp) + mov r5,r4 +1: + tstb (r5)+ + bne 1b + inc r5 + bic $1,r5 +1: + movb (r4)+,r0 + beq 1f + cmp r0,$'% + beq 2f + jsr r5,putc; obuf + br 1b +2: + movb (r4)+,r0 + beq 1f + cmp r0,$'s + beq cstr + cmp r0,$'c + beq cchr + cmp r0,$'d + beq cdec + cmp r0,$'o + beq coct + cmp r0,$'n + beq cnam + jsr r5,putc; obuf + br 1b +cnam: + jsr pc,cget + mov r1,r3 + jsr r5,getname + mov $symbuf,r1 + br 2f +cstr: + jsr pc,cget +2: + movb (r1)+,r0 + beq 1b + cmp r0,$'\n + beq 2b + jsr r5,putc; obuf + br 2b +cchr: + jsr pc,cget + mov r1,r0 + jsr r5,putc; obuf + mov r1,r0 + clrb r0 + swab r0 + beq 1b + jsr r5,putc; obuf + br 1b +coct: + jsr pc,cget + mov $8.,r2 + br 2f +cdec: + jsr pc,cget + mov $10.,r2 +2: + jsr pc,2f + br 1b +2: + clr r0 + dvd r2,r0 + mov r1,-(sp) + mov r0,r1 + beq 2f + jsr pc,2b +2: + mov (sp)+,r0 + add $'0,r0 + jsr r5,putc; obuf + rts pc +1: + mov (sp)+,r0 + mov (sp)+,r1 + mov (sp)+,r2 + mov (sp)+,r3 + mov (sp)+,r4 + rts r5 + +cget: + mov (r5)+,r1 + cmp r1,$4 + blos 1f + rts pc +1: + asl r1 + add $2,r1 + add sp,r1 + mov (r1),r1 + rts pc + diff --git a/source/fort/fx/fxa.s b/source/fort/fx/fxa.s new file mode 100644 index 0000000..cbfe55c --- /dev/null +++ b/source/fort/fx/fxa.s @@ -0,0 +1,36 @@ +/ +/ + +/ fxa -- genop -- output a typed operator + +.globl genop +.globl newline + +.globl code +.globl typ + +genop: + mov r1,-(sp) + mov r3,-(sp) + bic $!7,r3 + movb typ(r3),r1 + mov (sp),r3 + clrb r3 + swab r3 + jsr r5,code + < %c%c%d\0>; .even + r1 + r0 + r3 + mov (sp)+,r3 + mov (sp)+,r1 + rts r5 + +newline: + jsr r5,code + <\n\0>; .even + rts r5 + +typ: + + diff --git a/source/fort/fx/fxb.s b/source/fort/fx/fxb.s new file mode 100644 index 0000000..cd0bc3e --- /dev/null +++ b/source/fort/fx/fxb.s @@ -0,0 +1,32 @@ +/ +/ + +/ fxb -- get integer constant or label + +.globl geticon +.globl getlab + +.globl getsym +.globl geti +.globl ptemp + +geticon: + jsr r5,getsym + cmp r0,$2 + bne 1f + cmp r3,$intcon + bne 1f + jsr r5,geti + tst (r5)+ +1: + rts r5 + +getlab: + jsr r5,geticon + br 1f + mov r0,temp + jsr r5,ptemp; 'r; temp; line + tst (r5)+ +1: + rts r5 + diff --git a/source/fort/fx/fxc.s b/source/fort/fx/fxc.s new file mode 100644 index 0000000..273b109 --- /dev/null +++ b/source/fort/fx/fxc.s @@ -0,0 +1,36 @@ +/ +/ + +/ fxc -- size of array + +.globl size +.globl nelem + +.globl error + +size: + movb symtab+1(r3),r0 + jsr r5,nelem + inc r0 + bic $1,r0 / round to 0 mod 2 + rts r5 + +nelem: + mov r1,-(sp) + mov r0,r1 + mov symtab(r3),r0 + bic $!70,r0 + cmp r0,$20 + bne 1f + mov symtab+2(r3),r0 + mov (r0)+,-(sp) +2: + mpy (r0)+,r1 + dec (sp) + bgt 2b + tst (sp)+ +1: + mov r1,r0 + mov (sp)+,r1 + rts r5 + diff --git a/source/fort/fx/fxd.s b/source/fort/fx/fxd.s new file mode 100644 index 0000000..c56e930 --- /dev/null +++ b/source/fort/fx/fxd.s @@ -0,0 +1,50 @@ +/ +/ + +/ xd -- tmp file 2 handl + +.globl setln +.globl getln + +.globl tfil2 +.globl tfildiag +.globl fopen +.globl getc +.globl getw +.globl xbuf + +setln: + mov $tfil2,r0 + jsr r5,fopen; xbuf + bcc 1f + jmp tfildiag +1: + rts r5 + +getln: + jsr r5,getc; xbuf + bcs 3f + mov r0,-(sp) + jsr r5,getw; xbuf + mov r0,efno + jsr r5, getw; xbuf + mov r0,ifno + mov $line,r1 +1: + jsr r5,getc; xbuf + bcs 1f + tst r0 + beq 1f + bic $200,r0 + movb r0,(r1)+ + br 1b +1: + clrb (r1)+ + mov (sp)+,r0 + tst (r5)+ + rts r5 +3: + mov xbuf,r0 + sys close + rts r5 + diff --git a/source/fort/fx/fxe.s b/source/fort/fx/fxe.s new file mode 100644 index 0000000..b14be54 --- /dev/null +++ b/source/fort/fx/fxe.s @@ -0,0 +1,24 @@ +/ +/ + +/ xe -- temp file junk + +.globl tfildiag +.globl tfil1, tfil2 + +tfildiag: + mov $1,r0 + sys write; mes1; emes1-mes1 + clr r0 + sys seek; 0; 2 + mov $-1,r0 / failure return + sys exit + +mes1: + +emes1: +tfil1: + +tfil2: + + diff --git a/source/fort/fx/fxf.s b/source/fort/fx/fxf.s new file mode 100644 index 0000000..0787755 --- /dev/null +++ b/source/fort/fx/fxf.s @@ -0,0 +1,23 @@ +/ +/ + +/ fxf -- format statements + +.globl sform +.globl sdata + +.globl ptemp +.globl error + +sform: + cmp progt,$6 / block data + bne 1f + jsr r5,error; 50. +1: + jsr r5,ptemp; 'f; efno; line + rts r5 + +sdata: + jsr r5,ptemp; 'd; efno; line + rts r5 + diff --git a/source/fort/fx/fxg.s b/source/fort/fx/fxg.s new file mode 100644 index 0000000..e1b8b27 --- /dev/null +++ b/source/fort/fx/fxg.s @@ -0,0 +1,186 @@ +/ +/ + +/ fxg -- declare implicit functions + +.globl funimpl + +.globl getname +.globl lookup + +funimpl: + bit $7,symtab(r3) + bne 1f + jsr r5,getname + mov r2,-(sp) + mov $symbuf,r2 + jsr r5,lookup; funtab + br 2f + cmpb (r2),$'\n + bne 2f + asr r0 + movb funtabt(r0),r0 + mov r0,-(sp) + bic $!17,r0 + bis typtab(r0),symtab(r3) + mov (sp)+,r0 + asr r0 + asr r0 + asr r0 + asr r0 + bic $!17,r0 + mov typtab(r0),symtab+2(r3) / save argument conversion +2: / in dimension pointer + mov (sp)+,r2 +1: + rts r5 + +typtab: + intcon + realcon + dblcon + cplxcon + dcplxcon + +funtab: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <\0> + +/ function type xy +/ x = arg types +/ y = result type +/ 0 = integer +/ 2 = real +/ 4 = double +/ 6 = complex +/ 8 = doublecomplex +funtabt: + .byte 2\<4+2 / tanh + .byte 2\<4+2 / sqrt + .byte 4\<4+2 / sngl + .byte 2\<4+2 / sin + .byte 2\<4+2 / sign + .byte 6\<4+2 / real + .byte 0\<4+0 / mod + .byte 2\<4+0 / min1 + .byte 0\<4+0 / min0 + .byte 2\<4+0 / max1 + .byte 0\<4+0 / max0 + .byte 0\<4+0 / isign + .byte 2\<4+0 / int + .byte 2\<4+0 / ifix + .byte 4\<4+0 / idint + .byte 0\<4+0 / idim + .byte 0\<4+0 / iabs + .byte 0\<4+2 / float + .byte 2\<4+2 / exp + .byte 4\<4+4 / dsqrt + .byte 4\<4+4 / dsin + .byte 4\<4+4 / dsign + .byte 8\<4+4 / dreal + .byte 4\<4+4 / dmod + .byte 4\<4+4 / dmin1 + .byte 4\<4+4 / dmax1 + .byte 4\<4+4 / dlog10 + .byte 4\<4+4 / dlog + .byte 8\<4+4 / dimag + .byte 2\<4+2 / dim + .byte 4\<4+4 / dexp + .byte 8\<4+8 / dcsqrt + .byte 8\<4+8 / dcsin + .byte 4\<4+4 / dcos + .byte 8\<4+8 / dconjg + .byte 4\<4+8 / dcmplx + .byte 8\<4+8 / dclog + .byte 8\<4+8 / dcexp + .byte 8\<4+8 / dccos + .byte 8\<4+4 / dcabs + .byte 2\<4+4 / dble + .byte 4\<4+4 / datan2 + .byte 4\<4+4 / datan + .byte 4\<4+4 / dabs + .byte 6\<4+6 / csqrt + .byte 6\<4+6 / csin + .byte 2\<4+2 / cos + .byte 6\<4+6 / conjg + .byte 2\<4+6 / cmplx + .byte 6\<4+6 / clog + .byte 6\<4+6 / cexp + .byte 6\<4+6 / ccos + .byte 6\<4+2 / cabs + .byte 2\<4+2 / atan2 + .byte 2\<4+2 / atan + .byte 2\<4+2 / amod + .byte 2\<4+2 / amin1 + .byte 0\<4+2 / amin0 + .byte 2\<4+2 / amax1 + .byte 0\<4+2 / amax0 + .byte 2\<4+2 / alog10 + .byte 2\<4+2 / alog + .byte 2\<4+2 / aint + .byte 6\<4+2 / aimag + .byte 2\<4+2 / abs diff --git a/source/fort/fx/fxh.s b/source/fort/fx/fxh.s new file mode 100644 index 0000000..7b16fcb --- /dev/null +++ b/source/fort/fx/fxh.s @@ -0,0 +1,77 @@ +/ +/ + +/ fxh -- array constant offset + +.globl consub + +.globl getsym +.globl geti +.globl error +.globl geticon + +/ turn constant subscripts into offset. +/ in: r3 -> symtab +/ r1 -> just beyond ( +/ out:r0 has offset + +consub: + mov symtab(r3),r0 + bic $!70,r0 + cmp r0,$20 / test class == array + beq 1f + jsr r5,error; 17. + clr r0 + rts r5 +1: + mov r5,-(sp) + mov r4,-(sp) + mov r3,-(sp) + mov r2,-(sp) + clr r4 / accumulated offset + mov symtab+2(r3),r2 / ptr to declarator + mov (r2)+,-(sp) / dimensionality + mov $1,r5 / prod of declarators +1: + jsr r5,geticon + br 9f + cmp r0,(r2) + bgt 3f + dec r0 + bge 2f +3: + jsr r5,error; 19. / out of range + clr r0 +2: + mov r5,-(sp) + mpy r0,r5 + add r5,r4 + mov (sp)+,r5 + mpy (r2)+,r5 + jsr r5,getsym + cmp r0,$36. / comma + bne 1f + dec (sp) + bgt 1b + jsr r5,error; 18. / wrong subscript count + br 1b +1: + cmp r0,$34. / ) + beq 1f +9: + jsr r5,error; 20. + clr r0 +1: + cmp (sp)+,$1 + beq 1f + jsr r5,error; 18. / subscript count +1: + mov (sp)+,r2 + mov (sp)+,r3 + movb symtab+1(r3),r5 + mpy r4,r5 + mov r5,r0 + mov (sp)+,r4 + mov (sp)+,r5 + rts r5 + diff --git a/source/fort/fx/fxi.s b/source/fort/fx/fxi.s new file mode 100644 index 0000000..5ed5001 --- /dev/null +++ b/source/fort/fx/fxi.s @@ -0,0 +1,145 @@ +/ +/ + +/ quicker sort + +/ mov $base,r1 +/ mov $base+[n*width],r2 +/ mov $width,r3 +/ jsr pc,qsort + +/ r0,r1,r2,r3,r4 are used + +.globl qsort +.globl compare + +qsort: + mov r5,-(sp) + mov r4,-(sp) + bit $1,r3 + bne 1f + bit $1,r1 + bne 1f + cmp r3,$2 + bne 2f + mov $exch1,exchange + br 3f +2: + mov r3,r5 + clc + ror r5 + mov r5,width + mov $exchw,exchange + br 3f +1: + mov $exchb,exchange +3: + jsr pc,qs1 + mov (sp)+,r4 + mov (sp)+,r5 + rts pc + +qs1: + mov r1,r5 + neg r5 + add r2,r5 + bgt 1f + rts pc +1: + clr r4 + dvd r3,r4 + asr r4 + mpy r3,r4 + mov r5,r4 + add r1,r4 + + mov r1,-(sp) + mov r2,-(sp) + +loop: + cmp r1,r4 + bhis loop1 + mov r1,r0 + jsr pc,compare + bgt loop1 + add r3,r1 + br loop + +loop1: + cmp r2,r4 + blos 1f + sub r3,r2 + mov r2,r0 + jsr pc,compare + bge loop1 + + jsr pc,*exchange + cmp r1,r4 + bne loop + mov r2,r4 + br loop + +1: + cmp r1,r4 + beq 1f + jsr pc,*exchange + mov r1,r4 + br loop1 + +1: + mov (sp)+,r2 + mov r4,-(sp) + mov r4,r1 + add r3,r1 + mov r2,r0 + sub r1,r0 + sub 2(sp),r4 + cmp r0,r4 + blo 1f + mov (sp)+,r0 + mov (sp)+,r4 + mov r1,-(sp) + mov r2,-(sp) + mov r0,r2 + mov r4,r1 +1: + jsr pc,qs1 + mov (sp)+,r2 + mov (sp)+,r1 + br qs1 + +exchb: + mov r1,-(sp) + mov r2,-(sp) + mov r3,r5 +1: + movb (r1),r0 + movb (r2),(r1)+ + movb r0,(r2)+ + sob r5,1b + mov (sp)+,r2 + mov (sp)+,r1 + rts pc + +exchw: + mov r1,-(sp) + mov r2,-(sp) + mov width,r5 +1: + mov (r1),r0 + mov (r2),(r1)+ + mov r0,(r2)+ + sob r5,1b + mov (sp)+,r2 + mov (sp)+,r1 + rts pc + +exch1: + mov (r1),r0 + mov (r2),(r1) + mov r0,(r2) + rts pc + +.bss +exchange: .=.+2 +width: .=.+2 diff --git a/source/fort/fx/fxx.s b/source/fort/fx/fxx.s new file mode 100644 index 0000000..f2896d1 --- /dev/null +++ b/source/fort/fx/fxx.s @@ -0,0 +1,100 @@ +/ +/ + +/ fxx -- data segment definition + +.data +.globl holround +holround: 4 + +.bss + +/ pass 1 + +.globl dimu +dimu: .=.+2 + +/ pass 2 + +.globl eqvtab + +/ pass 3 stuff + +.globl conu +.globl dou +.globl blockp +.globl dotabp +.globl dotab +.globl edotab +.globl functn +.globl blocks + +conu: .=.+2 +dou: .=.+2 +blockp: .=.+2 +dotabp: .=.+2 +dotab: .=.+60. +edotab: +functn: .=.+2 + +/ pass 4 + +.globl negflg +.globl repfact +.globl contab +.globl dattab + +negflg: .=.+2 +repfact:.=.+2 + +/ general buffer + +xbufsiz = 2200. + +.globl xbuf + +xbuf: .=.+xbufsiz + +eqvtab = xbuf+518. / for pass 2 + +blocks = xbuf / for pass 3 + +dattab = xbuf+518. / for pass 4 +contab = xbuf+xbufsiz + +/ for all passes + +data: + ibuf: .=.+518. + obuf: .=.+518. + tbuf: .=.+518. + line: .=.+linsize + eline: .=.+4 + ifno: .=.+2 + efno: .=.+2 + errp: .=.+2 / init(errb) + errb: .=.+12. + eerrb: / size 0 mod 4 + symtab: .=.+symsize + esymtab: + esymp: .=.+2 / init(esymtab) + symtp: .=.+2 + namebuf:.=.+namsize + enamebuf: + namep: .=.+2 / init(namebuf) +.=.+40 /fake + .=.+1 / make odd + symbuf: .=.+smblsize / init(<_>) + esymbuf: + ch: .=.+1 + ch1: .=.+1 + progt: .=.+2 + holquo: .=.+2 + nxtaloc:.=.+2 + imptab: .=.+[26.*2*2] / 26 letters, 2 alphabets, 2 bytes + nerror: .=.+2 + temp: .=.+2 + functm: .=.+2 +edata: +dsize =.-data + diff --git a/source/fort/io/io1.s b/source/fort/io/io1.s new file mode 100644 index 0000000..3d42604 --- /dev/null +++ b/source/fort/io/io1.s @@ -0,0 +1,78 @@ +/ +/ + +/ io1 -- I/O operators + + +.globl rerr +.globl endio +.globl rio4 +.globl rio8 +.globl iio2 +.globl iio4 +.globl lio2 +.globl lio1 +.globl cio8 +.globl cio16 +.globl ecvt +.globl fcvt +.globl _ndigit + +endio: + mov (sp)+,r5 + rts r5 + +cio8: + tst slcnt + bne 2f + inc slcnt + tst -(r4) + br rio4 +2: + clr slcnt + mov ilval,-(sp) + add $4,(sp) + br rio4 + +cio16: + tst slcnt + bne 2f + inc slcnt + tst -(r4) + br rio8 +2: + clr slcnt + mov ilval,-(sp) + add $8,(sp) + br rio8 + +rio8: + mov $8.\<8+'r,r0 + br 1f + +rio4: + mov $4\<8+'r,r0 + br 1f + +iio4: + mov $4\<8+'i,r0 + br 1f + +iio2: + mov $2\<8+'i,r0 + br 1f + +lio2: + mov $2\<8+'l,r0 + br 1f + +lio1: + mov $1\<8+'l,r0 + +1: + mov r0,itype + mov (sp)+,ilval + mov (sp)+,r5 + tst (r5)+ + rts r5 + diff --git a/source/fort/io/io2.s b/source/fort/io/io2.s new file mode 100644 index 0000000..c4e21f6 --- /dev/null +++ b/source/fort/io/io2.s @@ -0,0 +1,268 @@ +/ +/ + +/ io2 -- format cracker + +.globl iowf +.globl iowp +.globl iorf + +iowp: + mov (sp)+,formp + mov $6,r1 + br 1f + +iowf: + mov (sp)+,formp + tst (sp)+ + mov (sp)+,r1 +1: + jsr r5,setio; 2 / write + clr rdflg + br 1f + +iorf: + mov (sp)+,formp + tst (sp)+ + mov (sp)+,r1 + jsr r5,setio; 1 / read + mov pc,rdflg + +1: + clr binflg + clr slcnt + clr itmfnd + clr scale + clr itmflg + mov $pbuf,ppar + mov $-1,llpcnt + jsr r5,fmtchr + mov formp,llp + cmp r0,$'( + beq crack + jsr r5,rerr; 106. + sys exit +crack: + clr ngflg + mov $1,rep +item: + jsr r5,fmtchr + cmp $' ,r0 + beq item + cmp $'\t,r0 + beq item + jsr r5,switch; mswitch + jsr r5,rerr; 105. + sys exit + +mswitch: + 'a; afmt + 'f; ffmt + 'e; efmt + 'g; gfmt + 'd; dfmt + 'i; ifmt + 'l; lfmt + 'h; hfmt + 'x; xfmt + 'p; scal + '-; minus + '0; numb + '1; numb + '2; numb + '3; numb + '4; numb + '5; numb + '6; numb + '7; numb + '8; numb + '9; numb + ',; crack + '/; slash + '(; lpar + '); rpar + '"; quote + ' ; item + 0; 0 + +minus: + jsr r5,gnum + neg r0 + br 1f +numb: + dec formp + jsr r5,gnum +1: + mov r0,rep + br item + +scal: + mov rep,scale + br crack + +elist: + tst _nocr + beq 1f + tst rdflg + bne 1f + jsr r5,eorec1 + br 2f +1: + jsr r5,eorec +2: + jmp *(r4)+ + +slash: + jsr r5,eorec + br crack + +rpar: + mov ppar,r0 + cmp r0,$pbuf / see if outer parens + blos 2f + dec -2(r0) + ble 1f / no repeats left + mov -4(r0),formp / reset scan + br crack +1: + sub $4,ppar + br crack / pop parens +2: + jsr r5,getitm + br elist + tst itmfnd + bne 1f + jsr r5,rerr; 107. + sys exit +1: + jsr r5,eorec + inc itmflg + mov llpcnt,r1 + bpl 1f + mov llp,formp + jmp crack +1: + mov llp,r2 + mov r2,formp + mov ppar,r0 + mov r2,(r0)+ + mov r1,(r0)+ + mov r0,ppar + jbr crack1 + +lpar: + mov ppar,r0 + cmp r0,$pbuf+10 + blo 1f + jsr r5,rerr; 108. + sys exit +1: + mov formp,(r0)+ + mov rep,(r0)+ + mov r0,ppar + cmp r0,$pbuf+4 + bhi 1f + mov formp,llp + mov rep,llpcnt +1: + jmp crack +quote: + inc ngflg + mov $44,-(sp) + br 3f + +hfmt: + inc ngflg + mov $40,-(sp) + br 3f + +xfmt: + inc ngflg + mov $34,-(sp) + br 3f + +afmt: + mov $30,-(sp) + br 1f + +ifmt: + clr -(sp) + br 1f + +lfmt: + mov $4,-(sp) +1: + jsr r5,gnum + mov r0,width + br 2f + +ffmt: + mov $10,-(sp) + br 1f + +dfmt: + mov $14,-(sp) + br 1f + +gfmt: + mov $20,-(sp) + br 1f + +efmt: + mov $24,-(sp) + +1: + jsr r5,gnum + mov r0,width +4: + jsr r5,fmtchr + cmp r0,$' / + beq 4b + cmp r0,$'. + bne err1 + jsr r5,gnum + mov r0,ndig +2: + inc itmfnd +3: + add $cvsw,(sp) + tst rdflg + beq 1f + add $2,(sp) +1: + mov *(sp)+,-(sp) +1: + tst ngflg + bne 2f + jsr r5,getitm + br 1f +2: + clr gflg + jsr r5,*(sp) + dec rep + bgt 1b + tst (sp)+ + br crack1 +1: + tst (sp)+ + jmp elist + +cvsw: + iocv; iicv / 0 + locv; licv / 4 + focv; ficv / 10 + docv; dicv / 14 + gocv; gicv / 20 + eocv; eicv / 24 + aocv; aicv / 30 + xocv; xicv / 34 + hocv; hicv / 40 + qocv; qicv / 44 + +crack1: + jmp crack + +err1: + jsr r5,rerr; 109. + sys exit + diff --git a/source/fort/io/io3.s b/source/fort/io/io3.s new file mode 100644 index 0000000..03f0801 --- /dev/null +++ b/source/fort/io/io3.s @@ -0,0 +1,299 @@ +/ +/ + +/ io3 -- Fortran I/O + +.globl getbuf +.globl chkunit +.globl creatf +.globl openf + +setio: + mov r1,unit + jsr r5,chkunit + movb utable(r1),r0 + beq 1f + bpl 2f + mov r1,r0 + asl r0 + mov btable(r0),r0 + mov r0,r2 + br 4f +2: + cmp (r5),r0 + beq 3f + jsr r5,rerr; 101. / inconsistent use of unit + sys exit +1: + mov r1,-(sp) + clr r0 + dvd $10.,r0 + swab r1 + bis r1,r0 + add $"00,r0 + mov r0,filnam+4 + mov (sp)+,r1 + jsr r5,getbuf + mov $filnam,r0 +4: + movb (r5),utable(r1) + bit $1,(r5) + bne 2f + jsr r5,creatf + br 3f +2: + jsr r5,openf +3: + tst (r5)+ + asl r1 + mov btable(r1),buffer + rts r5 + +getbuf: + mov $utable,r0 + mov $btable,r2 +1: + tstb (r0)+ + beq 2f + tst (r2)+ + br 3f +2: + tst (r2)+ + beq 3f + mov -(r2),r0 + clr (r2) + mov r0,r2 + br 2f +3: + cmp r0,$utable+20. + blo 1b + mov bufp,r2 + add $134.,bufp + mov bufp,0f + sys break; 0:.. +2: + mov r1,r0 + asl r0 + mov r2,btable(r0) + mov r2,buffer + rts r5 + +chkunit: + cmp r1,$20. + blo 1f + jsr r5,rerr; 100. / illegal unit number + sys exit +1: + rts r5 + +creatf: + cmp unit,$6 + bne 2f + mov $1,r0 + br 1f +2: + mov r0,0f + sys creat; 0:..; 666 + bec 1f + jsr r5,rerr; 102. / create error + sys exit +1: + mov r2,-(sp) + mov r0,(r2)+ + clr (r2)+ + clr (r2)+ + mov r2,-(r2) + mov (sp)+,r2 + rts r5 + +openf: + cmp unit,$5 + bne 2f + clr r0 + br 1f +2: + mov r0,0f + sys open; 0:..; 0 + bec 1f + jsr r5,rerr; 103. / open error + sys exit +1: + mov r2,-(sp) + mov r0,(r2)+ + clr (r2)+ + clr (r2)+ + mov (sp)+,r2 + rts r5 + +fputc: + mov r1,-(sp) + mov buffer,r1 + dec 2(r1) + bge 1f + mov r0,-(sp) + jsr pc,flush1 + dec 2(r1) + mov (sp)+,r0 +1: + movb r0,*4(r1) + inc 4(r1) + mov (sp)+,r1 + rts r5 + +fflush: + mov r1,-(sp) + mov buffer,r1 + jsr pc,flush1 + mov (sp)+,r1 + rts r5 + +flush1: + mov r1,r0 + add $6,r0 + mov r0,-(sp) + mov r0,0f + neg r0 + add 4(r1),r0 + bhis 1f + mov r0,0f+2 + mov (r1),r0 + sys write; 0:..; .. +1: + mov (sp)+,4(r1) + mov $128.,2(r1) + rts pc + +fgetc: + tst nlflg + bne 4f + mov r1,-(sp) + mov buffer,r1 + dec 2(r1) + bge 1f + mov r1,r0 + add $6,r0 + mov r0,0f + mov r0,4(r1) + mov (r1),r0 + sys read; 0:..; 128. + bes 2f + tst r0 + bne 3f +2: + jsr r5,rerr; 104. / EOF on input + sys exit +3: + dec r0 + mov r0,2(r1) +1: + clr r0 + bisb *4(r1),r0 + inc 4(r1) + mov (sp)+,r1 + tst binflg + bne 1f + cmp r0,$'\n + bne 1f +4: + mov pc,nlflg + mov $' ,r0 +1: + rts r5 + +gnum: + mov r1,-(sp) + clr r1 +1: + jsr r5,fmtchr + cmp r0,$' / + beq 1b + sub $'0,r0 + cmp r0,$9. + bhi 1f + mpy $10.,r1 + add r0,r1 + br 1b +1: + mov r1,r0 + mov (sp)+,r1 + dec formp + rts r5 + +switch: + mov (r5)+,r1 +1: + tst (r1) + beq 1f + cmp r0,(r1)+ + bne 1b + tst (sp)+ + jmp *(r1) +1: + rts r5 + +fmtchr: + movb *formp,r0 + inc formp + rts r5 + +getitm: + tst itmflg + bne 1f + mov r5,-(sp) + jmp *(r4)+ +1: + clr itmflg + tst (r5)+ + rts r5 + +/ just a fake, there's no carriage control + +fputcc: + cmp $' ,r0 + bne 1f + inc nspace + rts r5 +1: + mov r0,-(sp) +1: + dec nspace + blt 1f + mov $' ,r0 + jsr r5,fputc + br 1b +1: + clr nspace + mov (sp)+,r0 + beq 1f + jsr r5,fputc +1: + rts r5 + +eorec: + mov unit,r0 + bitb $1,utable(r0) + bne 1f + clr nspace + mov $'\n,r0 + jsr r5,fputc +eorec1: + clr r0 + jsr r5,fputcc +/ cmp unit,$6 / tty output +/ bne 2f + jsr r5,fflush +2: + rts r5 +1: + tst nlflg + bne 1f + jsr r5,fgetc + br 1b +1: + clr nlflg + rts r5 + +spaces: + add r1,nspace + rts r5 + diff --git a/source/fort/io/io4.s b/source/fort/io/io4.s new file mode 100644 index 0000000..be1eb6d --- /dev/null +++ b/source/fort/io/io4.s @@ -0,0 +1,231 @@ +/ +/ + +/ io4 -- numeric output conversion + +qicv: +hicv: + jsr r5,rerr; 999. + sys exit + +xicv: + jsr r5,fgetc + rts r5 + +gocv: + mov pc,gflg + jsr r5,getarg + mov ndig,_ndigit + jsr pc,ecvt + tst r2 + bmi eocv + cmp r2,ndig + bgt eocv + sub r2,ndig + sub $4,width + jsr r5,focv + add $4,width + add $4,nspace + rts r5 + +eocv: + mov $'e,-(sp) + br 1f + +docv: + mov $'d,-(sp) +1: + tst gflg + bne 1f + jsr r5,getarg +1: + mov ndig,r1 + add $6,r1 + add nflg,r1 + sub width,r1 + bge 2f + sub r1,nspace +2: + tst nflg + beq 2f + mov $'-,r0 + jsr r5,fputcc +2: + mov ndig,r1 + mov scale,r0 + bgt 2f + add r0,r1 + br 3f +2: + inc r1 +3: + mov r1,_ndigit + jsr pc,ecvt + mov r0,r1 + mov r2,-(sp) + mov scale,r2 + sub r2,(sp) + tst r2 + bgt 2f + mov $'0,r0 + jsr r5,fputcc + br 3f +2: + movb (r1)+,r0 + dec _ndigit + jsr r5,fputcc + sob r2,2b +3: + mov $'.,r0 + jsr r5,fputcc + neg r2 + ble 2f +3: + mov $'0,r0 + jsr r5,fputcc + sob r2,3b +2: + mov _ndigit,r2 + ble 2f +3: + movb (r1)+,r0 + jsr r5,fputcc + sob r2,3b +2: + mov 2(sp),r0 + jsr r5,fputcc + mov (sp)+,r1 + bge 2f + mov $'-,r0 + jsr r5,fputcc + neg r1 + br 3f +2: + mov $'+,r0 + jsr r5,fputcc +3: + clr r0 + div $10.,r0 + add $'0,r0 + jsr r5,fputcc + mov r1,r0 + add $'0,r0 + jsr r5,fputcc + tst (sp)+ + rts r5 + +iocv: + clr -(sp) + clr ndig + br 1f + +focv: + mov $1,-(sp) +1: + clr -(sp) + tst gflg + bne 1f + jsr r5,getarg + tst 2(sp) + beq 1f + mov scale,(sp) +1: + mov ndig,_ndigit + add (sp)+,_ndigit + jsr pc,fcvt + mov r0,r1 + tst (sp) + beq 1f + tst gflg + bne 1f + add scale,r2 +1: + mov ndig,r0 + add (sp),r0 + add nflg,r0 + tst r2 + ble 1f + add r2,r0 + br 2f +1: + inc r0 +2: + sub width,r0 + bge 1f + sub r0,nspace +1: + tst nflg + beq 1f + mov $'-,r0 + jsr r5,fputcc +1: + tst r2 + bgt 1f + mov $'0,r0 + jsr r5,fputcc + br 2f +1: + movb (r1)+,r0 + jsr r5,fputcc + sob r2,1b +2: + tst (sp)+ + beq 1f + mov $'.,r0 + jsr r5,fputcc +1: + mov ndig,-(sp) + ble 1f + tst r2 + bge 1f + neg r2 +2: + mov $'0,r0 + jsr r5,fputcc + dec ndig + ble 1f + sob r2,2b +1: + mov ndig,r2 + ble 2f +1: + movb (r1)+,r0 + jsr r5,fputcc + sob r2,1b +2: + mov (sp)+,ndig + rts r5 + +getarg: + clr nflg + setd + cmpb itype,$'r + beq 1f + seti + cmpb ilen,$4 + bne 2f + setl +2: + cmpb ilen,$1 + beq 3f + movif *ilval,r0 + br 2f +3: + movb *ilval,r0 + movif r0,fr0 + br 2f +1: + cmpb ilen,$4 + bne 1f + movof *ilval,r0 + br 2f +1: + movf *ilval,r0 +2: + cfcc + bge 1f + absf r0 + mov $1,nflg +1: + rts r5 + diff --git a/source/fort/io/io5.s b/source/fort/io/io5.s new file mode 100644 index 0000000..59d7bcb --- /dev/null +++ b/source/fort/io/io5.s @@ -0,0 +1,96 @@ +/ +/ + +/ io5 -- more conversions + +/.globl hocv +/.globl qocv +/.globl xocv +/.globl aocv +/.globl locv +/ +/.globl fmtchr +/.globl fputcc +/.globl rep +/.globl formp +/.globl spaces +/.globl ilen +/.globl width +/.globl ilval +.globl rerr + +hocv: + jsr r5,fmtchr + tst r0 + beq 2f + jsr r5,fputcc + dec rep + bgt hocv + rts r5 +2: + jsr r5,rerr; 111. + sys exit + +qocv: + mov formp,-(sp) +1: + jsr r5,fmtchr + tst r0 + beq 2f + cmp r0,$'" + beq 2f + jsr r5,fputcc + br 1b +2: + dec rep + ble 1f + mov (sp),formp + br 1b +1: + tst (sp)+ + rts r5 + +xocv: + mov $1,r1 + jsr r5,spaces + rts r5 + +aocv: + movb ilen,r1 + sub width,r1 + neg r1 + bpl 1f + clr r1 +1: + jsr r5,spaces + mov ilval,r2 + mov width,r1 + cmpb r1,ilen + ble 2f + movb ilen,r1 +2: + movb (r2)+,r0 + jsr r5,fputcc + dec r1 + bgt 2b + rts r5 + +locv: + mov width,r1 + dec r1 + jsr r5,spaces + mov $'f,r0 + movb ilen,r1 + mov ilval,r2 +2: + tstb (r2)+ + bne 1f + dec r1 + bgt 2b + br 2f +1: + mov $'t,r0 +2: + jsr r5,fputcc + rts r5 + diff --git a/source/fort/io/io6.s b/source/fort/io/io6.s new file mode 100644 index 0000000..13d144e --- /dev/null +++ b/source/fort/io/io6.s @@ -0,0 +1,248 @@ +/ +/ + +/ io6 -- input conversions + +/.globl aicv +/.globl gicv +/ +/.globl ilval +/.globl width +/.globl ilen +/.globl fgetc +/.globl itype +/.globl nlflg +/.globl gcflg + +aicv: + mov ilval,r1 + movb width,r2 + movb ilen,r0 + mov r0,-(sp) +1: + cmp r2,(sp) + ble 1f + jsr r5,fgetc + dec r2 + br 1b +1: + tst r2 + ble 1f + jsr r5,fgetc + movb r0,(r1)+ + dec r2 + dec (sp) + br 1b +1: + tst (sp) + ble 1f + movb $' ,(r1)+ + dec (sp) + br 1b +1: + tst (sp)+ + rts r5 + +licv: + mov width,twidth + setd + seti + clrf fr0 +1: + jsr r5,fgetcn + cmp r0,$'t + beq 2f + cmp r0,$'T + beq 2f + cmp r0,$'1 + beq 2f + cmp r0,$', + beq 1f + br 1b +2: + movif $1,fr0 + br 1b +1: + br storin + +iicv: + clr ndig + +ficv: +eicv: +dicv: + mov width,twidth + br 1f + +gicv: + mov $16383.,twidth + clr ndig + mov pc,gcflg + br 2f +1: + clr gcflg +2: + jsr r5,gatof +storin: + cmpb itype,$'r + beq 1f + cmpb ilen,$1 + beq 3f + cmpb ilen,$4 + bne 2f + setl +2: + movfi fr0,*ilval + rts r5 +3: + movfi fr0,r0 + movb r0,*ilval + rts r5 +1: + cmpb ilen,$8. + beq 2f + setf +2: + movf fr0,*ilval + rts r5 + +gatof: + setd + seti + movif $10.,fr3 + clr r2 + clrf fr0 + clr -(sp) +1: + jsr r5,fgetcn + cmp $' ,r0 + bne 1f + tst nlflg + beq 1b + tst (sp)+ + rts r5 +1: + cmp r0,$'+ + beq 1f + cmp r0,$'- + bne 2f + inc (sp) +1: + jsr r5,fgetcn +2: + cmp $' ,r0 + bne 3f + tst gcflg + bne 3f + mov $'0,r0 +3: + sub $'0,r0 + cmp r0,$9. + bhi 2f + mulf fr3,fr0 + movif r0,fr1 + addf fr1,fr0 + dec r1 + br 1b +2: + add $'0,r0 + cmp r0,$'. + bne 1f + inc r2 + clr r1 + br 1b +1: + mov r3,-(sp) + clr r3 + cmp r0,$'d + beq 3f + cmp r0,$'+ + beq 3f + cmp r0,$'- + beq 3f + cmp r0,$'e + bne 2f +3: + jsr r5,atoi +2: + tst r2 + bne 1f + mov ndig,r1 + neg r1 +1: + movf fr3,fr2 + add r3,r1 + mov (sp)+,r3 + tst r1 + beq 1f + bpl 3f + neg r1 + mov pc,-(sp) + br 2f +3: + clr -(sp) +2: + dec r1 + ble 2f + mulf fr3,fr2 + br 2b +2: + tst (sp)+ + bne 2f + mulf fr2,fr0 + br 1f +2: + divf fr2,fr0 +1: + tst (sp)+ + beq 1f + negf r0 +1: + cmp r0,$', + beq 1f + cmp $' ,r0 + beq 1f + jsr r5,rerr; 110. +1: + rts r5 + +atoi: + clr -(sp) + cmp r0,$'+ + beq 1f + cmp r0,$'- + beq 3f + jsr r5,fgetcn + cmp r0,$'+ + beq 1f + cmp r0,$'- + bne 2f +3: + inc (sp) +1: + jsr r5,fgetcn +2: + sub $'0,r0 + cmp r0,$'9. + bhi 2f + mpy $10.,r3 + add r0,r3 + br 1b +2: + add $'0,r0 + tst (sp)+ + beq 1f + neg r3 +1: + rts r5 + +fgetcn: + tst twidth + bgt 1f + mov $',,r0 + rts r5 +1: + jsr r5,fgetc + dec twidth + rts r5 + diff --git a/source/fort/io/io7.s b/source/fort/io/io7.s new file mode 100644 index 0000000..ff9a6fd --- /dev/null +++ b/source/fort/io/io7.s @@ -0,0 +1,62 @@ +/ +/ + +/ Fortran binary I/O + +.globl iowu +.globl ioru +.globl rewi +.globl enfl + +iowu: + tst (sp)+ + mov (sp)+,r1 / unit number + jsr r5,setio; 42 +1: + jsr r5,getitm + br 1f + movb ilen,r1 + mov ilval,r2 +2: + movb (r2)+,r0 + jsr r5,fputc + sob r1,2b + br 1b +1: + jsr r5,fflush + jmp *(r4)+ + +ioru: + tst (sp)+ + mov (sp)+,r1 / unit number + jsr r5,setio; 41 + clr nlflg + mov pc,binflg +1: + jsr r5,getitm + br 1f + movb ilen,r1 + mov ilval,r2 +2: + jsr r5,fgetc + movb r0,(r2)+ + sob r1,2b + br 1b +1: + jmp *(r4)+ + +rewi: +enfl: + tst (sp)+ + mov (sp)+,r1 / unit number + jsr r5,chkunit + clrb utable(r1) + asl r1 + mov *btable(r1),r0 + cmp r0,$1 + bhi 1f + sys seek; 0; 0 + jmp *(r4)+ +1: + sys close + jmp *(r4)+ diff --git a/source/fort/io/iox.s b/source/fort/io/iox.s new file mode 100644 index 0000000..b1ddcad --- /dev/null +++ b/source/fort/io/iox.s @@ -0,0 +1,51 @@ +/ +/ + +/ iox -- io variables + +.globl _nocr +.globl utable +.globl btable +.globl ftable + +.globl _end +.globl formp + +bufp: _end +filnam: + ; .even + + .bss + +gflg: .=.+2 +formp: .=.+2 +rdflg: .=.+2 +nflg: .=.+2 +unit: .=.+2 +buffer: .=.+2 +slcnt: .=.+2 +itype: .=.+1 +ilen: .=.+1 +ilval: .=.+2 +width: .=.+2 +twidth: .=.+2 +ndig: .=.+2 +pbuf: .=.+10 +ppar: .=.+2 +llp: .=.+2 +llpcnt: .=.+2 +itmflg: .=.+2 +nspace: .=.+2 +gcflg: .=.+2 +binflg: .=.+2 + +utable: .=.+20. +btable: .=.+40. +ftable: .=.+2. +rep: .=.+2 +scale: .=.+2 +itmfnd: .=.+2 +ngflg: .=.+2 +nlflg: .=.+2 +_nocr: .=.+2 + diff --git a/source/fort/rt/r0.s b/source/fort/rt/r0.s new file mode 100644 index 0000000..8050d36 --- /dev/null +++ b/source/fort/rt/r0.s @@ -0,0 +1,50 @@ +/ +/ + +.globl main +.globl temp +.globl rerr +.globl fptrap + +.comm erret,2 +.comm argp,2 + +ldfps = 170100^tst + + sys signal; 4; fptrap + ldfps $5400 + mov sp,argp + mov $main,r4 + jmp *(r4)+ + +rerr: + mov (r5)+,r1 + tst erret + beq 1f + jsr pc,erret +1: + mov $temp,r2 + jsr r5,1f + movb $'\n,(r2)+ + sub $mesg,r2 + mov r2,0f + mov $2,r0 + sys write; mesg; 0:.. + sys exit +1: + clr r0 + div $10.,r0 + mov r1,-(sp) + mov r0,r1 + beq 1f + jsr r5,1b +1: + mov (sp)+,r0 + add $'0,r0 + movb r0,(r2)+ + rts r5 + +mesg: + +temp: .=.+16. + diff --git a/source/fort/rt/r1.s b/source/fort/rt/r1.s new file mode 100644 index 0000000..a162e5b --- /dev/null +++ b/source/fort/rt/r1.s @@ -0,0 +1,147 @@ +/ +/ + +/ r1 -- fortran runtime + +.globl gas1 +.globl gas2 +.globl gas4 +.globl gas8 +.globl stop +.globl lval +.globl rval4 +.globl rval8 +.globl do1 +.globl do12 +.globl do14 +.globl do2 +.globl do22 +.globl do24 +.globl goto +.globl cgoto +.globl cagoto +.globl agoto + +.globl rerr + +gas8: + mov 8.(sp),r0 + mov (sp)+,(r0)+ + mov (sp)+,(r0)+ + br 1f + +gas1: + movb (sp)+,*(sp)+ + jmp *(r4)+ + +gas2: + mov (sp)+,*(sp)+ + jmp *(r4)+ + +gas4: + mov 4(sp),r0 +1: + mov (sp)+,(r0)+ + mov (sp)+,(r0) + tst (sp)+ + jmp *(r4)+ + +stop: + sys exit + +lval: + mov (r4)+,-(sp) + jmp *(r4)+ + +rval8: + mov (r4)+,r0 + add $8.,r0 + mov -(r0),-(sp) + mov -(r0),-(sp) + mov -(r0),-(sp) + mov -(r0),-(sp) + jmp *(r4)+ + +rval4: + mov (r4)+,r0 + mov 2(r0),-(sp) + mov (r0),-(sp) + jmp *(r4)+ + +do22: + mov (sp)+,r1 + br 1f + +do12: + mov $1,r1 +1: + mov (sp)+,r2 + mov (sp)+,r0 + add r1,(r0) + cmp (r0),r2 + bgt goto + tst (r4)+ + jmp *(r4)+ + +do24: +do2: + mov (sp)+,r2 + mov (sp)+,r1 + br 1f + +do14: +do1: + clr r2 + mov $1,r1 +1: + mov 4(sp),r0 + add r1,2(r0) + adc r2 + add r2,(r0) + cmp (r0)+,(sp)+ + bgt 1f + blt 2f + cmp (r0),(sp) + bhi 1f +2: + cmp (sp)+,(sp)+ + tst (r4)+ + jmp *(r4)+ + +1: + cmp (sp)+,(sp)+ +goto: + mov (r4),r4 + jmp *(r4)+ + +cgoto: + tst (sp)+ + mov (sp)+,r0 + asl r0 + add r4,r0 +1: + tst (r4)+ + beq gotoe + cmp r0,r4 + bne 1b + mov -(r0),r4 + jmp *(r4)+ +cagoto: + tst (sp)+ + mov (sp)+,r0 +1: + tst (r4) + beq gotoe + cmp r0,(r4)+ + bne 1b + mov r0,r4 + jmp *(r4)+ + +agoto: + tst (sp)+ + mov (sp)+,r4 + jmp *(r4)+ + +gotoe: + jsr r5,rerr; 14. + diff --git a/source/fort/rt/r2.s b/source/fort/rt/r2.s new file mode 100644 index 0000000..20731c8 --- /dev/null +++ b/source/fort/rt/r2.s @@ -0,0 +1,143 @@ +/ +/ + +/ r2 -- comparison of 4-byte integers + +.globl ilt4 +.globl ile4 +.globl ieq4 +.globl ine4 +.globl ige4 +.globl igt4 +.globl lan2 +.globl lor2 +.globl lnt2 +.globl ieq2 +.globl ile2 +.globl igt2 +.globl ige2 +.globl leq2 +.globl ine2 +.globl ilt2 +.globl lne2 +.globl leq1 +.globl lne1 + +ilt4: + jsr pc,compar + blt one + br zero + blo one + br zero + +ile4: + jsr pc,compar + ble one + br zero + blos one + br zero + +ieq4: + jsr pc,compar + beq one + br zero + beq one + br zero + +ine4: + jsr pc,compar + bne one + br zero + bne one + br zero + +ige4: + jsr pc,compar + bge one + br zero + bhis one + br zero + +igt4: + jsr pc,compar + bgt one + br zero + bhi one + br zero + +one: + mov $1,(sp) + jmp *(r4)+ + +zero: + clr (sp) + jmp *(r4)+ + +compar: + mov (sp)+,r0 + mov (sp)+,r1 + mov (sp)+,r2 + cmp (sp)+,r1 + beq 1f + jmp (r0) +1: + cmp (sp),r2 + jmp 4(r0) + +lor2: + bis (sp)+,(sp) + jmp *(r4)+ + +lan2: + tst (sp)+ + bne 1f + clr (sp) +1: + jmp *(r4)+ + +lnt2: + tst (sp) + beq one + br zero + +ieq2: +leq2: + cmp (sp)+,(sp) + beq one + br zero + +ilt2: cmp (sp)+,(sp) + bgt one + br zero + +ile2: + cmp (sp)+,(sp) + bge one + br zero + +igt2: + cmp (sp)+,(sp) + blt one + br zero + +ige2: + cmp (sp)+,(sp) + ble one + br zero + +ine2: +lne2: + cmp (sp)+,(sp) + bne one + br zero + +leq1: + cmpb (sp)+,(sp) + beq one + br zero + +lne1: + cmpb (sp)+,(sp) + bne one + br zero + diff --git a/source/fort/rt/r3.s b/source/fort/rt/r3.s new file mode 100644 index 0000000..53c9bbe --- /dev/null +++ b/source/fort/rt/r3.s @@ -0,0 +1,50 @@ +/ +/ + +/ r3 -- comparisons + +.globl lif2 +.globl lif1 +.globl rif4 +.globl iif2 +.globl iif4 +.globl rif8 + +lif2: +lif1: + tst (sp)+ + bne 1f + mov (r4),r4 + jmp *(r4)+ +1: + tst (r4)+ + jmp *(r4)+ + +rif8: + setd + tstf (sp)+ + cfcc + br 2f + +iif4: +rif4: + mov (sp)+,r0 + mov (sp)+,r1 + tst r0 + bne 2f + tst r1 + cln + br 2f + +iif2: + tst (sp)+ +2: + bmi 1f + beq 2f + tst (r4)+ +2: + tst (r4)+ +1: + mov (r4),r4 + jmp *(r4)+ + diff --git a/source/fort/rt/r4.s b/source/fort/rt/r4.s new file mode 100644 index 0000000..64e6b15 --- /dev/null +++ b/source/fort/rt/r4.s @@ -0,0 +1,65 @@ +/ +/ + +/ r4 -- short integer arithmetic + +.globl iad2 +.globl isb2 +.globl imp2 +.globl idv2 +.globl i2i4 +.globl i1i4 +.globl i4i2 +.globl i4i1 +.globl ing2 +.globl rval2 +.globl rval1 +.globl l2l1 + +iad2: + add (sp)+,(sp) + jmp *(r4)+ + +isb2: + sub (sp)+,(sp) + jmp *(r4)+ + +imp2: + mov (sp)+,r1 + mul (sp)+,r1 + mov r1,-(sp) + jmp *(r4)+ + +idv2: + mov 2(sp),r1 + sxt r0 + div (sp)+,r0 + mov r0,(sp) + jmp *(r4)+ + +i4i2: +i4i1: + tst (sp)+ + jmp *(r4)+ + +i2i4: +i1i4: + tst (sp) + sxt -(sp) + jmp *(r4)+ + +ing2: + neg (sp) + jmp *(r4)+ + +rval2: + mov *(r4)+,-(sp) + jmp *(r4)+ + +rval1: + movb *(r4)+,r0 + mov r0,-(sp) + +l2l1: + jmp *(r4)+ + diff --git a/source/fort/rt/r5.s b/source/fort/rt/r5.s new file mode 100644 index 0000000..8b11561 --- /dev/null +++ b/source/fort/rt/r5.s @@ -0,0 +1,49 @@ +/ +/ + +/ r5 -- long integer arithmetic + +.globl iad4 +.globl isb4 +.globl imp4 +.globl idv4 +.globl ing4 +.globl rerr + +iad4: + jsr pc,load + addf fr0,fr1 + br store + +isb4: + jsr pc,load + subf fr0,fr1 + br store + +imp4: + jsr pc,load + mulf fr0,fr1 + br store + +idv4: + jsr pc,load + divf fr0,fr1 + +store: + movfi fr1,-(sp) + jmp *(r4)+ + +load: + mov (sp)+,r0 + setd + setl + movif (sp)+,fr0 + movif (sp)+,fr1 + jmp (r0) + +ing4: + neg (sp) + neg 2(sp) + sbc (sp) + jmp *(r4)+ + diff --git a/source/fort/rt/r6.s b/source/fort/rt/r6.s new file mode 100644 index 0000000..d53c955 --- /dev/null +++ b/source/fort/rt/r6.s @@ -0,0 +1,137 @@ +/ +/ + +/ r6 -- real arithmetic + +.globl rad4 +.globl rad8 +.globl rsb4 +.globl rsb8 +.globl rmp4 +.globl rmp8 +.globl rdv4 +.globl rdv8 +.globl rng4 +.globl rng8 +.globl r4r8 +.globl r8r4 +.globl i4r4 +.globl i2r4 +.globl r4i4 +.globl r8i2 +.globl i2r8 +.globl r4i2 +.globl i4r8 +.globl r8i4 +.globl rerr + +rad8: + setd + br 1f +rad4: + setf +1: + movf (sp)+,fr0 + addf (sp)+,fr0 + br store + +rsb8: + setd + br 1f +rsb4: + setf +1: + movf (sp)+,fr0 + negf fr0 + addf (sp)+,fr0 + br store + +rmp8: + setd + br 1f +rmp4: + setf +1: + movf (sp)+,fr0 + mulf (sp)+,fr0 + br store + +rdv8: + setd + br 1f +rdv4: + setf +1: + movf (sp)+,fr1 + movf (sp)+,fr0 + divf fr1,fr0 + +store: + movf fr0,-(sp) + jmp *(r4)+ + +rng8: + setd + br 1f +rng4: + setf +1: + negf (sp) + jmp *(r4)+ + +r8r4: + setd + br 1f +r4r8: + setf +1: + movf (sp)+,fr0 + movfo fr0,-(sp) + jmp *(r4)+ + +i2r8: + seti + br 1f + +i4r8: + setl +1: + setd + br 2f + +i2r4: + seti + br 1f + +i4r4: + setl +1: + setf +2: + movif (sp)+,fr0 + movf fr0,-(sp) + jmp *(r4)+ + +r8i2: + seti + br 1f + +r8i4: + setl +1: + setd + br 2f + +r4i2: + seti + br 1f + +r4i4: + setl +1: + setf +2: + movf (sp)+,fr0 + movfi fr0,-(sp) + jmp *(r4)+ + diff --git a/source/fort/rt/r7.s b/source/fort/rt/r7.s new file mode 100644 index 0000000..2def643 --- /dev/null +++ b/source/fort/rt/r7.s @@ -0,0 +1,124 @@ +/ +/ + +/ r7 -- fortran runtime + +achk = 1 / 1 to check array bounds +.globl lvalp +.globl rval1p +.globl rval2p +.globl rval4p +.globl rval8p +.globl alval +.globl alvalp +.globl arval +.globl arvalp + +.globl rerr + +lvalp: + mov r3,r0 + add (r4)+,r0 + mov (r0)+,-(sp) + jmp *(r4)+ + +rval1p: + mov r3,r0 + add (r4)+,r0 + movb *(r0)+,-(sp) + jmp *(r4)+ + +rval2p: + mov r3,r0 + add (r4)+,r0 + mov *(r0)+,-(sp) + jmp *(r4)+ + +rval4p: + mov r3,r0 + add (r4)+,r0 + mov (r0),r0 + cmp (r0)+,(r0)+ + mov -(r0),-(sp) + mov -(r0),-(sp) + jmp *(r4)+ + +rval8p: + setd + mov r3,r0 + add (r4)+,r0 + movf *(r0)+,fr0 + movf fr0,-(sp) + jmp *(r4)+ + +alval: + jsr r5,getsub; 1 + mov (r4)+,-(sp) + add r1,(sp) + jmp *(r4)+ + +arvalp: + jsr r5,getsub; 0 + mov r3,r2 + add (r4)+,r2 + mov (r2),r2 + br 1f + +arval: + jsr r5,getsub; 1 + mov (r4)+,r2 +1: + add r2,r1 + mov -(r0),r2 + asr r2 + bcc 1f + movb (r1),-(sp) + jmp *(r4)+ +1: + add (r0),r1 +1: + mov -(r1),-(sp) + sob r2,1b + jmp *(r4)+ + +getsub: + tst (sp)+ + mov (r4)+,r0 + mov (r0)+,r2 + clr r1 + tst (r0)+ +1: + tst (sp)+ + dec (sp) + add (sp)+,r1 + mpy (r0)+,r1 + sob r2,1b + + tst (r5)+ + beq 2f + mov r1,-(sp) + mov -2(r4),r0 + mov (r0)+,r2 + inc r2 + mov $1,r1 +1: + mpy (r0)+,r1 + sob r2,1b +.if achk + cmp r1,(sp) + bhi 1f + jsr r5,rerr; 15. +.endif +1: + mov (sp)+,r1 + +2: + jmp (r5) + +alvalp: + jsr r5,getsub; 0 + mov r3,r0 + add (r4)+,r0 + mov (r0),-(sp) + add r1,(sp) + jmp *(r4)+ diff --git a/source/fort/rt/r8.s b/source/fort/rt/r8.s new file mode 100644 index 0000000..70b201a --- /dev/null +++ b/source/fort/rt/r8.s @@ -0,0 +1,32 @@ +/ +/ + +/ r8 - fortran runtime -- powers of integers + +.globl ipi2 + +ipi2: + tst (sp)+ + mov (sp)+,r0 + bge 1f + clr (sp) + jmp *(r4)+ +1: + mov (sp)+,r1 + mov r3,-(sp) + mov $1,r3 +1: + tst r0 + beq 1f + asr r0 + bcc 2f + mpy r1,r3 +2: + mpy r1,r1 + br 1b +1: + mov r3,r1 + mov (sp)+,r3 + mov r1,-(sp) + jmp *(r4)+ + diff --git a/source/fort/rt/r9.s b/source/fort/rt/r9.s new file mode 100644 index 0000000..fe126d3 --- /dev/null +++ b/source/fort/rt/r9.s @@ -0,0 +1,61 @@ +/ +/ + +one = 40200 +/ r9 -- fortran runtime -- real**integer + +.globl ipi4 +.globl rpi4 +.globl rpi8 + +.globl rerr + +ipi4: + setf + setl + movif 4(sp),fr0 + movf fr0,4(sp) + jsr r5,1f + movfi fr1,-(sp) + jmp *(r4)+ + +rpi4: + setf + br 2f + +rpi8: + setd +2: + jsr r5,1f + movf fr1,-(sp) + jmp *(r4)+ + +1: + cmp (sp)+,(sp)+ / jsr + msp of i4 + mov (sp)+,r0 + movf $one,fr1 + movf (sp)+,fr0 + tst r0 + bgt 1f + cfcc + beq 9f + tst r0 + beq 3f + divf fr0,fr1 + movf fr1,fr0 + neg r0 + movf $one,fr1 +1: + asr r0 + bcc 2f + mulf fr0,fr1 +2: + tst r0 + beq 3f + mulf fr0,fr0 + br 1b +3: + jmp (r5) + +9: + jsr r5, rerr; 17. diff --git a/source/fort/rt/ra.s b/source/fort/rt/ra.s new file mode 100644 index 0000000..afaa8bd --- /dev/null +++ b/source/fort/rt/ra.s @@ -0,0 +1,43 @@ +/ +/ + +/ ra -- fortran runtime -- real ** real + +.globl rpr4 +.globl rpr8 + +.globl log +.globl exp +.globl rerr + +rpr8: + setd + br 1f + +rpr4: + setf + +1: + seti + movf (sp)+,fr1 + movf (sp)+,fr0 + cfcc + beq 3f / 0**x + movf fr1,-(sp) + jsr pc,log + bes error + mulf (sp)+,fr0 + jsr pc,exp + bes error +2: + movf fr0,-(sp) + jmp *(r4)+ + +3: + tstf r1 + cfcc + bgt 2b + +error: + jsr r5,rerr; 17. + diff --git a/source/fort/rt/rb.s b/source/fort/rt/rb.s new file mode 100644 index 0000000..6b83b29 --- /dev/null +++ b/source/fort/rt/rb.s @@ -0,0 +1,49 @@ +/ +/ + +/ rb -- funct/subr stuff + +.globl call +.globl callp +.globl retrn +.globl stsp + +callp: + mov (r4)+,r0 + add r3,r0 + mov (r0),r0 + br 1f + +call: + mov (r4)+,r0 +1: + mov r3,-(sp) + mov (r4)+,r3 + mov r4,-(sp) + mov r0,r4 + mov (r4)+,-(sp) / lv of funct + jmp *(r4)+ + +retrn: + mov r3,r0 + mov (sp)+,r1 / lv of funct + mov (sp)+,r4 + mov (sp)+,r3 + mov (r0),sp + tst (r4)+ / arg count + mov (r4)+,r0 / return byte count + inc r0 + bic $1,r0 + add r0,r1 +1: + sub $2,r0 + blt 1f + mov -(r1),-(sp) + br 1b +1: + jmp *(r4)+ + +stsp: + mov sp,*(r4)+ + jmp *(r4)+ + diff --git a/source/fort/rt/rc.s b/source/fort/rt/rc.s new file mode 100644 index 0000000..abbf826 --- /dev/null +++ b/source/fort/rt/rc.s @@ -0,0 +1,320 @@ +/ +/ + +/ rc -- complex arithmetic + +.globl c8c16 +.globl c16c8 +.globl i4c8 +.globl r4c8 +.globl r8c8 +.globl i4c16 +.globl r4c16 +.globl r8c16 +.globl cad8 +.globl csb8 +.globl cmp8 +.globl cdv8 +.globl cng8 +.globl cad16 +.globl csb16 +.globl cmp16 +.globl cdv16 +.globl cng16 +.globl rval16 +.globl rval16p +.globl gas16 +.globl ceq8 +.globl cne8 +.globl ceq16 +.globl cne16 + +.globl cpi8 +.globl cpi16 + +one = 040200 +a = r2 +b = r3 +c = r4 +d = r5 + +e = r0 +f = r1 + +gas16: + mov 16.(sp),r0 + setd + movf (sp)+,a + movf (sp)+,b + tst (sp)+ + movf a,(r0)+ + movf b,(r0)+ + jmp *(r4)+ + +rval16p: + mov r3,r0 + add (r4)+,r0 + mov (r0),r0 + br 1f + +rval16: + mov (r4)+,r0 +1: + setd + movf (r0)+,a + movf (r0)+,b + movf b,-(sp) + movf a,-(sp) + jmp *(r4)+ + +cad16: + setd + br 1f + +cad8: + setf +1: + jsr pc,garg + addf a,e + addf b,f + br sarg + +csb16: + setd + br 1f + +csb8: + setf +1: + jsr pc,garg + subf a,e + negf e + subf b,f + negf f + br sarg + +cmp16: + setd + br 1f + +cmp8: + setf +1: + jsr pc,garg + mulf a,e + mulf b,f + subf f,e + mulf d,a + mulf c,b + movf a,f + addf b,f + +sarg: + movf f,-(sp) + movf e,-(sp) + jmp *(r4)+ + +cdv16: + setd + br 1f + +cdv8: + setf +1: +divide: + jsr pc,garg + absf e + absf f + cmpf e,f + cfcc + blt 1f + +/ algorithm #1 |c| > |d| + + movf d,e + divf c,e / r = d/c + movf d,f + mulf e,f + addf c,f / x = c+rd + movf f,c + movf a,f + mulf e,f + negf f + addf b,f + mulf b,e + addf a,e + divf c,e + divf c,f + br sarg + +/ algorithm #2 |c| < |d| + +1: + movf c,e + divf d,e / r = c/d + movf c,f + mulf e,f + addf d,f / x = d+rc + movf f,c + movf b,f + mulf e,f + subf a,f + mulf a,e + addf b,e + divf c,e + divf c,f + br sarg + +cng16: + setd + br 1f + +cng8: + setf +1: + movf (sp)+,a + negf a + negf (sp) + movf a,-(sp) + jmp *(r4)+ + +/ setup the following registers +/ (a,bi) +o (c,di) -> (e+fi) +/ a,b,c,d are input +/ e,f are output and also contain +/ c,d on input + +garg: + mov (sp)+,r0 + movf (sp)+,e + movf e,c + movf (sp)+,f + movf f,d + movf (sp)+,a + movf (sp)+,b + jmp (r0) + +i4c8: + setf + br 1f + +i4c16: + setd +1: + setl + movif (sp)+,fr0 + br 2f + +r4c8: + setf + br 1f + +r8c16: + setd +1: + movf (sp)+,fr0 + br 2f + +r4c16: + setd + br 1f + +r8c8: + setf +1: + movof (sp)+,fr0 +2: + clrf -(sp) + movf fr0,-(sp) + jmp *(r4)+ + +c16c8: + setd + br 1f + +c8c16: + setf +1: + movf (sp)+,r0 + movf (sp)+,r1 + movfo r1,-(sp) + movfo r0,-(sp) + jmp *(r4)+ + +ceq16: + setd + br 1f +ceq8: + setf +1: + mov $1,r1 + br 2f + +cne16: + setd + br 1f + +cne8: + setf +1: + clr r1 +2: + jsr pc,garg + cmpf c,a + cfcc + bne 1f + cmpf d,b + cfcc + beq 2f +1: + inc r1 + bic $2,r1 +2: + mov r1,-(sp) + jmp *(r4)+ + +cpi8: + setf + br 1f + +cpi16: + setd +1: + clr r0 + tst (sp)+ + mov (sp)+,r1 + bge 1f + inc r0 + neg r1 +1: + movf (sp)+,fr0 + movf fr0,fr4 + movf (sp)+,fr0 + movf fr0,fr5 + movf $one,fr0 + clrf fr1 +1: + dec r1 + bmi 1f + movf fr0,fr2 + movf fr1,fr3 + mulf fr4,fr0 + mulf fr4,fr1 + mulf fr5,fr2 + mulf fr5,fr3 + subf fr3,fr0 + addf fr2,fr1 + br 1b +1: + tst r0 + beq 1f + clrf -(sp) + movf $one,fr2 + movf fr2,-(sp) + movf fr1,-(sp) + movf fr0,-(sp) + jmp divide +1: + movf fr1,-(sp) + movf fr0,-(sp) + jmp *(r4)+ diff --git a/source/fort/rt/rd.s b/source/fort/rt/rd.s new file mode 100644 index 0000000..9ffab1c --- /dev/null +++ b/source/fort/rt/rd.s @@ -0,0 +1,38 @@ +/ +/ + +/ rd -- short list I/O do loop + +.globl slist1 +.globl slist2 +.globl slist3 + +.globl temp + +slist1: + mov (r4)+,r0 + mov (r0)+,r2 + mov $1,r1 +1: + mpy (r0)+,r1 + sob r2,1b + mov $temp,r2 + mov r1,(r2)+ + clr (r2)+ + mov (r0)+,(r2)+ + jmp *(r4)+ + +slist2: + mov (r4)+,r0 + dec temp + ble 1f + mov r0,r4 +1: + jmp *(r4)+ + +slist3: + mov $temp+2,r0 + add (r0)+,(sp) + add (r0),-(r0) + jmp *(r4)+ + diff --git a/source/fort/rt/re.s b/source/fort/rt/re.s new file mode 100644 index 0000000..e1f3731 --- /dev/null +++ b/source/fort/rt/re.s @@ -0,0 +1,57 @@ +/ +/ + +/ re -- comparison of 8-byte quantities + +.globl rle8 +.globl rlt8 +.globl req8 +.globl rne8 +.globl rge8 +.globl rgt8 +rlt8: + jsr pc,compar + blt one + br zero + +rle8: + jsr pc,compar + ble one + br zero + +req8: + jsr pc,compar + beq one + br zero + +rne8: + jsr pc,compar + bne one + br zero + +rge8: + jsr pc,compar + bge one + br zero + +rgt8: + jsr pc,compar + bgt one + br zero + +one: + mov $1,-(sp) + jmp *(r4)+ + +zero: + clr -(sp) + jmp *(r4)+ + +compar: + setd + mov (sp)+,r0 + movf (sp)+,fr0 + cmpf (sp)+,fr0 + cfcc + jmp (r0) + diff --git a/source/fort/rt/rf.s b/source/fort/rt/rf.s new file mode 100644 index 0000000..7e04bd1 --- /dev/null +++ b/source/fort/rt/rf.s @@ -0,0 +1,58 @@ +/ +/ + +/ rf -- real comparisons + +.globl rlt4 +.globl rle4 +.globl req4 +.globl rne4 +.globl rge4 +.globl rgt4 + +rlt4: + jsr pc,compar + blt one + br zero + +rle4: + jsr pc,compar + ble one + br zero + +req4: + jsr pc,compar + beq one + br zero + +rne4: + jsr pc,compar + bne one + br zero + +rge4: + jsr pc,compar + bge one + br zero + +rgt4: + jsr pc,compar + bgt one + br zero + +one: + mov $1,-(sp) + jmp *(r4)+ + +zero: + clr -(sp) + jmp *(r4)+ + +compar: + mov (sp)+,r0 + setf + movf (sp)+,r0 + cmpf (sp)+,r0 + cfcc + jmp (r0) + diff --git a/source/fort/rt/rg.s b/source/fort/rt/rg.s new file mode 100644 index 0000000..46db47d --- /dev/null +++ b/source/fort/rt/rg.s @@ -0,0 +1,87 @@ +/ +/ + +/ rg -- assignments + +.globl gmv1 +.globl gmv2 +.globl gmv4 +.globl gmv8 +.globl gmv16 +.globl stst + +gmv1: + movb (sp)+,*(r4)+ + jmp *(r4)+ + +gmv2: +stst: + mov (sp)+,*(r4)+ + jmp *(r4)+ + +gmv4: + mov (r4)+,r0 + mov (sp)+,(r0)+ + mov (sp)+,(r0)+ + jmp *(r4)+ + +gmv8: + setd + movf (sp)+,fr0 + movf fr0,*(r4)+ + jmp *(r4)+ + +gmv16: + setd + mov (r4)+,r0 + movf (sp)+,fr0 + movf fr0,(r0)+ + movf (sp)+,fr0 + movf fr0,(r0)+ + jmp *(r4)+ + +.globl gmv1p +.globl gmv2p +.globl gmv4p +.globl gmv8p +.globl gmv16p + +gmv1p: + mov (r4)+,r0 + add r3,r0 + movb (sp)+,*(r0)+ + jmp *(r4)+ + +gmv2p: + mov (r4)+,r0 + add r3,r0 + mov (sp)+,*(r0)+ + jmp *(r4)+ + +gmv4p: + mov (r4)+,r0 + add r3,r0 + mov (r0),r0 + mov (sp)+,(r0)+ + mov (sp)+,(r0)+ + jmp *(r4)+ + +gmv8p: + setd + mov (r4)+,r0 + add r3,r0 + movf (sp)+,fr0 + movf fr0,*(r0)+ + jmp *(r4)+ + +gmv16p: + setd + mov (r4)+,r0 + add r3,r0 + mov (r0),r0 + movf (sp)+,fr0 + movf fr0,(r0)+ + movf (sp)+,fr0 + movf fr0,(r0)+ + jmp *(r4)+ + diff --git a/source/fort/rt/rh.s b/source/fort/rt/rh.s new file mode 100644 index 0000000..3d886a6 --- /dev/null +++ b/source/fort/rt/rh.s @@ -0,0 +1,141 @@ +/ +/ + +/ rh -- simple array l/r values + +achk = 1 / 1 to check array bounds +.globl gal1 +.globl gal2 +.globl gal4 +.globl gal8 +.globl gal16 +.globl gar1 +.globl gar2 +.globl gar4 +.globl gar8 +.globl gar16 + +.globl rerr + +gal1: + tst (sp)+ + dec (sp) + br 1f + +gal2: + tst (sp)+ + dec (sp) + asl (sp) + br 1f + +gal4: + tst (sp)+ + dec (sp) + asl (sp) + asl (sp) + br 1f + +gal8: + tst (sp)+ + dec (sp) + asl (sp) + asl (sp) + asl (sp) + br 1f + +gal16: + tst (sp)+ + dec (sp) + asl (sp) + asl (sp) + asl (sp) + asl (sp) + +1: + cmp (sp),(r4)+ +.if achk + bhis 9f +.endif + add (r4)+,(sp) + jmp *(r4)+ + +9: + jsr r5,rerr; 15. + 4 + +gar1: + tst (sp)+ + dec (sp) + cmp (sp),(r4)+ +.if achk + bhis 9b +.endif + add (r4)+,(sp) + movb *(sp)+,r0 + mov r0,-(sp) + jmp *(r4)+ + +gar2: + tst (sp)+ + dec (sp) + asl (sp) + cmp (sp),(r4)+ +.if achk + bhis 9b +.endif + add (r4)+,(sp) + mov *(sp)+,-(sp) + jmp *(r4)+ + +gar4: + tst (sp)+ + dec (sp) + mov (sp)+,r0 + asl r0 + asl r0 + cmp r0,(r4)+ +.if achk + bhis 9b +.endif + add (r4)+,r0 + cmp (r0)+,(r0)+ + mov -(r0),-(sp) + mov -(r0),-(sp) + jmp *(r4)+ + +gar8: + setd + tst (sp)+ + dec (sp) + asl (sp) + asl (sp) + asl (sp) + cmp (sp),(r4)+ +.if achk + bhis 9b +.endif + add (r4)+,(sp) + movf *(sp)+,fr0 + movf fr0,-(sp) + jmp *(r4)+ + +gar16: + setd + tst (sp)+ + dec (sp) + mov (sp)+,r0 + asl r0 + asl r0 + asl r0 + asl r0 + cmp r0,(r4)+ +.if achk + bhis 9b +.endif + add (r4)+,r0 + movf (r0)+,fr0 + movf (r0)+,fr1 + movf fr1,-(sp) + movf fr0,-(sp) + jmp *(r4)+ + diff --git a/source/fort/rt/rx.s b/source/fort/rt/rx.s new file mode 100644 index 0000000..7312f29 --- /dev/null +++ b/source/fort/rt/rx.s @@ -0,0 +1,10 @@ +/ +/ + +/ rtx -- last routine + +.globl ecore + + .bss + +ecore: diff --git a/source/fort/rt1/abs.s b/source/fort/rt1/abs.s new file mode 100644 index 0000000..45643d2 --- /dev/null +++ b/source/fort/rt1/abs.s @@ -0,0 +1,24 @@ +/ +/ + +/ abs & dabs fortran functions + +.globl abs. +.globl dabs. + +.globl retrn +.globl temp + +dabs.: temp + .+2 + setd + br 1f + +abs.: temp + .+2 + setf +1: + movf *2(r3),r0 + absf r0 + movf r0,temp + jmp retrn diff --git a/source/fort/rt1/aimag.s b/source/fort/rt1/aimag.s new file mode 100644 index 0000000..09b43d3 --- /dev/null +++ b/source/fort/rt1/aimag.s @@ -0,0 +1,19 @@ +/ +/ + +/ aimag fortran function + +.globl aimag. + +.globl rval8p +.globl retrn +.globl temp + +aimag.: temp + rval8p; 2 + .+2 + setf + tstf (sp)+ + movf (sp)+,r0 + movf r0,temp + jmp retrn diff --git a/source/fort/rt1/aint.s b/source/fort/rt1/aint.s new file mode 100644 index 0000000..97518e9 --- /dev/null +++ b/source/fort/rt1/aint.s @@ -0,0 +1,19 @@ +/ +/ + +/ aint fortran function + +.globl aint. +.globl temp + +one = 40200 + +.globl retrn + +aint.: temp + .+2 + setf + movf *2(r3),r0 + modf $one,r0 + movf r1,temp + jmp retrn diff --git a/source/fort/rt1/alog.s b/source/fort/rt1/alog.s new file mode 100644 index 0000000..72eb211 --- /dev/null +++ b/source/fort/rt1/alog.s @@ -0,0 +1,31 @@ +/ +/ + +/ alog & log fortran functions + +.globl alog. +.globl dlog. + +.globl log +.globl retrn +.globl rerr +.globl temp + +dlog.: temp + .+2 + setd + br 1f + +alog.: temp + .+2 + setf +1: + seti + movf *2(r3),r0 + jsr pc,log + bes 1f + movf r0,temp + jmp retrn + +1: + jsr r5,rerr; 1 diff --git a/source/fort/rt1/alog10.s b/source/fort/rt1/alog10.s new file mode 100644 index 0000000..5b5fb50 --- /dev/null +++ b/source/fort/rt1/alog10.s @@ -0,0 +1,33 @@ +/ +/ + +/ alog10 & dlog10 fortran functions + +.globl dlog10. +.globl alog10. + +.globl log +.globl retrn +.globl rerr +.globl temp + +dlog10.:temp + .+2 + setd + br 1f + +alog10.:temp + .+2 + setf +1: + movf *2(r3),r0 + jsr pc,log + bes 1f + mulf const,r0 + movf r0,temp + jmp retrn + +1: + jsr r5,rerr; 1 + +const: 37736;55730;124467;24146 diff --git a/source/fort/rt1/amax0.s b/source/fort/rt1/amax0.s new file mode 100644 index 0000000..3c19876 --- /dev/null +++ b/source/fort/rt1/amax0.s @@ -0,0 +1,44 @@ +/ +/ + +/ max0 & amax0 fortran functions + +.globl amax0. +.globl max0. + +.globl retrn +.globl temp + +max0.: temp + .+2 + mov pc,r2 + br 1f + +amax0.: temp + .+2 + clr r2 +1: + setf + setl + mov *2(sp),r0 / arg count + mov r3,r1 + tst (r1)+ / argpp + movif *(r1)+,r1 + br 2f +1: + movif *(r1)+,r0 + cmpf r0,r1 + cfcc + ble 2f + movf r0,r1 +2: + dec r0 + bgt 1b + tst r2 + bne 1f + movf r1,temp + br 2f +1: + movfi r1,temp +2: + jmp retrn diff --git a/source/fort/rt1/amax1.s b/source/fort/rt1/amax1.s new file mode 100644 index 0000000..abaf405 --- /dev/null +++ b/source/fort/rt1/amax1.s @@ -0,0 +1,52 @@ +/ +/ + +/ max1, amax1 & dmax1 fortran functions + +.globl amax1. +.globl dmax1. +.globl max1. + +.globl retrn +.globl temp + +max1.: temp + .+2 + setl + setf + mov pc,r2 / integer flag + br 2f + +dmax1.: temp + .+2 + setd + br 1f + +amax1.: temp + .+2 + setf +1: + clr r2 / integer flag +2: + mov *2(sp),r0 / arg count + mov r3,r1 + tst (r1)+ / argpp + movf *(r1)+,r1 + br 2f +1: + movf *(r1)+,r0 + cmpf r0,r1 + cfcc + ble 2f + movf r0,r1 +2: + dec r0 + bgt 1b + tst r2 + bne 1f + movf r1,temp + br 2f +1: + movfi r1,temp +2: + jmp retrn diff --git a/source/fort/rt1/amin0.s b/source/fort/rt1/amin0.s new file mode 100644 index 0000000..aa02803 --- /dev/null +++ b/source/fort/rt1/amin0.s @@ -0,0 +1,44 @@ +/ +/ + +/ min0 & amin0 fortran functions + +.globl amin0. +.globl min0. + +.globl retrn +.globl temp + +min0.: temp + .+2 + mov pc,r2 + br 1f + +amin0.: temp + .+2 + clr r2 +1: + setf + setl + mov *2(sp),r0 / arg count + mov r3,r1 + tst (r1)+ / argpp + movif *(r1)+,r1 + br 2f +1: + movif *(r1)+,r0 + cmpf r0,r1 + cfcc + bge 2f + movf r0,r1 +2: + dec r0 + bgt 1b + tst r2 + bne 1f + movf r1,temp + br 2f +1: + movfi r1,temp +2: + jmp retrn diff --git a/source/fort/rt1/amin1.s b/source/fort/rt1/amin1.s new file mode 100644 index 0000000..17d2c43 --- /dev/null +++ b/source/fort/rt1/amin1.s @@ -0,0 +1,52 @@ +/ +/ + +/ min1, amin1 & dmin1 fortran functions + +.globl amin1. +.globl dmin1. +.globl min1. + +.globl retrn +.globl temp + +min1.: temp + .+2 + setl + setf + mov pc,r2 + br 2f + +dmin1.: temp + .+2 + setd + br 1f + +amin1.: temp + .+2 + setf +1: + clr r2 +2: + mov *2(sp),r0 / arg count + mov r3,r1 + tst (r1)+ / argpp + movf *(r1)+,r1 + br 2f +1: + movf *(r1)+,r0 + cmpf r0,r1 + cfcc + bge 2f + movf r0,r1 +2: + dec r0 + bgt 1b + tst r2 + bne 1f + movf r1,temp + br 2f +1: + movfi r1,temp +2: + jmp retrn diff --git a/source/fort/rt1/amod.s b/source/fort/rt1/amod.s new file mode 100644 index 0000000..938181a --- /dev/null +++ b/source/fort/rt1/amod.s @@ -0,0 +1,36 @@ +/ +/ + +/ amod & dmod fortran functions + +.globl amod. +.globl dmod. + +.globl retrn +one = 40200 +.globl temp +.globl rerr + +dmod.: temp + .+2 + setd + br 1f + +amod.: temp + .+2 + setf +1: + cmp *2(sp),$2 + bne 1f + movf *2(r3),r0 + movf r0,r2 + movf *4(r3),r1 + divf r1,r2 + modf $one,r2 + mulf r1,r3 + subf r3,r0 + movf r0,temp + jmp retrn + +1: + jsr r5,rerr; 2 diff --git a/source/fort/rt1/atan.s b/source/fort/rt1/atan.s new file mode 100644 index 0000000..56290d9 --- /dev/null +++ b/source/fort/rt1/atan.s @@ -0,0 +1,25 @@ +/ +/ + +/ atan & datan fortran functions + +.globl atan. +.globl datan. + +.globl atan +.globl retrn +.globl temp + +datan.: temp + .+2 + setd + br 1f + +atan.: temp + .+2 + setf +1: + movf *2(r3),r0 + jsr pc,atan + movf r0,temp + jmp retrn diff --git a/source/fort/rt1/atan2.s b/source/fort/rt1/atan2.s new file mode 100644 index 0000000..7197764 --- /dev/null +++ b/source/fort/rt1/atan2.s @@ -0,0 +1,31 @@ +/ +/ + +/ atan2 & datan2 fortran functions + +.globl atan2. +.globl datan2. + +.globl retrn +.globl rerr +.globl temp +.globl atan2 + +datan2.: temp + .+2 + setd + br 1f + +atan2.: temp + .+2 + setf +1: + cmp *2(sp),$2 + bne 1f + movf *2(r3),r0 + movf *4(r3),r1 + jsr pc,atan2 + movf r0,temp + jmp retrn +1: + jsr r5,rerr; 3 diff --git a/source/fort/rt1/cabs.s b/source/fort/rt1/cabs.s new file mode 100644 index 0000000..cd0ae3e --- /dev/null +++ b/source/fort/rt1/cabs.s @@ -0,0 +1,57 @@ +/ +/ + +/ cabs fortran function + +.globl cabs. +.globl dcabs. + +.globl sqrt +.globl retrn +.globl rerr +.globl temp + +dcabs.: temp + .+2 + setd + br 1f + +cabs.: temp + .+2 + setf +1: + mov 2(r3),r1 + movf (r1)+,r0 + movf (r1)+,r1 + jsr pc,hypot + bes 1f + movf r0,temp + jmp retrn +1: + jsr r5,rerr; 4 +hypot: + movf fr1,-(sp) + absf fr0 + absf fr1 + cmpf fr0,fr1 + cfcc + bne 1f + movf $one,fr0 + br 3f +1: + blt 2f + movf fr0,-(sp) + movf fr1,fr0 + movf (sp)+,fr1 +2: + divf fr1,fr0 + mulf fr0,fr0 +3: + addf $one,fr0 + jsr pc,sqrt + mulf fr1,fr0 + cfcc + movf (sp)+,fr1 + rts pc + +one = 40200 diff --git a/source/fort/rt1/ccos.f b/source/fort/rt1/ccos.f new file mode 100644 index 0000000..17e008c --- /dev/null +++ b/source/fort/rt1/ccos.f @@ -0,0 +1,13 @@ + function ccos(z1) + complex ccos, z1, z2 + dimension dummy(2) + equivalence (a,z2,dummy(1)), (b,dummy(2)) + + z2 = z1 + c = exp(b) + d = 1.0/c + b = sin(a)*(d-c)/2.0 + a = cos(a)*(c+d)/2.0 + ccos = z2 + return + end diff --git a/source/fort/rt1/cexp.s b/source/fort/rt1/cexp.s new file mode 100644 index 0000000..64db356 --- /dev/null +++ b/source/fort/rt1/cexp.s @@ -0,0 +1,35 @@ +/ +/ + +/ cexp fortran function + +.globl cexp. + +.globl rval8p +.globl retrn +.globl temp +.globl rerr +.globl exp +.globl sin +.globl cos + +cexp.: temp + rval8p; 2 + .+2 + setf + movf (sp)+,r0 + jsr pc,exp + bes 1f + movf r0,temp + movf (sp),r0 + jsr pc,sin + mulf temp,r0 + movf r0,temp+4 + movf (sp)+,r0 + jsr pc,cos + mulf temp,r0 + movf r0,temp + jmp retrn + +1: + jsr r5,rerr; 5. diff --git a/source/fort/rt1/clog.f b/source/fort/rt1/clog.f new file mode 100644 index 0000000..5055e06 --- /dev/null +++ b/source/fort/rt1/clog.f @@ -0,0 +1,12 @@ + function clog(z1) + complex clog, z1, z2 + dimension dummy(2) + equivalence (a,z2,dummy(1)), (b,dummy(2)) + + z2 = z1 + c = cabs(z2) + b = atan2(b, a) + a = alog(c) + clog = z2 + return + end diff --git a/source/fort/rt1/cmplx.s b/source/fort/rt1/cmplx.s new file mode 100644 index 0000000..17495a3 --- /dev/null +++ b/source/fort/rt1/cmplx.s @@ -0,0 +1,34 @@ +/ +/ + +/ cmplx fortran function + +.globl cmplx. +.globl dcmplx. + +.globl retrn +.globl temp +.globl rerr + +dcmplx.:temp + .+2 + setd + br 1f + +cmplx.: temp + .+2 + setf +1: + cmp *2(sp),$2 + bne 1f + mov r3,r1 + tst (r1)+ + movf *(r1)+,r0 + movf *(r1)+,r1 + mov $temp,r1 + movf r0,(r1)+ + movf r1,(r1)+ + jmp retrn + +1: + jsr r5,rerr; 6. diff --git a/source/fort/rt1/conjg.s b/source/fort/rt1/conjg.s new file mode 100644 index 0000000..728d29d --- /dev/null +++ b/source/fort/rt1/conjg.s @@ -0,0 +1,21 @@ +/ +/ + +/ conjg fortran function + +.globl conjg. + +.globl rval8p +.globl retrn +.globl temp + +conjg.: temp + rval8p; 2 + .+2 + setf + movf (sp)+,r0 + movf r0,temp + movf (sp)+,r0 + negf r0 + movf r0,temp+4 + jmp retrn diff --git a/source/fort/rt1/cos.s b/source/fort/rt1/cos.s new file mode 100644 index 0000000..4dc89a8 --- /dev/null +++ b/source/fort/rt1/cos.s @@ -0,0 +1,25 @@ +/ +/ + +/ cos & dcos fortran functions + +.globl cos. +.globl dcos. + +.globl cos +.globl retrn +.globl temp + +dcos.: temp + .+2 + setd + br 1f + +cos.: temp + .+2 + setf +1: + movf *2(r3),r0 + jsr pc,cos + movf r0,temp + jmp retrn diff --git a/source/fort/rt1/csin.f b/source/fort/rt1/csin.f new file mode 100644 index 0000000..553b6af --- /dev/null +++ b/source/fort/rt1/csin.f @@ -0,0 +1,13 @@ + function csin(z1) + complex csin, z1, z2 + dimension dummy(2) + equivalence (a,z2,dummy(1)), (b,dummy(2)) + + z2 = z1 + c = exp(b) + d = 1.0/c + b = cos(a)*(c-d)/2.0 + a = sin(a)*(c+d)/2.0 + csin = z2 + return + end diff --git a/source/fort/rt1/csqrt.f b/source/fort/rt1/csqrt.f new file mode 100644 index 0000000..bdafe28 --- /dev/null +++ b/source/fort/rt1/csqrt.f @@ -0,0 +1,14 @@ + function csqrt(z1) + complex csqrt, z1, z2 + dimension dummy(2) + equivalence (a,z2,dummy(1)), (b,dummy(2)) + + z2 = z1 + c = cabs(z2) + c = sqrt(c) + b = atan2(b, a)/2.0 + a = c*cos(b) + b = c*sin(b) + csqrt = z2 + return + end diff --git a/source/fort/rt1/dble.s b/source/fort/rt1/dble.s new file mode 100644 index 0000000..4eaa1cb --- /dev/null +++ b/source/fort/rt1/dble.s @@ -0,0 +1,20 @@ +/ +/ + +/ dble fortran function + +.globl dble. + +.globl rval4p +.globl lval +.globl r4r8 +.globl gas8 +.globl retrn +.globl temp + +dble.: temp + lval; temp + rval4p; 2 + r4r8 + gas8 + retrn diff --git a/source/fort/rt1/dccos.f b/source/fort/rt1/dccos.f new file mode 100644 index 0000000..f6e4601 --- /dev/null +++ b/source/fort/rt1/dccos.f @@ -0,0 +1,13 @@ + function dccos(z1) + double complex dccos, z1, z2 + double precision dummy(2), a, b, c, d + equivalence (a,z2,dummy(1)), (b,dummy(2)) + + z2 = z1 + c = dexp(b) + d = 1.0d0/c + b = dsin(a)*(d-c)/2.0d0 + a = dcos(a)*(c+d)/2.0d0 + dccos = z2 + return + end diff --git a/source/fort/rt1/dclog.f b/source/fort/rt1/dclog.f new file mode 100644 index 0000000..fa8be96 --- /dev/null +++ b/source/fort/rt1/dclog.f @@ -0,0 +1,13 @@ + function dclog(z1) + double complex z1, z2, dclog + double precision a,b,c + double precision dummy(2) + equivalence (a,z2,dummy(1)), (b,dummy(2)) + + z2=z1 + c=dcabs(z2) + b=datan2(b,a) + a=dlog(c) + dclog=z2 + return + end diff --git a/source/fort/rt1/dcsin.f b/source/fort/rt1/dcsin.f new file mode 100644 index 0000000..6d7e0e8 --- /dev/null +++ b/source/fort/rt1/dcsin.f @@ -0,0 +1,13 @@ + function dcsin(z1) + double complex dcsin, z1, z2 + double precision dummy(2), a, b, c, d + equivalence (a,z2,dummy(1)), (b,dummy(2)) + + z2 = z1 + c = dexp(b) + d = 1.0d0/c + b = dcos(a)*(c-d)/2.0d0 + a = dsin(a)*(c+d)/2.0d0 + dcsin = z2 + return + end diff --git a/source/fort/rt1/dcsqrt.f b/source/fort/rt1/dcsqrt.f new file mode 100644 index 0000000..580a44c --- /dev/null +++ b/source/fort/rt1/dcsqrt.f @@ -0,0 +1,14 @@ + function dcsqrt(z1) + double complex dcsqrt, z1, z2 + double precision dummy(2), a, b, c + equivalence (a,z2,dummy(1)), (b,dummy(2)) + + z2 = z1 + c = dcabs(z2) + c = dsqrt(c) + b = datan2(b, a)/2.0d0 + a = c*dcos(b) + b = c*dsin(b) + dcsqrt = z2 + return + end diff --git a/source/fort/rt1/dim.s b/source/fort/rt1/dim.s new file mode 100644 index 0000000..1e0b571 --- /dev/null +++ b/source/fort/rt1/dim.s @@ -0,0 +1,27 @@ +/ +/ + +/ dim fortran function + +.globl dim. + +.globl retrn +.globl temp +.globl rerr +/ +dim.: temp + .+2 + setf + cmp *2(sp),$2 + bne 2f + movf *2(r3),r0 + subf *4(r3),r0 + cfcc + bge 1f + clrf r0 +1: + movf r0,temp + jmp retrn + +2: + jsr r5,rerr; 7. diff --git a/source/fort/rt1/dimag.s b/source/fort/rt1/dimag.s new file mode 100644 index 0000000..e19f1ea --- /dev/null +++ b/source/fort/rt1/dimag.s @@ -0,0 +1,19 @@ +/ +/ + +/ dimag fortran function + +.globl dimag. + +.globl rval16p +.globl retrn +.globl temp + +dimag.: temp + rval16p; 2 + .+2 + setd + tstf (sp)+ + movf (sp)+,r0 + movf r0,temp + jmp retrn diff --git a/source/fort/rt1/exp.s b/source/fort/rt1/exp.s new file mode 100644 index 0000000..8b0781b --- /dev/null +++ b/source/fort/rt1/exp.s @@ -0,0 +1,31 @@ +/ +/ + +/ exp & dexp fortran functions + +.globl exp. +.globl dexp. + +.globl exp +.globl retrn +.globl rerr +.globl temp + +dexp.: temp + .+2 + setd + br 1f + +exp.: temp + .+2 + setf +1: + seti + movf *2(r3),r0 + jsr pc,exp + bes 1f + movf r0,temp + jmp retrn + +1: + jsr r5,rerr; 8. diff --git a/source/fort/rt1/float.s b/source/fort/rt1/float.s new file mode 100644 index 0000000..abcb8c5 --- /dev/null +++ b/source/fort/rt1/float.s @@ -0,0 +1,20 @@ +/ +/ + +/ float fortran function + +.globl float. + +.globl rval4p +.globl lval +.globl gas4 +.globl i4r4 +.globl retrn +.globl temp + +float.: temp + lval; temp + rval4p; 2 + i4r4 + gas4 + retrn diff --git a/source/fort/rt1/iabs.s b/source/fort/rt1/iabs.s new file mode 100644 index 0000000..966925f --- /dev/null +++ b/source/fort/rt1/iabs.s @@ -0,0 +1,18 @@ +/ +/ + +/ iabs fortran function + +.globl iabs. + +.globl retrn +.globl temp + +iabs.: temp + .+2 + setl + setd + movif *2(r3),r0 + absf r0 + movfi r0,temp + jmp retrn diff --git a/source/fort/rt1/idim.s b/source/fort/rt1/idim.s new file mode 100644 index 0000000..d7f4278 --- /dev/null +++ b/source/fort/rt1/idim.s @@ -0,0 +1,29 @@ +/ +/ + +/ idim fortran function + +.globl idim. + +.globl retrn +.globl rerr +.globl temp + +idim.: temp + .+2 + setd + setl + cmp *2(sp),$2 + bne 2f + movif *2(r3),r0 + movif *4(r3),r1 + subf r1,r0 + cfcc + bge 1f + clrf r0 +1: + movfi r0,temp + jmp retrn + +2: + jsr r5,rerr; 9. diff --git a/source/fort/rt1/idint.s b/source/fort/rt1/idint.s new file mode 100644 index 0000000..36de36a --- /dev/null +++ b/source/fort/rt1/idint.s @@ -0,0 +1,17 @@ +/ +/ + +/ idint fortran function + +.globl idint. + +.globl retrn +.globl temp + +idint.: temp + .+2 + setd + setl + movf *2(r3),r0 + movfi r0,temp + jmp retrn diff --git a/source/fort/rt1/ierr.s b/source/fort/rt1/ierr.s new file mode 100644 index 0000000..d75a2f7 --- /dev/null +++ b/source/fort/rt1/ierr.s @@ -0,0 +1,69 @@ +/ +/ + +/ catch runtime errors: +/ if (ierror(errno)) goto place +/ on call, returns 0 +/ on occurrence of error, returns non-zero + +.globl ierror. +.globl erret + +.globl rerr +.globl retrn + +ierror.:zero + .+2 + mov 2(r3),r0 + mov 2(r0),r1 + mov $errbuf,r0 +1: + cmp r0,cerrp + blo 2f + cmp cerrp,$eerbuf + blo 3f + jsr r5,rerr; 120. +3: + add $8,cerrp + br 1f +2: + cmp r1,(r0) + beq 1f + add $8,r0 + br 1b +1: + mov r1,(r0)+ + mov r3,(r0)+ + mov 2(sp),(r0)+ + mov 4(sp),(r0)+ + jmp retrn + +.data +erret: + jmp 9f +.text +9: + mov $errbuf,r0 + cmp (r0),r1 + beq 1f + add $8,r0 + cmp r0,cerrp + blo 1b + rts pc +1: + add $8,r0 + mov -(r0),-(sp) + mov -(r0),-(sp) + mov $one,-(sp) + mov -(r0),r3 + jmp retrn + +.data +one: 77777; 177777 +zero: 0; 0 + +cerrp: errbuf + +.bss +errbuf: .=.+50 +eerbuf: diff --git a/source/fort/rt1/ifix.s b/source/fort/rt1/ifix.s new file mode 100644 index 0000000..223f400 --- /dev/null +++ b/source/fort/rt1/ifix.s @@ -0,0 +1,22 @@ +/ +/ + +/ ifix & int fortran functions + +.globl ifix. +.globl int. + +.globl lval +.globl r4i4 +.globl gas4 +.globl rval4p +.globl retrn +.globl temp + +int.: +ifix.: temp + lval; temp + rval4p; 2 + r4i4 + gas4 + retrn diff --git a/source/fort/rt1/isign.s b/source/fort/rt1/isign.s new file mode 100644 index 0000000..ad46753 --- /dev/null +++ b/source/fort/rt1/isign.s @@ -0,0 +1,29 @@ +/ +/ + +/ isign fortran function + +.globl isign. + +.globl retrn +.globl rerr +.globl temp + +isign.: temp + .+2 + setd + setl + cmp *2(sp),$2 + bne 2f + movif *2(r3),r0 + absf r0 + movif *4(r3),r1 + cfcc + bge 1f + negf r0 +1: + movfi r0,temp + jmp retrn + +2: + jsr r5,rerr; 10. diff --git a/source/fort/rt1/mod.s b/source/fort/rt1/mod.s new file mode 100644 index 0000000..4797840 --- /dev/null +++ b/source/fort/rt1/mod.s @@ -0,0 +1,30 @@ +/ +/ + +/ mod fortran function + +.globl mod. + +.globl retrn +.globl temp +one = 40200 +.globl rerr + +mod.: temp + .+2 + setd + setl + cmp *2(sp),$2 + bne 1f + movif *2(r3),r0 + movf r0,r2 + movif *4(r3),r1 + divf r1,r2 + modf $one,r2 + mulf r1,r3 + subf r3,r0 + movfi r0,temp + jmp retrn + +1: + jsr r5,rerr; 11. diff --git a/source/fort/rt1/real.s b/source/fort/rt1/real.s new file mode 100644 index 0000000..cbe8dab --- /dev/null +++ b/source/fort/rt1/real.s @@ -0,0 +1,23 @@ +/ +/ + +/ real & dreal fortran function + +.globl real. +.globl dreal. + +.globl retrn +.globl temp + +dreal.: temp + .+2 + setd + br 1f + +real.: temp + .+2 + setf +1: + movf *2(r3),r0 + movf r0,temp + jmp retrn diff --git a/source/fort/rt1/sign.s b/source/fort/rt1/sign.s new file mode 100644 index 0000000..7794b9e --- /dev/null +++ b/source/fort/rt1/sign.s @@ -0,0 +1,35 @@ +/ +/ + +/ sign & dsign fortran functions + +.globl sign. +.globl dsign. + +.globl retrn +.globl temp +.globl rerr + +dsign.: temp + .+2 + setd + br 1f + +sign.: temp + .+2 + setf +1: + cmp *2(sp),$2 + bne 2f + movf *2(r3),r0 + absf r0 + tstf *4(r3) + cfcc + bge 1f + negf r0 +1: + movf r0,temp + jmp retrn + +2: + jsr r5,rerr; 12. diff --git a/source/fort/rt1/sin.s b/source/fort/rt1/sin.s new file mode 100644 index 0000000..adbcbf7 --- /dev/null +++ b/source/fort/rt1/sin.s @@ -0,0 +1,25 @@ +/ +/ + +/ sin & dsin fortran functions + +.globl sin. +.globl dsin. + +.globl sin +.globl retrn +.globl temp + +dsin.: temp + .+2 + setd + br 1f + +sin.: temp + .+2 + setf +1: + movf *2(r3),r0 + jsr pc,sin + movf r0,temp + jmp retrn diff --git a/source/fort/rt1/sngl.s b/source/fort/rt1/sngl.s new file mode 100644 index 0000000..a0d3ddf --- /dev/null +++ b/source/fort/rt1/sngl.s @@ -0,0 +1,20 @@ +/ +/ + +/ sngl fortran function + +.globl sngl. + +.globl rval8p +.globl lval +.globl r8r4 +.globl gas4 +.globl retrn +.globl temp + +sngl.: temp + lval; temp + rval8p; 2 + r8r4 + gas4 + retrn diff --git a/source/fort/rt1/sqrt.s b/source/fort/rt1/sqrt.s new file mode 100644 index 0000000..c8ea43f --- /dev/null +++ b/source/fort/rt1/sqrt.s @@ -0,0 +1,29 @@ +/ +/ + +/ sqrt & dsqrt fortran functions + +.globl sqrt. +.globl dsqrt. + +.globl sqrt +.globl retrn +.globl rerr +.globl temp + +dsqrt.: temp + .+2 + setd + br 1f + +sqrt.: temp + .+2 + setf +1: + movf *2(r3),r0 + jsr pc,sqrt + bes 1f + movf r0,temp + jmp retrn +1: + jsr r5,rerr; 13. diff --git a/source/fort/rt1/tanh.f b/source/fort/rt1/tanh.f new file mode 100644 index 0000000..a81a32c --- /dev/null +++ b/source/fort/rt1/tanh.f @@ -0,0 +1,7 @@ + function tanh(a) + + b = exp(a) + c = 1.0/b + tanh = (b-c)/(b+c) + return + end diff --git a/source/fort/rt2/ctime.s b/source/fort/rt2/ctime.s new file mode 100644 index 0000000..0e4d6fd --- /dev/null +++ b/source/fort/rt2/ctime.s @@ -0,0 +1,15 @@ +.globl ctime., retrn, temp +ctime.: temp + .+2 + sys time + clr temp + mov r0,temp+2 + setd + setl + movif temp,fr0 + mulf $44200,fr0 + mov r1,temp+2 + movif temp,fr1 + addf fr1,fr0 + movf fr0,temp + jmp retrn diff --git a/source/fort/rt2/getarg.s b/source/fort/rt2/getarg.s new file mode 100644 index 0000000..a95418f --- /dev/null +++ b/source/fort/rt2/getarg.s @@ -0,0 +1,64 @@ +/ call getarg(n, array [, nword] ) +/ +/ fill in the array with the n-th argument to the routine. +/ array is integer. +/ n counts from 1 for the file name (first) arg +/ if nword is specifies it gives the max number +/ of words to fill in +/ If no nword is given the array ends with at least one blank. +/ if nword is given the array is blank-padded to that length. + +/ iargc(dummy) returns the number of arguments +/ (1-origin) + +.globl getarg., iargc. +.globl retrn, temp +.comm argp,2 + +getarg.: + temp + .+2 + mov $512.,r2 + cmp *2(sp),$3 + blt 1f + mov 6(r3),r2 + mov 2(r2),r2 + asl r2 + asl r2 +1: + mov 4(r3),r4 + mov 2(r3),r1 + mov 2(r1),r1 + mov argp,r0 + cmp r1,(r0) + bgt 1f + asl r1 + add r0,r1 + mov (r1),r1 +2: + tst r2 + ble 1f + movb (r1)+,(r4)+ + beq 2f + dec r2 + br 2b +2: + dec r4 +1: + movb $' ,(r4)+ + dec r2 + bit $3,r2 + bne 1b + cmp r2,$256. + bge 1f + tst r2 + bgt 1b +1: + jmp retrn + +iargc.: + temp + .+2 + clr temp + mov *argp,temp+2 + jmp retrn diff --git a/source/fort/rt2/nice.s b/source/fort/rt2/nice.s new file mode 100644 index 0000000..109ce18 --- /dev/null +++ b/source/fort/rt2/nice.s @@ -0,0 +1,20 @@ +/ +/ + +/ fortran nice subroutine + +.globl nice. +.globl retrn, temp + +nice.: + temp + .+2 + mov $16.,r0 + tst *2(sp) + beq 1f + mov 2(r3),r0 + mov 2(r0),r0 +1: + sys nice + jmp retrn + diff --git a/source/fort/rt2/openrw.s b/source/fort/rt2/openrw.s new file mode 100644 index 0000000..5a4bc47 --- /dev/null +++ b/source/fort/rt2/openrw.s @@ -0,0 +1,51 @@ +/ +/ + +/ openr, openw-- +/ +/ call open(r|w) (string, iunit) +/ or, +/ call open(r|w) (argno, iunit) +/ where argno is an argument number (0 is command name) + +.globl openr. +.globl openw. + +.globl utable +.globl btable +.globl ftable +.globl getbuf +.globl fopen +.globl fcreat + +openr.: temp + .+2 + mov pc,-(sp) + br 1f + +openw.: temp + .+2 + clr -(sp) +1: + mov 4(r3),r1 + mov 2(r1),r1 + jsr r5,chkunit + tstb utable(r1) + beq 1f + jsr r5,rerr; 101. + sys exit +1: + jsr r5,getbuf + mov 2(r3),r0 + mov 2(r0),r0 + cmp r0,$32. + bhi 1f + cmp r0,*argp + bhi err + asl r0 + add argp,r0 + br 2f +1: + tst (sp)+ + beq 1f + movb $1,utable(r1) diff --git a/source/fort/rt2/plot.s b/source/fort/rt2/plot.s new file mode 100644 index 0000000..1744528 --- /dev/null +++ b/source/fort/rt2/plot.s @@ -0,0 +1,147 @@ +/ +/ + +/ move, line + +sct = 2 +/ fortran vt0 interfaces + +/ erase screen + +erase.: temp + .+2 + jsr pc,setfil + mov f,r0 + sys write; erase; 2 + jmp retrn + +/ move(x, y) +/ +/ sets current x,y to arguments +/ + +.globl move. +.globl line. +.globl erase. +.globl frame. +.globl arc. +.globl circle. + +.globl temp +.globl retrn + +frame.: temp + .+2 + jsr pc,setfil + mov 2(r3),r0 + movb 2(r0),frame+1 + mov f,r0 + sys write; frame; 2 + jmp retrn + +move.: temp + .+2 + jsr pc,garg + mov r0,x + mov r1,y + jmp retrn + +/ line(x, y) +/ +/ plot vector from current x,y +/ to arguments, setting current +/ x,y when done to arguments +/ + +line.: temp + .+2 + jsr pc,garg + mov r0,x1 + mov r1,y1 + movb $3,command + mov f,r0 + sys write; command; 9 + mov x1,x + mov y1,y + jmp retrn + +/ call circle(x, y, radius) +/ circle's center at x, y + +circle.:temp + .+2 + jsr pc,garg + mov r0,x + mov r1,y + mov 6(r3),r0 + mov 2(r0),r0 + ash $2,r0 + mov r0,x1 + movb $5,command + mov f,r0 + sys write; command; 7 + jmp retrn + +/ call arc(xo, yo, x1, y1, x2, y2) +/ plot circle arc: origin xo,yo; +/ counterclockwise from x1,y1 to x2,y2 + +arc.: temp + .+2 + jsr pc,garg + mov r0,x + mov r1,y + cmp (r3)+,(r3)+ + jsr pc,garg + mov r0,x1 + mov r1,y1 + cmp (r3)+,(r3)+ + jsr pc,garg + mov r0,x2 + mov r1,y2 + movb $6,command + mov f,r0 + sys write; command; 13. + sub $8.,r3 + jmp retrn + +setfil: + tst f + bne 1f + sys creat; vt; 17 + bes 9f + mov r0,f +1: + rts pc + +garg: + jsr pc,setfil + mov 2(r3),r0 + mov 2(r0),r0 + mov 4(r3),r1 + mov 2(r1),r1 + ash $2,r0 + ash $2,r1 + sub $2048.,r0 + sub $2048.,r1 + rts pc +9: + mov $1,r0 + sys write; bmes; emes-bmes + sys exit + +frame: .byte 4,0 +erase: .byte 1,1 + .byte 0 +vt: +bmes: ; emes: + .bss + .=.+1 +command:.=.+1 +x: .=.+2 +y: .=.+2 +x1: .=.+2 +y1: .=.+2 +x2: .=.+2 +y2: .=.+2 +f: .=.+2 diff --git a/source/fort/rt2/rand.s b/source/fort/rt2/rand.s new file mode 100644 index 0000000..cdede9d --- /dev/null +++ b/source/fort/rt2/rand.s @@ -0,0 +1,43 @@ +/ fortran random number generator. +/ either single or double prec. + +.globl rand., srand. +.globl retrn + +srand.: + value + .+2 + mov *2(r3),seed1 + inc first + jmp retrn + +rand.: + value + .+2 + tst first + bne 1f + sys time + mov r1,seed1 + inc first +1: + mov seed1,r1 + jsr pc,ran + mov r1,seed1 + seti + setd + movif r0,fr0 + divf $44000,fr0 + movf fr0,value + jmp retrn + +ran: + mpy $13077.,r1 + add $6925.,r1 + mov r1,r0 + bic $100000,r0 + rts pc + +.bss +first: .=.+2 +seed1: .=.+2 +value: .=.+8 diff --git a/source/fort/rt2/rio.s b/source/fort/rt2/rio.s new file mode 100644 index 0000000..1410891 --- /dev/null +++ b/source/fort/rt2/rio.s @@ -0,0 +1,58 @@ +/ +/ + +/ fortran random I/O + +.globl rread. +.globl rwrite. + +.globl temp +.globl retrn +.globl rerr + +rread.: temp + .+2 + mov 2(r3),r0 + mov 2(r0),0f + mov rfin,r0 + bne 1f + sys open; rf; 0 + bes 9f + mov r0,rfin +1: + sys seek; 0:..; 0 + mov 4(r3),0f + mov 6(r3),r0 + mov 2(r0),0f+2 + mov rfin,r0 + sys read; 0:..; 0 + jmp retrn + +rwrite.:temp + .+2 + mov 2(r3),r0 + mov 2(r0),0f + mov rfout,r0 + bne 1f + sys creat; rf; 17 + bes 9f + mov r0,rfout +1: + sys seek; 0:..; 0 + mov 4(r3),0f + mov 6(r3),r0 + mov 2(r0),0f+2 + mov rfout,r0 + sys write; 0:..; .. + jmp retrn + +9: + jsr r5,rerr; 456. + sys exit + +rf: + + .even +rfin: .=.+2 +rfout: .=.+2 + diff --git a/source/fort/rt2/setfil.s b/source/fort/rt2/setfil.s new file mode 100644 index 0000000..43cd888 --- /dev/null +++ b/source/fort/rt2/setfil.s @@ -0,0 +1,35 @@ +/ Fortran library-- setfil + +/ call setfil(unit, 5hname ) + +.globl setfil. + +.globl getbuf +.globl chkunit +.globl retrn +.globl utable +.globl temp +.globl rerr + +setfil.: + temp + .+2 + mov 2(r3),r1 + mov 2(r1),r1 + jsr r5,chkunit + tstb utable(r1) + beq 1f + jsr r5,rerr; 112. +1: + jsr r5,getbuf + movb $-1,utable(r1) + mov 4(r3),r0 + mov r2,r1 +1: + movb (r0)+,(r1) + beq 1f + cmpb $' ,(r1)+ + bne 1b + clrb -(r1) +1: + jmp retrn diff --git a/source/fort/rt2/uio.s b/source/fort/rt2/uio.s new file mode 100644 index 0000000..231f05c --- /dev/null +++ b/source/fort/rt2/uio.s @@ -0,0 +1,194 @@ +/ fortran to UNIX IO +/ +.globl read. +.globl write. +.globl seek. +.globl seek0. +.globl open. +.globl creat. +.globl close. +.globl errno. + +indir = 0 + +/ integer function read(f, a, n) +/ integer f, n +/ logical*1 a(n) +/ same as C + +read.: + temp + rval4p; 2 / f + i4i2 + lvalp; 4 / a + rval4p; 6 / n + i4i2 + .+2 + mov (sp)+,9f+4 + mov (sp)+,9f+2 + mov (sp)+,r0 + sys indir; 9f + br ret + +.data +9: sys read; ..; .. +.text + +/ integer function read(f, a, n) +/ integer f, n +/ logical*1 a(n) +/ same as C + +write.: + temp + rval4p; 2 / f + i4i2 + lvalp; 4 / a + rval4p; 6 / n + i4i2 + .+2 + mov (sp)+,9f+4 + mov (sp)+,9f+2 + mov (sp)+,r0 + sys indir; 9f + br ret + +.data +9: sys write; ..; .. +.text + +/ integer function seek(f, o, b) +/ integer f, o, b +/ same as C + +seek.: + temp + rval4p; 2 / f + i4i2 + rval4p; 4 / o + i4i2 + rval4p; 6 / b + i4i2 + .+2 + mov (sp)+,9f+4 + mov (sp)+,9f+2 + mov (sp)+,r0 + sys indir; 9f + br ret + +/ integer function seek0(f, n) +/ integer f, n +/ same as seek(f, n, 0) +/ but with 24 bit `n' + +seek0.: + temp + rval4p; 2 / f + i4i2 + rval4p; 4 / n + .+2 + mov (sp)+,r0 + mov (sp),r1 + bic $!777,(sp) + ashc $-9.,r0 + mov r1,9f+2 + mov $3,9f+4 + mov 2(sp),r0 + sys indir; 9f / to block + mov (sp)+,9f+2 + mov $1,9f+4 + mov (sp)+,r0 + sys indir; 9f / to byte within block + br ret + +.data +9: sys seek; ..; .. +.text + +/ integer function open(a, m) +/ logical*1 a(n) +/ integer m +/ same as C, name is ` ' terminated + +open.: + temp + lvalp; 2 / a + rval4p; 4 / m + i4i2 + .+2 + mov (sp)+,9f+4 + mov (sp)+,r0 + mov r0,9f+2 +1: + cmpb (r0)+,$' / + bne 1b + clrb -(r0) + sys indir; 9f + br ret + +.data +9: sys open; ..; .. +.text + +/ integer function creat(a, m) +/ logical*1 a(n) +/ integer m +/ same as C, name is ` ' terminated + +creat.: + temp + lvalp; 2 / a + rval4p; 4 / m + i4i2 + .+2 + mov (sp)+,9f+4 + mov (sp)+,r0 + mov r0,9f+2 +1: + cmpb (r0)+,$' / + bne 1b + clrb -(r0) + sys indir; 9f + br ret + +.data +9: sys creat; ..; .. +.text + +/ integer function close(f) +/ integer f +/ same as C + +close.: + temp + rval4p; 2 / f + i4i2 + .+2 + mov (sp)+,r0 + sys close + +ret: + bec 1f + mov r0,error + mov $-1,r0 +1: + mov r0,temp+2 + sxt temp + jmp retrn + +/ error = errno +/ returns last error number + +errno.: + temp + .+2 + mov error,r0 + br ret + +.globl temp +.globl retrn +.globl rval4p +.globl lvalp +.globl i4i2 +.bss +error: .=.+2 diff --git a/source/fort/run b/source/fort/run new file mode 100644 index 0000000..605693f --- /dev/null +++ b/source/fort/run @@ -0,0 +1,164 @@ +chdir f1 +as ../fx/fhd.s f11.s; mv a.out f11.o +as ../fx/fhd.s f12.s; mv a.out f12.o +as ../fx/fhd.s f13.s; mv a.out f13.o +as ../fx/fhd.s f14.s; mv a.out f14.o +as ../fx/fhd.s f15.s; mv a.out f15.o +as ../fx/fhd.s f16.s; mv a.out f16.o +as ../fx/fhd.s f17.s; mv a.out f17.o +ld -r *.o +mv a.out .. +rm *.o + +chdir ../f2 +as ../fx/fhd.s f21.s; mv a.out f21.o +as ../fx/fhd.s f22.s; mv a.out f22.o +as ../fx/fhd.s f23.s; mv a.out f23.o +as ../fx/fhd.s f24.s; mv a.out f24.o +ld -r ../a.out *.o +mv a.out .. +rm *.o + +chdir ../f3 +as ../fx/fhd.s f31.s; mv a.out f31.o +as ../fx/fhd.s f32.s; mv a.out f32.o +as ../fx/fhd.s f33.s; mv a.out f33.o +as ../fx/fhd.s f34.s; mv a.out f34.o +as ../fx/fhd.s f35.s; mv a.out f35.o +as ../fx/fhd.s f36.s; mv a.out f36.o +as ../fx/fhd.s f37.s; mv a.out f37.o +as ../fx/fhd.s f38.s; mv a.out f38.o +as ../fx/fhd.s f39.s; mv a.out f39.o +ld -r ../a.out *.o +mv a.out .. +rm *.o + +chdir ../f4 +as ../fx/fhd.s f41.s; mv a.out f41.o +as ../fx/fhd.s f42.s; mv a.out f42.o +as ../fx/fhd.s f43.s; mv a.out f43.o +as ../fx/fhd.s f44.s; mv a.out f44.o +as ../fx/fhd.s f45.s; mv a.out f45.o +as ../fx/fhd.s f46.s; mv a.out f46.o +as ../fx/fhd.s f47.s; mv a.out f47.o +ld -r ../a.out *.o +mv a.out .. +rm *.o + +chdir ../fx +as fhd.s fx1.s; mv a.out fx1.o +as fhd.s fx2.s; mv a.out fx2.o +as fhd.s fx3.s; mv a.out fx3.o +as fhd.s fx4.s; mv a.out fx4.o +as fhd.s fx5.s; mv a.out fx5.o +as fhd.s fx6.s; mv a.out fx6.o +as fhd.s fx7.s; mv a.out fx7.o +as fhd.s fx8.s; mv a.out fx8.o +as fhd.s fx9.s; mv a.out fx9.o +as fhd.s fxa.s; mv a.out fxa.o +as fhd.s fxb.s; mv a.out fxb.o +as fhd.s fxc.s; mv a.out fxc.o +as fhd.s fxd.s; mv a.out fxd.o +as fhd.s fxe.s; mv a.out fxe.o +as fhd.s fxf.s; mv a.out fxf.o +as fhd.s fxg.s; mv a.out fxg.o +as fhd.s fxh.s; mv a.out fxh.o +as fhd.s fxi.s; mv a.out fxi.o +as fhd.s fxx.s; mv a.out fxx.o +ld -r ../a.out *.o +mv a.out .. +rm *.o + +chdir .. +ld -s a.out -l +cmp a.out /usr/fort/fc1 +cp a.out /usr/fort/fc1 +rm a.out + +chdir io +as io?.s +mv a.out io.o +ar r /lib/filib.a io.o +rm io.o + +chdir ../rt +as r0.s +cmp a.out /lib/fr0.o +cp a.out /lib/fr0.o +as r1.s; mv a.out r1.o +as r2.s; mv a.out r2.o +as r3.s; mv a.out r3.o +as r4.s; mv a.out r4.o +as r5.s; mv a.out r5.o +as r6.s; mv a.out r6.o +as r7.s; mv a.out r7.o +as r8.s; mv a.out r8.o +as r9.s; mv a.out r9.o +as ra.s; mv a.out ra.o +as rb.s; mv a.out rb.o +as rc.s; mv a.out rc.o +as rd.s; mv a.out rd.o +as re.s; mv a.out re.o +as rf.s; mv a.out rf.o +as rg.s; mv a.out rg.o +as rh.s; mv a.out rh.o +as rx.s; mv a.out rx.o +ar r /lib/filib.a *.o +rm *.o + +chdir ../rt1 +as abs.s; mv a.out abs.o +as aimag.s; mv a.out aimag.o +as aint.s; mv a.out aint.o +as alog.s; mv a.out alog.o +as alog10.s; mv a.out alog10.o +as amax0.s; mv a.out amax0.o +as amax1.s; mv a.out amax1.o +as amin0.s; mv a.out amin0.o +as amin1.s; mv a.out amin1.o +as amod.s; mv a.out amod.o +as atan.s; mv a.out atan.o +as atan2.s; mv a.out atan2.o +as cabs.s; mv a.out cabs.o +fc -c ccos.f +as cexp.s; mv a.out cexp.o +fc -c clog.f +as cmplx.s; mv a.out cmplx.o +as conjg.s; mv a.out conjg.o +as cos.s; mv a.out cos.o +fc -c csin.f +fc -c csqrt.f +as dble.s; mv a.out dble.o +fc -c dccos.f +fc -c dclog.f +fc -c dcsin.f +fc -c dcsqrt.f +as dim.s; mv a.out dim.o +as dimag.s; mv a.out dimag.o +as exp.s; mv a.out exp.o +as float.s; mv a.out float.o +as iabs.s; mv a.out iabs.o +as idim.s; mv a.out idim.o +as idint.s; mv a.out idint.o +as ierr.s; mv a.out ierr.o +as ifix.s; mv a.out ifix.o +as isign.s; mv a.out isign.o +as mod.s; mv a.out mod.o +as real.s; mv a.out real.o +as sign.s; mv a.out sign.o +as sin.s; mv a.out sin.o +as sngl.s; mv a.out sngl.o +as sqrt.s; mv a.out sqrt.o +fc -c tanh.f +ar r /lib/libf.a *.o +rm *.o + +chdir ../rt2 +as ctime.s; mv a.out ctime.o +as getarg.s; mv a.out getarg.o +as nice.s; mv a.out nice.o +as rand.s; mv a.out rand.o +as setfil.s; mv a.out setfil.o +as uio.s; mv a.out uio.o +ar r /lib/libf.a +rm *.o diff --git a/source/fort/sum.s b/source/fort/sum.s new file mode 100644 index 0000000..bdb8bf1 --- /dev/null +++ b/source/fort/sum.s @@ -0,0 +1,44 @@ +/ example of UNIX fortran +/ calling interface to machine code +/ this example is a function that +/ returns the single precision +/ sum of all of its single precision arguments. +/ for example: +/ f = sum(1.,2.,3.) +/ sets f to 6. + +.globl sum. / defination of entry +.globl retrn / reference of return + +sum.: / entry point + value / location of return value + .+2 / pointer to execution code + setf / no d/f i/l modes guaranteed + mov *2(sp),r0 / arg count + mov r3,r1 / r3 points to arg list + tst (r1)+ / zeroth arg is old r3 + + clrf fr0 / start of actual function +1: + addf *(r1)+,fr0 / add in each argument + sob r0,1b / for each argument + + movf fr0,value / make returned value available + jmp retrn / actual return + +.bss +value: .=.+4 / space for return value + +/ synopsis: +/ 1. save registers r3, sp +/ 2. arg list (pointers to values) +/ begins at 2(r3) +/ 3. entry name is name of function +/ followed by "." +/ 4. first word after entry point is +/ location of return value. this is +/ true for both functions and subroutines +/ 5. second word after entry point is +/ pointer to pdp-11 code body +/ 6. return is expedited by a jump to +/ the globl routine "retrn" diff --git a/source/iolib/alloc.c b/source/iolib/alloc.c new file mode 100644 index 0000000..952f5a7 --- /dev/null +++ b/source/iolib/alloc.c @@ -0,0 +1,75 @@ +# +/* + * C library -- alloc/free + */ + +#define logical char * + +struct fb { + logical size; + char *next; +}; + +int freelist[] { + 0, + -1, +}; +logical slop 2; + +alloc(asize) +logical asize; +{ + register logical size; + register logical np; + register logical cp; + + if ((size = asize) == 0) + return(0); + size =+ 3; + size =& ~01; + for (;;) { + for (cp=freelist; (np= cp->next) != -1; cp=np) { + if (np->size>=size) { + if (size+slop >= np->size) { + cp->next = np->next; + return(&np->next); + } + cp = cp->next = np+size; + cp->size = np->size - size; + cp->next = np->next; + np->size = size; + return(&np->next); + } + } + asize = size<1024? 1024: size; + if ((cp = sbrk(asize)) == -1) { + return (-1); + } + cp->size = asize; + free(&cp->next); + } +} + +free(aptr) +char *aptr; +{ + register logical ptr; + register logical cp; + register logical np; + + ptr = aptr-2; + cp = freelist; + while ((np = cp->next) < ptr) + cp = np; + if (ptr+ptr->size == np) { + ptr->size =+ np->size; + ptr->next = np->next; + np = ptr; + } else + ptr->next = np; + if (cp+cp->size == ptr) { + cp->size =+ ptr->size; + cp->next = ptr->next; + } else + cp->next = ptr; +} diff --git a/source/iolib/calloc.c b/source/iolib/calloc.c new file mode 100644 index 0000000..146db61 --- /dev/null +++ b/source/iolib/calloc.c @@ -0,0 +1,4 @@ +calloc(n, s) +{ +return(alloc(n*s)); +} diff --git a/source/iolib/cclose.c b/source/iolib/cclose.c new file mode 100644 index 0000000..7d2e94d --- /dev/null +++ b/source/iolib/cclose.c @@ -0,0 +1,24 @@ +# include "ciodec.c" +cclose (fn) +int fn; +{ +struct fileps *fp; +extern char *IEH3olbf[10]; +if (fn < 0 || fn > 20) return; +fp = &IEH3fpts[fn]; +if (fp->nchars > 0 || fp->wrflag == 3) + switch (fp->wrflag) + { + case 3: seek(fn,0,2); + case 2: write (fn, fp->buff, fp->nchars); + break; + case 1: seek(fn, -(fp->nchars), 1); + } +fp -> nchars = fp->eoferr = 0; +fp -> wrflag = 0; +if ( IEH3olbf[fn] != 0 && fp->bsize >4) + free(IEH3olbf[fn]); +IEH3olbf[fn] = 0; +close (fn); +} +char *IEH3olbf[10] {0,0,0,0,0,0,0,0,0,0}; diff --git a/source/iolib/ceof.c b/source/iolib/ceof.c new file mode 100644 index 0000000..75cd006 --- /dev/null +++ b/source/iolib/ceof.c @@ -0,0 +1,20 @@ +# include "ciodec.c" +ceof (fn) +int fn; +{ +struct fileps *fp; +fp = &IEH3fpts[fn]; +if (fp->wrflag > 0 && fp->eoferr == 2) + return(1); +else return(0); +} +cerr (fn) +int fn; +{ +struct fileps *fp; +fp = &IEH3fpts[fn]; +if (fp->eoferr == 0) fp->eoferr = 1; +if (fp->wrflag > 0 && fp->eoferr == 3) + return(1); +else return(0); +} diff --git a/source/iolib/cerror.c b/source/iolib/cerror.c new file mode 100644 index 0000000..bd197ff --- /dev/null +++ b/source/iolib/cerror.c @@ -0,0 +1,10 @@ +IEH3err (message, a, b, c, d, e) +char message[]; + { + extern int cgoof; + printf("ERROR "); + printf(message, a, b, c, d, e); + cputc('\n'); + cexit(cgoof); + } +cgoof 127; diff --git a/source/iolib/cexit.c b/source/iolib/cexit.c new file mode 100644 index 0000000..dc55f19 --- /dev/null +++ b/source/iolib/cexit.c @@ -0,0 +1,8 @@ +cexit (rcode) +{ +/* closes all files and exits */ +int i; +for (i = 0; i < 10; i++) + cclose(i); +exit(rcode); /* rcode courtesy of sny */ +} diff --git a/source/iolib/cflush.c b/source/iolib/cflush.c new file mode 100644 index 0000000..8c99a10 --- /dev/null +++ b/source/iolib/cflush.c @@ -0,0 +1,19 @@ +# include "ciodec.c" +cflush (fn) +int fn; +{ +struct fileps *fp; +if (nargs() != 1) + IEHzap("cflush"); +if (fn < 0 || fn >15) return; +fp = &IEH3fpts[fn]; +if (fp->nchars > 0 && fp->wrflag >= 2) + { + write (fn, fp->buff,fp->nchars); + fp->bptr = fp->buff; + fp -> nchars = fp->eoferr = 0; + } +if (fp->wrflag == 1) + seek(fn, -(fp->nchars),1); +return; +} diff --git a/source/iolib/cfree.c b/source/iolib/cfree.c new file mode 100644 index 0000000..db08eb2 --- /dev/null +++ b/source/iolib/cfree.c @@ -0,0 +1,4 @@ +cfree (ptr) +{ +free(ptr); +} diff --git a/source/iolib/cgetc.c b/source/iolib/cgetc.c new file mode 100644 index 0000000..19b869a --- /dev/null +++ b/source/iolib/cgetc.c @@ -0,0 +1,31 @@ +# include "ciodec.c" +char cgetc(fn) +{ +struct fileps *fp; +if (nargs() != 1) + IEHzap("cgetc "); +if (fn <0 || fn >15) + IEH3err("cgetc: %d illegal file number",fn); +fp = &IEH3fpts[fn]; +if (fp == 0 || fp->wrflag > 1) + IEH3err("cgetc: %d not open to read",fn); +if (fp->wrflag == 0) + /* file not opened with fopen: try making a buffer */ + IEH3mbuf (fn, 0); +if (fp->eoferr > 1) + return ('\0'); +if (fp->nchars == 0) + switch (fp->nchars = read(fn, fp->bptr=fp->buff, fp->bsize)) + { + case -1: /* error */ + if (fp->eoferr == 0) + IEH3err("cgetc: error on %d",fn); + fp->eoferr = 3; + return ('\0'); + case 0: fp->eoferr = 2; + return ('\0'); + } +fp->nchars--; +return (*(fp->bptr++)); +} +cin 0; diff --git a/source/iolib/ciodec.c b/source/iolib/ciodec.c new file mode 100644 index 0000000..e94cf0a --- /dev/null +++ b/source/iolib/ciodec.c @@ -0,0 +1,7 @@ +struct fileps + { + char *buff, *bptr; + int nchars, bsize; + char eoferr, wrflag; + }; +extern struct fileps IEH3fpts[10]; diff --git a/source/iolib/clenf.c b/source/iolib/clenf.c new file mode 100644 index 0000000..cbc2e11 --- /dev/null +++ b/source/iolib/clenf.c @@ -0,0 +1,6 @@ +_clenf (s) /* counts length of string */ +char *s; +{ +int n; +for (n=0; *s++ != '\0'; n++); +return (n);} diff --git a/source/iolib/copen.c b/source/iolib/copen.c new file mode 100644 index 0000000..f797b0d --- /dev/null +++ b/source/iolib/copen.c @@ -0,0 +1,23 @@ +copen (filename, type) +char *filename; +int type; +{ +int fn; +switch (type) + { + case 'r': type = 0; + case 0: fn = open(filename,0); + break; + case 'a': type = 2; + case 2: if ((fn=open(filename,1))>=0) + break; /* courtesy of sny */ + /* append defaults to write if file missing */ + case 'w': type = 1; + case 1: fn = creat(filename,0666); + break; + default: IEH3err("copen: bad file %s",filename); + } +if (fn >= 0) + IEH3mbuf(fn,type); +return(fn); +} diff --git a/source/iolib/cputc.c b/source/iolib/cputc.c new file mode 100644 index 0000000..38bd2fd --- /dev/null +++ b/source/iolib/cputc.c @@ -0,0 +1,30 @@ +# include "ciodec.c" +char cputc(ch, fn) +{ +struct fileps *fp; +if (nargs() != 2) + IEHzap("cputc "); +if (fn<0 || fn>20) return(ch); +fp = &IEH3fpts[fn]; +if (fp->wrflag == 1) + IEH3err("cputc: %d not open",fn); +if (fp->wrflag == 0) + IEH3mbuf(fn,1); +*(fp->bptr++) = ch; +if (++(fp->nchars) < fp->bsize) + return(ch); +if (fp->wrflag == 3) /* append, seek to end */ + { + seek(fn, 0, 2); + fp->wrflag = 2; /* now just write from here on */ + } +if ( write(fn, fp->bptr=fp->buff, fp->nchars) < 0) + { + if (fp->eoferr == 0) + IEH3err("cputc: writing %d",fn); + fp->eoferr = 3; + } +fp->nchars = 0; +return (ch); +} +cout 1; diff --git a/source/iolib/cwrd.c b/source/iolib/cwrd.c new file mode 100644 index 0000000..d029164 --- /dev/null +++ b/source/iolib/cwrd.c @@ -0,0 +1,18 @@ +cwrite (buff, buffp1, len, fn) +char *buff, *buffp1; int len, fn; +{ +int unit, nwr; +unit = buffp1-buff; +len =* unit; +nwr = write (fn, buff, len); +return (nwr < 0 ? -1 : nwr/unit); +} +cread (buff, buffp1, len, fn) +char *buff, *buffp1; int len, fn; +{ +int unit, nrd; +unit = buffp1 - buff; +len =* unit; +nrd = read(fn, buff, len); +return (nrd < 0 ? -1 : nrd/unit); +} diff --git a/source/iolib/dummy.s b/source/iolib/dummy.s new file mode 100644 index 0000000..6b89860 --- /dev/null +++ b/source/iolib/dummy.s @@ -0,0 +1,4 @@ +.globl ndigit +.globl _ieh305i +ndigit: .=.+2 +_ieh305i: .=.+2 diff --git a/source/iolib/ftoa.c b/source/iolib/ftoa.c new file mode 100644 index 0000000..d71c51e --- /dev/null +++ b/source/iolib/ftoa.c @@ -0,0 +1,84 @@ +ftoa (x, str, prec, format) +float x; +char *str; +{ +/* converts a floating point number to an ascii string */ +/* x is stored into str, which should be at least 30 chars long */ +int ie, i, k, ndig, fstyle; +double y; +if (nargs() != 7) + IEHzap("ftoa "); +ndig = ( prec<=0) ? 7 : (prec > 22 ? 23 : prec+1); +if (format == 'f' || format == 'F') + fstyle = 1; +else + fstyle = 0; +/* print in e format unless last arg is 'f' */ +ie = 0; +/* if x negative, write minus and reverse */ +if ( x < 0) + { + *str++ = '-'; + x = -x; + } + +/* put x in range 1 <= x < 10 */ +if (x > 0.0) while (x < 1.0) + { + x =* 10.0; + ie--; + } +while (x >= 10.0) + { + x = x/10.0; + ie++; + } + +/* in f format, number of digits is related to size */ +if (fstyle) ndig =+ ie; + +/* round. x is between 1 and 10 and ndig will be printed to + right of decimal point so rounding is ... */ +for (y = i = 1; i < ndig; i++) + y = y/10.; +x =+ y/2.; +if (x >= 10.0) {x = 1.0; ie++;} /* repair rounding disasters */ +/* now loop. put out a digit (obtain by multiplying by + 10, truncating, subtracting) until enough digits out */ +/* if fstyle, and leading zeros, they go out special */ +if (fstyle && ie<0) + { + *str++ = '0'; *str++ = '.'; + if (ndig < 0) ie = ie-ndig; /* limit zeros if underflow */ + for (i = -1; i > ie; i--) + *str++ = '0'; + } +for (i=0; i < ndig; i++) + { + k = x; + *str++ = k + '0'; + if (i == (fstyle ? ie : 0)) /* where is decimal point */ + *str++ = '.'; + x =- (y=k); + x =* 10.0; + } + +/* now, in estyle, put out exponent if not zero */ +if (!fstyle && ie != 0) + { + *str++ = 'E'; + if (ie < 0) + { + ie = -ie; + *str++ = '-'; + } + for (k=100; k > ie; k =/10); + for (; k > 0; k =/10) + { + *str++ = ie/k + '0'; + ie = ie%k; + } + } +*str = '\0'; +return; +} diff --git a/source/iolib/getch.c b/source/iolib/getch.c new file mode 100644 index 0000000..f4e7071 --- /dev/null +++ b/source/iolib/getch.c @@ -0,0 +1,5 @@ +getchar() +{ +extern cin; +return (cgetc(cin)); +} diff --git a/source/iolib/gets.c b/source/iolib/gets.c new file mode 100644 index 0000000..bdeb80e --- /dev/null +++ b/source/iolib/gets.c @@ -0,0 +1,13 @@ +gets (s) +char *s; +{ /* gets (s) - read a string with cgetc and store in s */ +char *p; +extern int cin; +if (nargs () == 2) + IEHzap("gets "); +p=s; +while ((*s = cgetc(cin)) != '\n' && *s != '\0') s++; +if (*p == '\0') return (0); +*s = '\0'; +return (p); +} diff --git a/source/iolib/getvec.c b/source/iolib/getvec.c new file mode 100644 index 0000000..2ee722d --- /dev/null +++ b/source/iolib/getvec.c @@ -0,0 +1,4 @@ +getvec (n) +{ +return (alloc(n)); +} diff --git a/source/iolib/iehzap.c b/source/iolib/iehzap.c new file mode 100644 index 0000000..8aa8d20 --- /dev/null +++ b/source/iolib/iehzap.c @@ -0,0 +1,7 @@ +IEHzap(s) +{ +write(2,s,6); +write(2,": argument count wrong\n",23); +write(2,"That's all, folks\n",18); +exit(); +} diff --git a/source/iolib/makbuf.c b/source/iolib/makbuf.c new file mode 100644 index 0000000..3a233ff --- /dev/null +++ b/source/iolib/makbuf.c @@ -0,0 +1,36 @@ +# include "ciodec.c" +IEH3bsz 512; +IEH3mbuf (fn, type) +int fn, type; +{ +struct fileps *fp; +extern char *IEH3olbf[], *alloc(); +extern int IEHfbak[10]; +int bx[19], size, bloc; +fp = &IEH3fpts[fn]; +fp->eoferr = fp->nchars = 0; +fp->wrflag = type+1; +/* decide whether to buffer or not */ +if (ttyn(fn) != 'x') + size = 1; +else +if (fstat(fn,bx) > 0 && bx[0] == 40 && type == 0) + size = 1; +else + size = IEH3bsz; +for (fp->buff = 0; size >10 && fp->buff == 0; size =/ 4) + if ((bloc = alloc(size+100)) != -1) + { + IEH3olbf[fn] = bloc; + fp->buff = fp->bptr =bloc + 100; + fp->bsize = size; + break; + } +if (fp->buff == 0) + { + fp->buff = fp->bptr = &IEHfbak[fn]; + fp->bsize = size>1 ? 2 : 1; + } +} +struct fileps IEH3fpts [10]; +int IEHfbak[10]; diff --git a/source/iolib/maktab.c b/source/iolib/maktab.c new file mode 100644 index 0000000..8cc0f01 --- /dev/null +++ b/source/iolib/maktab.c @@ -0,0 +1,17 @@ +char IEH3endm[128] {0}; +IEH3mtab (formatp) +char **formatp; +{ +/* make up special table of string ending characters */ +int i, normal; +char ch; +/* normally all characters end string except those listed */ +normal = 1; +if (**formatp == '^') + {normal = 0; (*formatp)++;} +for (i= 0; i < 128; i++) + IEH3endm[i] = normal; +while ((ch = *((*formatp)++)) != ']') + IEH3endm[ch] = !IEH3endm[ch]; + +} diff --git a/source/iolib/nexch.c b/source/iolib/nexch.c new file mode 100644 index 0000000..4c52bd4 --- /dev/null +++ b/source/iolib/nexch.c @@ -0,0 +1,10 @@ +IEH3nxch () +/* returns next character which is not IEH3spce */ +{ + char ch, cgetc(); + extern int IEH3sfil; +while ((ch = cgetc(IEH3sfil)) > 0 && IEH3spce(ch)); +if (ch > 0) + return (ch); +return (-1); +} diff --git a/source/iolib/nodig.c b/source/iolib/nodig.c new file mode 100644 index 0000000..bb4b3ff --- /dev/null +++ b/source/iolib/nodig.c @@ -0,0 +1,13 @@ +IEH3nodg (ch) +char ch; +{ +if (IEH3digt(ch)) return (0); +switch (ch) + { + case 'E': + case 'e': + case '.': case '+': case '-': + return (0); + } +return (1); +} diff --git a/source/iolib/printf.c b/source/iolib/printf.c new file mode 100644 index 0000000..af33a40 --- /dev/null +++ b/source/iolib/printf.c @@ -0,0 +1,130 @@ +char *_ptrbf, *_ptrst, *__fmt; +printf(a1,a2,a3,a4){ +auto char c, *s, adj, *ptr,*p, buf[30]; +extern cputc(),_putstr(), cout; +auto int *adx, x, n, m, width, prec,i, padchar, fd; +double zz, *dblptr; +char (*f)(); +_ptrbf = buf; + +fd=cout; +adx = &a1; +f = cputc; +if (a1 == -1) + { + f = _putstr; + _ptrst = a2; + adx =+ 2; + } +else if (a1 >= 0 && a1 <= 9) + fd = *adx++; +__fmt = *adx++; + + +while( c = *__fmt++ ){ + if(c != '%') (*f)(c,fd); + else { x = *adx++; + if( *__fmt == '-' ){ adj = 'l'; __fmt++; } + else adj = 'r'; + padchar = (*__fmt=='0') ? '0' : ' '; + width = __conv(); + if( *__fmt == '.'){++__fmt; prec = __conv();} + else prec = 0; + + s = 0; + switch ( c = *__fmt++ ) { + case 'D': + case 'd': + _prt1(x); break; + case 'o': + case 'O': + _prnt8(x); break; + case 'x': + case 'X': + _prntx(x); break; + case 'S': + case 's': s=x; + break; + case 'C': + case 'c': *_ptrbf++ = x&0777; + break; + case 'E': + case 'e': + case 'F': + case 'f': + dblptr = adx-1; + zz = *dblptr; + adx =+ 3; + ftoa (zz, buf, prec, c); + prec = 0; + s = buf; + break; + default: (*f)(c,fd); + adx--; + } + if (s == 0) + {*_ptrbf = '\0'; s = buf;} + n = _clenf (s); + n = (prec 0) (*f)(padchar,fd); + while (n--) (*f)(*s++,fd); + while (m-- > 0) (*f)(padchar,fd); + _ptrbf = buf; + } +} +if(a1 == -1) (*f)('\0',fd); +} + + +_prnt8 (n) +{ /* print in octal */ +int p, k, sw; +if (n==0) {*_ptrbf++ = '0'; return;} +sw = 0; +for (p=15; p >= 0; p =- 3) + if ((k = (n>>p)&07) || sw) + { + *_ptrbf++ = '0' + k; + sw = 1; + } +} +_prntx (n) +{ + int d,a; + if (a = n>>4) + _prntx ( a & 07777); + d = n&017; + *_ptrbf++ = d > 9 ? 'A'+d-10 : '0' + d; +} + +__conv() +{ +auto c,n; +n = 0; +while( ((c = *__fmt++) >= '0') && (c<='9')) n = n*10+c-'0'; +__fmt--; +return(n); +} + +_putstr(chr,str){ +*_ptrst++ = chr; +return; ieh305i(); /* force loading of dummy.s */ +} +_prt1(n) +{ +int digs[15], *dpt; +dpt = digs; +if (n >= 0) + n = -n; +else + *_ptrbf++ = '-'; +for (; n != 0; n = n/10) + *dpt++ = n%10; +if (dpt == digs) + *dpt++ = 0; +while (dpt != digs) + { --dpt; + *_ptrbf++ = '0' - *dpt; +} +} diff --git a/source/iolib/putch.c b/source/iolib/putch.c new file mode 100644 index 0000000..fd438fb --- /dev/null +++ b/source/iolib/putch.c @@ -0,0 +1,6 @@ +putchar (c) +char c; +{ +extern cout; +cputc(c,cout); +} diff --git a/source/iolib/puts.c b/source/iolib/puts.c new file mode 100644 index 0000000..ac0f1b0 --- /dev/null +++ b/source/iolib/puts.c @@ -0,0 +1,13 @@ +puts(str) +char *str; +{ +auto char *p,c; +auto int f; +extern int cout; +if (nargs() != 1) + IEHzap("puts "); +p = str; +while( (c = *p++)!= '\0') cputc(c,cout); +cputc('\n',cout); +return(str); +} diff --git a/source/iolib/relvec.c b/source/iolib/relvec.c new file mode 100644 index 0000000..4fedb5e --- /dev/null +++ b/source/iolib/relvec.c @@ -0,0 +1,4 @@ +relvec (ptr) +{ +free(ptr); +} diff --git a/source/iolib/revput.c b/source/iolib/revput.c new file mode 100644 index 0000000..b305464 --- /dev/null +++ b/source/iolib/revput.c @@ -0,0 +1,10 @@ +# define bufflen 100 +IEH3revp (c) +char c; +{ +/* reversed line IEH3outputter */ +extern char *IEH3outp, *IEH3outlim; +*IEH3outp++ = c; +if (IEH3outp > IEH3outlim+100) + IEH3err("unprint producing too many chars"); +} diff --git a/source/iolib/run b/source/iolib/run new file mode 100644 index 0000000..81c2ba3 --- /dev/null +++ b/source/iolib/run @@ -0,0 +1,39 @@ +cc -c -O alloc.c +cc -c -O calloc.c +cc -c -O cclose.c +cc -c -O ceof.c +cc -c -O cerror.c +cc -c -O cexit.c +cc -c -O cflush.c +cc -c -O cfree.c +cc -c -O cgetc.c +cc -c -O ciodec.c +cc -c -O clenf.c +cc -c -O copen.c +cc -c -O cputc.c +cc -c -O cwrd.c +as dummy.s; mv a.out dummy.o +cc -c -f -O ftoa.c +cc -c -O getch.c +cc -c -O gets.c +cc -c -O getvec.c +cc -c -O iehzap.c +cc -c -O makbuf.c +cc -c -O maktab.c +cc -c -O nexch.c +cc -c -O nodig.c +cc -c -O printf.c +cc -c -O putch.c +cc -c -O puts.c +cc -c -O relvec.c +cc -c -O revput.c +cc -c -O scan1.c +cc -c -O scan2.c +cc -c -O scan3.c +cc -c -O system.c +cc -c -O tmpnam.c +cc -c -O unget.c +as unprnt.s; mv a.out unprnt.o +cc -c -O wdleng.c +ar r /lib/libp.a *.o +rm *.o diff --git a/source/iolib/scan1.c b/source/iolib/scan1.c new file mode 100644 index 0000000..ba87e99 --- /dev/null +++ b/source/iolib/scan1.c @@ -0,0 +1,149 @@ +scanf (p1, p2, p3, p4) + int p1, p2, p3, p4; +{ +/* first arg can be a control string, a file id, or -1 */ + int ptrs[10], j, ip, flp, k; + char *np; +/* extern int cin;*/ +extern (*_Igetc)(), (*_Iungc)(), cgetc(), ungetc(), _Igstr(), _Iungs(); +extern char *_Iinpt; +ip = 0; +if (p1 == -1) + {k = 1; _Iinpt = p2;} +else if (p1 >= 0 && p1 < 10) + k = 0; +else + k = -1; +if (k <= 0) + {_Igetc = cgetc; _Iungc = ungetc;} +else + {_Igetc = _Igstr; _Iungc = _Iungs;} +j = 0; +for (np = (&p2)[k]; *np; np++) + if (*np == '%' && *(np+1) != '%' && *(np+1) != '*') + ptrs[ip++] = (&p3)[(j++)+k]; +return (_Iscan ((k==0 ? p1 : 0), (&p2)[k], ptrs)); +} + +_Iscan (fileid, format, listp) + char *format; + int *listp; +{ + char ch, _Inxch(); + int nmatch; + extern int _Isfil; + _Isfil = fileid; +nmatch = 0; +while (1) switch (ch= *format++) + { + case '\0': return (nmatch); + case '%': switch (_Isfrm(&format, *listp++)) + { + case 0: listp--; break; + case -1: return (nmatch > 0 ? nmatch : -1); + default: nmatch++; + } + case ' ': + case '\n': + case '\t': break; + default: if (ch != _Inxch()) + return(nmatch); + } +} + +int _Isfil 0; + +_Ichar (cptr) + char *cptr; +{ + char ch, _Inxch(); + +if ((ch = _Inxch()) < 0) + return (-1); +if (cptr == 0) + return (0); +*cptr = ch; +return (1); +} + +_Iflot (fptr, length) + float *fptr; + int length; +{ + char temp[75]; + int _Inodg(); + float x; + double atof(); + +if (_Isstr(temp, length, _Inodg) < 0) + return (-1); +x = atof(temp); +if (fptr == 0) + return (0); +*fptr = x; +return (1); +} + +_Inodg (ch) +char ch; +{ +if (_Idigt(ch,10) >= 0) return (0); +switch (ch) + { + case 'E': + case 'e': + case '.': case '+': case '-': + return (0); + } +return (1); +} + +_Isfrm (spec, pointer) + char **spec; + int pointer; +{ + int length, lflag, _Iestr(), _Ispnd(); + char ch; +length = lflag = 0; +while (1) switch (ch = *((*spec)++)) + { + case '*': pointer=0; break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + length = length*10 + ch - '0' ; + lflag++; + break; + case 'o': /* octal */ + return(_Iint(pointer, lflag ? length : 100, 8)); + case 'x': /* hex */ + return(_Iint(pointer, lflag ? length : 100, 16)); + case 'd': /* decimal */ + return (_Iint(pointer, lflag ? length : 100, 10)); + case 'c': /* character */ + return (_Ichar(pointer)); + case 's': /* string */ + return (_Isstr(pointer, lflag ? length : 100, _Iestr)); + case 'f': + case 'e': /* float */ + return (_Iflot(pointer, lflag ? length : 100)); + case 'l': /* (long) double or int */ + switch(*(*spec)++) + { + case 'f': case 'F': + case 'e': case 'E': + return (_Ilong (pointer, lflag ? length : 100)); + default: printf(2, "long not yet implemented\n"); + return(0); + } + case '[': /* special strings */ + _Imtab(spec); + return (_Isstr (pointer, lflag ? length : 100, _Ispnd)); + case '%': + if (_Inxch() != '%') + return (-1); + return(0); + case '\0': + _Ierr("scanf: bad format termination\n"); + default: _Ierr ("scanf: format character %c", ch); + } +} diff --git a/source/iolib/scan2.c b/source/iolib/scan2.c new file mode 100644 index 0000000..730722a --- /dev/null +++ b/source/iolib/scan2.c @@ -0,0 +1,111 @@ +_Iint (iptr, length, numbase) + int *iptr, length; +{ + int n, minus, numdig; + extern int _Isfil, (*_Iungc)(), (*_Igetc)(); + int c, dval; + +n = minus = numdig = 0; +switch ((c=_Inxch())) + { + case '-': minus = 1; + case '+': break; + default: (*_Iungc)(c,_Isfil); + } +while ((dval=_Idigt(c=((*_Igetc)(_Isfil)), numbase ) ) >= 0 && numdig++ < length) + n = n*numbase + dval; +(*_Iungc)(c,_Isfil); +if (numdig == 0) + return (-1); +if (iptr == 0) + return (0); +*iptr = minus ? -n : n; +return (1); +} + +_Idigt (x, base) +{ +switch (x) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + return(x-'0'); + case '8': + case '9': + if (base > 8) + return(x - '0'); + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + if (base >10) + return(x - 'a' + 10); + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + if (base > 10) + return(x-'A' + 10); + } +return(-1); +} + +_Ilong (dptr, length) + double *dptr; + int length; +{ + char temp[75]; + int _Inodg(); + double x; + double atof(); + +if (_Isstr(temp, length, _Inodg) < 0) + return (-1); +x = atof(temp); +if (dptr == 0) + return (0); +*dptr = x; +return (1); +} + +_Isstr (sptr, length, stopf) + char *sptr; + int length, (*stopf)(); +{ + int ch, initlen, _Inxch(); + extern int _Isfil, (*_Igetc)(), (*_Iungc)(); + +initlen = length; +if ((ch=_Inxch()) < 0) + return (-1); +(*_Iungc)(ch,_Isfil); +while (!((*stopf)(ch=(*_Igetc)(_Isfil))) && length-- > 0) + if (sptr != 0) + *(sptr++) = ch; +if (ch >= 0) + (*_Iungc)(ch,_Isfil); +if (length == initlen) + return (-1); +if (sptr == 0) + return (0); +*sptr = '\0'; +return (1); +} + +_Iestr (c) +char c; +{ +if (_Ispce(c)) return (1); +if (c == '\0') return (1); +return (0); +} diff --git a/source/iolib/scan3.c b/source/iolib/scan3.c new file mode 100644 index 0000000..4a6a11c --- /dev/null +++ b/source/iolib/scan3.c @@ -0,0 +1,69 @@ +_Ierr (message, a, b, c, d, e) +char message[]; + { + extern int cgoof; + printf("ERROR "); + printf(message, a, b, c, d, e); + cputc('\n'); + cexit(cgoof); + } +char _Iendm[128] {0}; +_Imtab (formatp) +char **formatp; +{ +/* make up special table of string ending characters */ +int i, normal; +char ch; +/* normally all characters end string except those listed */ +normal = 1; +if (**formatp == '^') + {normal = 0; (*formatp)++;} +for (i= 0; i < 128; i++) + _Iendm[i] = normal; +while ((ch = *((*formatp)++)) != ']') + _Iendm[ch] = !_Iendm[ch]; + +} + +_Inxch () +/* returns next character which is not _Ispce */ +{ + extern int _Isfil, (*_Igetc)(); + int ch; +while ((ch = (*_Igetc)(_Isfil)) > 0 && _Ispce(ch)); +if (ch > 0) + return (ch); +return (-1); +} + +_Ispce (c) +char c; +{ +switch (c) + { + case ' ': + case '\n': + case '\t': return(1); + } +return(0); +} + +_Ispnd (ch) +char ch; +{ +return (_Iendm[ch] > 0); +} + +char *_Iinpt; +int (*_Igetc)(), (*_Iungc)(); +_Igstr () +{ +extern char *_Iinpt; +return (*_Iinpt++); +} + +_Iungs(ch) +{ +extern char *_Iinpt; +*--_Iinpt = ch; +} diff --git a/source/iolib/system.c b/source/iolib/system.c new file mode 100644 index 0000000..2f5caa0 --- /dev/null +++ b/source/iolib/system.c @@ -0,0 +1,8 @@ +system(str) + char *str; +{ +int status; + if(fork() == 0) + execl("/bin/sh", "sh", "-c", str, 0); + wait(&status); + } diff --git a/source/iolib/tmpnam.c b/source/iolib/tmpnam.c new file mode 100644 index 0000000..f82f2be --- /dev/null +++ b/source/iolib/tmpnam.c @@ -0,0 +1,7 @@ +int IEH0958g 0; +tmpnam(s) + char *s; +{ +printf(-1,s,"pl%d%c",getpid(),'a'+IEH0958g++); +return(s); +} diff --git a/source/iolib/unget.c b/source/iolib/unget.c new file mode 100644 index 0000000..abab7cc --- /dev/null +++ b/source/iolib/unget.c @@ -0,0 +1,15 @@ +# include "ciodec.c" +ungetc (c, fn) +{ +struct fileps *fp; +if (nargs() != 2) + IEHzap("ungetc"); +/* push back onto input */ +fp = &IEH3fpts[fn]; +if (fp->wrflag == 0) + IEH3mbuf(fn,0); +if (fp->bptr <= fp->buff - 100) + IEH3err("ungetc/unprintf: buffer full file %d",fn); +*--fp->bptr = c; +fp->nchars++; +} diff --git a/source/iolib/unprnt.s b/source/iolib/unprnt.s new file mode 100644 index 0000000..a9f681f --- /dev/null +++ b/source/iolib/unprnt.s @@ -0,0 +1,210 @@ +/ C library -- unprintf + + +.globl _unprintf +.globl ndigix + +.globl pfloat +.globl pscien +.globl _IEH3revp +.globl _IEH3bcko + +_unprintf: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),formp / format + mov r5,r4 + add $6,r4 / arglist + sub $128.,sp / buffer +loop: + movb *formp,r0 + beq 1f + inc formp + cmp r0,$'% + beq 2f +3: + mov r4,-(sp) + mov r0,-(sp) + jsr pc,*$_IEH3revp + tst (sp)+ + mov (sp)+,r4 + br loop +1: + add $128.,sp + mov (sp)+,r5 + jsr pc,_IEH3bcko + rts pc +2: + clr rjust + clr ndigix + cmpb *formp,$'- + bne 2f + inc formp + inc rjust +2: + jsr r3,gnum; width + clr ndfnd + cmp r0,$'. + bne 1f + jsr r3,gnum; ndigix +1: + mov sp,r3 + mov $swtab,r1 +1: + mov (r1)+,r2 + beq 3b + cmp r0,(r1)+ + bne 1b + jmp (r2) +swtab: + decimal; 'd + octal; 'o + float; 'f + scien; 'e + charac; 'c + string; 's + logical; 'l + 0; 0 + +decimal: + mov (r4)+,r1 + bge 1f + neg r1 + movb $'-,(r3)+ + br 1f + +logical: + mov (r4)+,r1 +1: + jsr pc,1f + br prbuf +1: + clr r0 + div $10.,r0 + mov r1,-(sp) + mov r0,r1 + beq 1f + jsr pc,1b +1: + mov (sp)+,r0 + add $'0,r0 + movb r0,(r3)+ + rts pc + +charac: + movb (r4)+,(r3)+ + bne 1f + dec r3 +1: + movb (r4)+,(r3)+ + br prbuf + +string: + mov ndigix,r1 +1: + mov (r4)+,r2 +1: + movb (r2)+,(r3)+ + beq prbuf + sob r1,1b + br prbuf + +octal: + mov (r4)+,r1 + jsr pc,1f + br prbuf +1: + mov r1,-(sp) + beq 1f + ash $-3,r1 + bic $!17777,r1 + jsr pc,1b +1: + mov (sp)+,r0 + bic $!7,r0 + add $'0,r0 + movb r0,(r3)+ + rts pc + +float: + mov ndfnd,r2 + jsr pc,pfloat + br prbuf + +scien: + mov ndfnd,r2 + jsr pc,pscien + br prbuf + +prbuf: + cmp r3,sp + blos 1f + tstb -1(r3) + bne 1f + dec r3 + br prbuf +1: + mov sp,r2 + mov r4,-(sp) + mov $' ,-(sp) + mov width,r1 + sub r3,r1 + clrb (r3)+ + add r2,r1 + mov r1,spaces + ble 1f + tst rjust + bne 1f +2: + jsr pc,*$_IEH3revp + dec spaces + bne 2b +1: + mov r2,bufp +1: + movb *bufp,(sp) + beq 1f + inc bufp + jsr pc,*$_IEH3revp + br 1b +1: + tst spaces + ble 1f + tst rjust + beq 1f + mov $' ,(sp) +2: + jsr pc,*$_IEH3revp + dec spaces + bne 2b +1: + tst (sp)+ + mov (sp)+,r4 + jmp loop + +gnum: + clr ndfnd + clr r1 +1: + movb *formp,r0 + inc formp + sub $'0,r0 + cmp r0,$9. + bhi 1f + inc ndfnd + mul $10.,r1 + add r0,r1 + br 1b +1: + add $'0,r0 + mov r1,*(r3)+ + rts r3 + + .bss +ndigix: .=.+2 +width: .=.+2 +formp: .=.+2 +rjust: .=.+2 +ndfnd: .=.+2 +bufp: .=.+2 +spaces: .=.+2 diff --git a/source/iolib/wdleng.c b/source/iolib/wdleng.c new file mode 100644 index 0000000..4ce517b --- /dev/null +++ b/source/iolib/wdleng.c @@ -0,0 +1,10 @@ +wdleng () +/* returns number of bits in a machine integer */ +/* written so kernighan can tell where he is running */ +{ +int k, leng; +k = leng = 1; +while (k =<< 1) + leng++; +return (leng); +} diff --git a/source/m6/m6.h b/source/m6/m6.h new file mode 100644 index 0000000..9804ee6 --- /dev/null +++ b/source/m6/m6.h @@ -0,0 +1,66 @@ + +struct { + int word; +}; + +struct { /*"put stack", currently gathering args*/ + int prev; /*previous frame ptr, self-relative*/ + int pan; /*argument number of arg being collected*/ + int pa0; /*self-relative ptr oo arg0*/ +#define pend 6 +}; + +struct { /*"get stack", currently expanding macros*/ + int prev; /* prev frame ptr, self-realtive*/ + int mframe; /* ptr to macro definition frame*/ + int mchar; /* next char relative to def. frame*/ + int marg; /* 0 or ptr to next arg char reltive to gf*/ + int ga0; /* arg0 ptr self-rel*/ +}; + +struct { /*"definition stack"*/ + int prev; /* prev frame ptr, self-relative*/ + int dswitch; /* builtin func code, neg for dead definition*/ + int dtext; /* definition text prt rel to df*/ + int dident; /* first char of identifier naming def*/ +#define dend 6 +}; + +char metas[]; +#define lquote metas[0] +#define rquote metas[1] +#define sharp metas[2] +#define colon metas[3] +#define semi metas[4] +#define comma metas[5] +#define dollar metas[6] +#define NMETA 7 + +char one[]; +int rescan; +int traceflag; +int trashflag; /* nonzero when dead def'n exist*/ + +int lp; /* arg collection level (out level)*/ +int lg; /*input level (get level) */ +int lq; /*quote level*/ +int l9; /*apparent call level within arg 9*/ + +char c; /*current input character*/ + +char *pf; /*put stack frame ptr*/ +char *pe; /*put stack end*/ +char *pmax; /*top of put stack*/ +char p0[]; /*put stack*/ + +char *gf; /*get stack frame ptr*/ +char *ge; /*get stack end*/ +char *gmax; /*get stack limit*/ +char g0[]; /*get stack*/ + +char *df; /*definition stack frame ptr*/ +char *de; /*def stack end*/ +char *dmax; /*def stack limit*/ +char d0[]; /*def stack*/ + +char dummy[]; /*dummy empty macro*/ diff --git a/source/m6/m61.c b/source/m6/m61.c new file mode 100644 index 0000000..fa0b0dd --- /dev/null +++ b/source/m6/m61.c @@ -0,0 +1,35 @@ +# + +#include "m6.h" + +main(argc,argv) +char **argv; +{ + extern fin; + int t; + gf = ge = g0; + pf = pe = p0; + t = g0; + gmax =+ t-10; + t = d0; + dmax =+ t-10; + t = p0; + pmax =+ t-10; + revptr(d0,d0+2,&df,&de); + if(argc>1) { + fin = open(argv[1],0); + control(); + close(fin); + } + fin = dup(0); + control(); +} + + +diag(m) { + printf("%s\n",m); + iot(); +} /* abort */ + +int iot 4; + diff --git a/source/m6/m62.c b/source/m6/m62.c new file mode 100644 index 0000000..f6e3f8d --- /dev/null +++ b/source/m6/m62.c @@ -0,0 +1,90 @@ +# + +#include "m6.h" + +control() { + + while(1) { + get(); + if(c==0 && lg>0) { + popget(); + trash(); + rescan = 1; + } + else { + if(!rescan) put(); + else if(lq>0) { + if(c==lquote) { + lq++; + put(); + } + else if(c==rquote || c==0) { + lq--; + if(lq>0 || l9>0) put (rquote); + } + else put(); + } + else if(l9>0) + if(c==colon||c==0||c==semi) + if(--l9<=0) endcall(); + else put(); + else { + if(c==sharp) l9++; + else if(c==lquote) lq++; + put(); + } + else { + if(c==sharp) begincall(); + else if(c==lquote) lq++; + else if(lp>0) { + if(c==colon||c==0||c==semi) endcall(); + else if(c==comma) newarg(); + else put(); + } + else if(c==0) return; /* lg=lp=lq=0 */ + else put(); + } + } + } +} + +endcall() { + char *pt, *p; + rescan = c!=semi; + newarg(); + pushget(); + pt = &pf->pa0; + ge = move(pt,&gf->ga0,pe-pt); + if(ge>gmax) diag("Call stack overflow"); + if(traceflag) dotrace(); + p = finddef(0); + setscan(p); + popput(); + lp--; + function(p->dswitch); +} + +begincall() { + lp++; + pushput(); + pe = pf+pend; + pf->pan = pf->pa0 = 0; +} + +newarg() { + char *p; + if(++pf->pan>=9) if(c==comma) l9++; + *pe++ = 0; + pe = (pe+1)&0177776; + p = &pf->pa0; + while(p->word!=0) p =+ p->word; + p->word = pe - p; + *pe++ = *pe++ = 0; +} + +setscan(p) +char *p; +{ + gf->mchar = (gf->mframe = p)->dtext; + gf->marg = 0; +} diff --git a/source/m6/m63.c b/source/m6/m63.c new file mode 100644 index 0000000..479f7ad --- /dev/null +++ b/source/m6/m63.c @@ -0,0 +1,85 @@ +# + +#include "m6.h" + +char * +finddef(n) { + char *p; + if((p = lookup(arg(n)))==0) + if((p = lookup(""))==0) diag("Software error"); + return(p); +} + +char * +lookup(s) { + char *dt; + dt = df; + while(dt>d0) { + if(dt->dswitch>=0 && comp(s,&dt->dident)) return(dt); + dt =+ dt->prev; + } + return(0); +} + +comp(s,t) +char *s, *t; +{ + for(;*s++ == *t;t++) + if(*t==0) return(1); + return(0); +} + +remove(n) { + char *p; + if(p = lookup(arg(n))) if(p>d0+2) { + trashflag++; + p->dswitch = -1; + } +} + +trash() { + char *p,*q,*r; + if(lg>0) return; + while(df->dswitch<0) { + de = df; + df =+ df->prev; + trashflag--; + } + if(trashflag<=0) return; + de = (de+1)&0177776; + revptr(de,df,&p,&q); + q = p; + for(;p->word!=0;p=+r->word) { + r = p; + if(p->dswitch>=0) { + r = q; + q = move(p,q,p->word); + } + } + q->word = 0; + revptr(d0,d0+2,&df,&de); +} + + +revptr(p,q,np,nq) +char *p, *q, **np, **nq; +{ + int t; + p->word = 0; + while((t = q->word)!=0) { + q->word = p-q; + p = q; + q =+ t; + if(qdmax) diag("Software error"); + } + *np = p; + *nq = q; +} + +char * +move(from,to,count) +char *from, *to; +{ + while(count-->0) *to++ = *from++; + return(to); +} diff --git a/source/m6/m64.c b/source/m6/m64.c new file mode 100644 index 0000000..db4bedc --- /dev/null +++ b/source/m6/m64.c @@ -0,0 +1,82 @@ +# + +#include "m6.h" + +pushget() { + ge = (ge+1)&0177776; + ge->word = gf-ge; + gf = ge; + ge =+2; + ++lg; +} + +dotrace() { + char *arg(); + int i,j; + printf("\n%d %c%s",lg,sharp,arg(0)); + for(j=9;j>0&&*arg(j)==0;j--); + for(i=1;i<=j;i++) + printf("%c%c%s%c",comma,lquote,arg(i),rquote); + printf("%c\n",c); +} + +popget() { + ge = gf; + gf =+ gf->word; + --lg; + if(gfprev =| 1; + pe++; + } + pe->word = pf-pe; + pf = pe; + pe =+2; +} + +popput() { + pe = pf; + pf =+ pf->word; + if(pf->prev&1) { + pe--; + pf->prev =& 0177776; + } + if(pfword = df-de; + df = de; + de =+2; +} + +put() { + if(lp>0) { + *pe++ = c; + if(pe>pmax) diag("Arg collection overflow"); + } + else putchar(c); +} + +get() { + char *p; + int n; + if(lg==0) + c = getchar(); + else while(1) { + if(gf->marg!=0) { + if((c = gf[gf->marg++])==0) gf->marg = 0; + else return; + } + c = (p = gf->mframe)[gf->mchar++]; + if(c!=dollar) return; + n = p[gf->mchar] - '0'; + if(n<0 || n>9) return; + ++gf->mchar; + gf->marg = arg(n) - gf; + } +} diff --git a/source/m6/m65.c b/source/m6/m65.c new file mode 100644 index 0000000..0ec7039 --- /dev/null +++ b/source/m6/m65.c @@ -0,0 +1,85 @@ +# + +#include "m6.h" + +define() { + remove(1); + newdef(decbin(3)); + setdef(arg(1),arg(2)); +} + +newdef(n) { + pushdef(); + de = &df[df->dtext = dend]; + if((df->dswitch = n)<0) trashflag++; +} + +setdef(s1,s2) { + copydef(s1); + df->dtext = de -df; + copydef(s2); +} + +copydef(s) +char *s; +{ + while(*de++ = *s++) + if(de>dmax) diag("Definition table overflow"); +} + +char * +arg(n) { + char *p; + p = &gf->ga0; + while(--n>=0 && p->word!=0) p =+ p->word; + return(p->word!=0?p+2:p); +} + +function(n) { + if(n==0) ; + else if(1<=n && n<=13) binop(n); + else { + switch(n) { + case 20: + doif(); + return; + case 21: + define(); + return; + case 22: + copy(); + return; + case 23: + meta(); + return; + case 24: + size(); + return; + case 25: + substr(); + return; + case 26: + case 27: + go(n); + return; + case 28: + remove(1); + return; + case 29: + dnl(); + return; + case 32: + quote(); + return; + case 33: + result(finddef(1)->dswitch); + return; + case 34: + list(); + return; + case 35: + traceflag = comp(arg(1),one); + return; + } + } +} diff --git a/source/m6/m66.c b/source/m6/m66.c new file mode 100644 index 0000000..2ca8c52 --- /dev/null +++ b/source/m6/m66.c @@ -0,0 +1,164 @@ +# + +#include "m6.h" + + +doif() { + int i; + int *p; + char *arg(); + i = 1; + while(!comp(arg(i),one)) if((i =+ 2)>8) return; + p = arg(i+1) - 2; + ge = move(p,&gf->ga0,p->word+1); + setscan(dummy); +} + +bindec(n) { + if(n == 0) return; + bindec(n/10); + *ge++ = (n%10) + '0'; +} + +result(n) { + char *p; + setscan(dummy); + ge = 2 + (p = &gf->ga0); + if(n<0) { + *ge++ = '-'; + n = -n; + } + if(n==0) *ge++ = '0'; + else bindec(n); + *ge++ = 0; + ge = (ge+1)&0177776; + p->word = ge - p; + *ge++ = *ge++ = 0; +} + +binop(code) { + int r1,r2; + int r,t; + int arg1, arg2; + arg1 = decbin(1); + arg2 = decbin(2); + if(code < 7) /* relationals */ + result((code & ((arg1ga0 = 0; + return; + case 13: /* exp */ + r = 1; + while(arg2-->0) r =* arg1; + result(r); + if(arg2<-1) gf->ga0 = 0; + } +} + +decbin(i) { + char *s; + char t; + int n; + if(t = (*(s = arg(i))=='-')) s++; + n = 0; + while(*s>='0' && *s<='9') n = 10*n + *s++ - '0'; + return(t?-n:n); +} + +dnl() { + char d; + d = 0; + while(d=getchar()) if(d=='\n') return; +} + +quote() { + char *p,*s; + p = finddef(1); + s = &p[p->dtext]; + while(c = *s++) put(); +} + +list() { + int n,i; + char *p; + if((n=decbin(1))<=0) return; + p = df; + for(i=1;;) { + if(p<=d0) return; + if(p->dswitch>=0) + if(i++>=n) break; + p =+ p->prev; + } + for(p = &p->dident;c = *p++;) + put(); +} + +copy() { + char *p; + p = finddef(1); + remove(2); + newdef(p->dswitch); + setdef(arg(2),p+p->dtext); +} + +go(n) { + if(comp(arg(1),one)) { + popget(); + if(lg>0) + if(n==26) popget(); + else setscan(gf->mframe); /* gobk=27 */ + } +} + +size() { + int i; + char *p; + i = 0; + p = arg(1); + while(*p++ != 0) i++; + result(i); +} + +meta() { + char d; + int i; + char *arg(); + if((d = *arg(2))!=0) { + for(i=0;i0 && *s!=0) s++; + while(arg3-->0) { + if((*de++ = *s++)==0) return; + if(de>dmax) diag("No room for substr"); + } + *de++ = 0; +} diff --git a/source/m6/m67.c b/source/m6/m67.c new file mode 100644 index 0000000..f5b9d1c --- /dev/null +++ b/source/m6/m67.c @@ -0,0 +1,66 @@ +#define PSIZE 1000 +#define GSIZE 2000 +#define DSIZE 5000 + +int pmax PSIZE; +char p0[PSIZE]; + +int gmax GSIZE; +char g0[GSIZE]; + +int dmax DSIZE; +char d0[DSIZE] { + 0,0, + 8,0, 0,0, 6,0, 0,0, /*null*/ + 12,0, 35,0, 11,0, 't','r','a','c','e',0, + 12,0, 23,0, 10,0, 'w','a','r','n',0,0, + 12,0, 22,0, 10,0, 'c','o','p','y',0,0, + 12,0, 32,0, 11,0, 'q','u','o','t','e',0, + 14,0, 33,0, 12,0, 's','e','r','i','a','l',0,0, + 12,0, 34,0, 10,0, 'l','i','s','t',0,0, + 12,0, 24,0, 10,0, 's','i','z','e',0,0, + 14,0, 25,0, 12,0, 's','u','b','s','t','r',0,0, + 10,0, 26,0, 8,0, 'g','o',0,0, + 12,0, 27,0, 10,0, 'g','o','b','k',0,0, + 10,0, 28,0, 9,0, 'd','e','l',0, + 10,0, 29,0, 9,0, 'd','n','l',0, + 10,0, 7,0, 9,0, 's','e','q',0, + 10,0, 8,0, 9,0, 's','n','e',0, + 10,0, 9,0, 9,0, 'a','d','d',0, + 10,0, 10,0, 9,0, 's','u','b',0, + 10,0, 11,0, 9,0, 'm','p','y',0, + 10,0, 12,0, 9,0, 'd','i','v',0, + 10,0, 13,0, 9,0, 'e','x','p',0, + 10,0, 1,0, 8,0, 'g','t',0,0, + 10,0, 2,0, 8,0, 'e','q',0,0, + 10,0, 3,0, 8,0, 'g','e',0,0, + 10,0, 4,0, 8,0, 'l','t',0,0, + 10,0, 5,0, 8,0, 'n','e',0,0, + 10,0, 6,0, 8,0, 'l', 'e',0,0, + 10,0, 21,0, 9,0, 'd','e','f',0, + 10,0, 20,0, 8,0, 'i','f',0, + 0,0 +}; + +int dummy[] { + 0, + 0, + 6, + '$0', + 0 +}; +char metas[] { + '<', + '>', + '#', + ':', + ';', + ',', + '$' +}; + +int rescan 1; +int traceflag 0; +int trashflag 0; +char one[] { + '1',0 }; diff --git a/source/m6/run b/source/m6/run new file mode 100644 index 0000000..621a4c1 --- /dev/null +++ b/source/m6/run @@ -0,0 +1,4 @@ +cc -s -O m6?.c +cmp a.out /usr/bin/m6 +cp a.out /usr/bin/m6 +rm a.out *.o diff --git a/source/mdec/dldr.s b/source/mdec/dldr.s new file mode 100644 index 0000000..6c4ce3c --- /dev/null +++ b/source/mdec/dldr.s @@ -0,0 +1,106 @@ +/ copy and execute DEC loaders + +core = 24. +prs = 177550 + + mov $dldr,r0 + mov $[core*2048.]-300,r1 + mov r1,r2 +1: + mov (r0)+,(r1)+ + cmp r0,$end + blo 1b + jmp (r2) + +dldr: + 10706 + 24646 + 10705 + 62705 + 114 + 5001 + 13716 + 177570 + 6016 + 103402 + 5016 + 404 + 241 + 6116 + 1001 + 10116 + 5000 + 4715 + 105303 + 1374 + 4715 + 4767 + 74 + 10402 + 162702 + 4 + 22702 + 2 + 1441 + 4767 + 54 + 61604 + 10401 + 4715 + 2004 + 105700 + 1753 + 0 + 751 + 110321 + 770 + 16703 + 150 + 105213 + 105713 + 100376 + 116303 + 2 + 60300 + 42703 + 177400 + 5302 + 207 + 12667 + 44 + 4715 + 10304 + 4715 + 303 + 50304 + 16707 + 26 + 4767 + 177752 + 4715 + 105700 + 1342 + 6204 + 103002 + 0 + 677 + 6304 + 114 + 0 + +. = dldr-500+744 + 16701 + 26 + 12702 + 352 + 5211 + 105711 + 100376 + 116162 + 2 + [core*2048.]-400 + 5267 + 177756 + 765 + prs +end: diff --git a/source/mdec/dtf.s b/source/mdec/dtf.s new file mode 100644 index 0000000..64f2b73 --- /dev/null +++ b/source/mdec/dtf.s @@ -0,0 +1,337 @@ +/ unix DEC-tape time/mtrack track formatter + +nword = 256. +nblock = 578. +endz = 7200. + +ps = 177776 +tcst = 177340 +tccm = 177342 +tcwc = 177344 +tcba = 177346 +tcdt = 177350 + + mov r5,savr5 + mov sp,savsp + +start: + mov savr5,r5 + mov savsp,sp + jsr pc,4(r5) + + .even + + clr r0 + mov $cobtab,r1 +1: + jsr pc,bcomobv + mov r2,(r1)+ + inc r0 + cmp r0,$512. + bne 1b + + mov $buffer,r0 +1: + mov $-1,(r0)+ + cmp r0,$buffer+nword+nword + blo 1b + + mov savr5,r5 + jsr pc,2(r5) + + mov $340,ps + mov $tcdt,r5 + mov $13,tccm + jsr pc,flag + +/ 8Kch for end zone + + mov $endz,r4 +1: + jsr r0,mtrack; 101101 + dec r4 + bne 1b + +/ foreward guard + + mov $199.,r4 +1: + jsr r0,mtrack; 10101 + dec r4 + bne 1b + +/ blocks + + mov $nblock,r3 +1: + jsr r0,mtrack; 10101 + jsr r0,mtrack; 10110 + jsr r0,mtrack; 11010 + jsr r0,mtrack; 01000 + jsr r0,mtrack; 01000 + jsr r0,mtrack; 01000 + jsr r0,mtrack; 01000 + mov $nword-4,r4 +2: + jsr r0,mtrack; 111000 + dec r4 + bne 2b + jsr r0,mtrack; 111011 + jsr r0,mtrack; 111011 + jsr r0,mtrack; 111011 + jsr r0,mtrack; 111011 + jsr r0,mtrack; 101001 + jsr r0,mtrack; 100101 + jsr r0,mtrack; 10101 + dec r3 + bne 1b + +/ rear guard + + mov $199.,r4 +1: + jsr r0,mtrack; 10101 + dec r4 + bne 1b + +/ rear end zone + + mov $endz,r4 +1: + jsr r0,mtrack; 10010 + dec r4 + bne 1b + clr tccm + +/ end of mtrack pass +/ go back 12 blocks + + mov $12.,r0 + mov $4002,tccm +1: + incb tccm + jsr pc,flag + dec r0 + bne 1b + +/ put comobv(nblock-1) in everything +/ up to end zone + + mov $nblock-1,r0 + mov r0,bn + jsr pc,comobv + mov $17,tccm + jsr pc,flag +1: + movb r1,tcst + mov r0,(r5) + jsr pc,flag1 + br 1b + +/ reverse pass put in +/ foreward and reverse +/ block numbers + + mov $4017,tccm + jsr pc,flag +1: + mov $nword+3.,r4 +2: + clrb tcst + clr (r5) + jsr pc,flag + dec r4 + bne 2b + + clrb tcst + clr (r5) + mov bn,r0 + jsr pc,comobv + jsr pc,flag + movb r1,tcst + mov r0,(r5) + jsr pc,flag + dec bn + blt check + clrb tcst + clr (r5) + jsr pc,flag + clrb tcst + clr (r5) + jsr pc,flag + clrb tcst + mov bn,(r5) + jsr pc,flag + clrb tcst + clr (r5) + jsr pc,flag + clrb tcst + clr (r5) + jsr pc,flag + br 1b + +/ foreward pass +/ confirm block numbers +/ write all 1's in data + +check: + clrb tcst + clr (r5) + jsr pc,flag1 + br check + clr r4 +1: + mov $3,tccm + jsr pc,flag + cmp (r5),r4 + bne error1 + mov $-nword,tcwc + mov $buffer,tcba + mov $15,tccm + jsr pc,flag + inc r4 + cmp r4,$nblock + bne 1b + mov $3,tccm + jsr pc,flag1 + br error2 + +/ reverse pass +/ confirm block numbers +/ read data and compare +/ to all 1's + +1: + mov $4003,tccm + jsr pc,flag + dec r4 + cmp r4,(r5) + bne error3 + mov $-nword,tcwc + mov $buffer,tcba + mov $4005,tccm + jsr pc,compare + jsr pc,flag + tst r4 + bne 1b + mov $4003,tccm + jsr pc,flag1 + br error4 + jsr pc,compare + jmp start + +error1: + mov $1,r0 + br 1f +error2: + mov $1,r0 + br 1f +error3: + mov $3,r0 + br 1f +error4: + mov $4,r0 + br 1f +error5: + mov $5,r0 + br 1f +error6: + mov $6,r0 + br 1f +error7: + mov $7,r0 +1: + add $'0,r0 + movb r0,0f + mov tcst,-(sp) + mov tccm,-(sp) + mov $1,tccm + mov savr5,r5 + jsr pc,4(r5) + +0: + + .even + mov (sp)+,r1 + mov (sp)+,r0 + 0 + rts pc + +compare: + mov r0,-(sp) + mov $buffer,r0 +1: + cmp (r0)+,$-1 + bne error5 + cmp r0,$buffer+nword+nword + blo 1b + mov (sp)+,r0 + rts pc + +mtrack: + mov (r0)+,(r5) + jsr pc,flag + rts r0 + +flag: + bit $100200,tccm + beq flag + blt error6 + rts pc + +flag1: + bit $100200,tccm + beq flag1 + bge 1f + tst tcst + bge error7 + add $2,(sp) +1: + rts pc + +comobv: + mov r0,r4 + bic $!777,r0 + asl r0 + mov cobtab(r0),r0 + swab r0 + clr r1 + ror r0 + rol r1 + asl r0 + asl r0 + rol r1 + swab r4 + bic $177401,r4 + bis cobtab(r4),r0 + rts pc + +bcomobv: + mov r0,r2 + bic $!70,r2 + mov r0,r3 + mov $6.,r4 +1: + asr r3 + dec r4 + bne 1b + bic $!7,r3 + bis r3,r2 + mov r0,r3 + mov $6.,r4 +1: + asl r3 + dec r4 + bne 1b + bic $!700,r3 + bis r3,r2 + com r2 + bic $!777,r2 + rts pc + +bn: .=.+2 +savr5: .=.+2 +savsp: .=.+2 +cobtab: .=.+1024. +buffer: .=.+nword+nword + diff --git a/source/mdec/fsboot.s b/source/mdec/fsboot.s new file mode 100644 index 0000000..e885133 --- /dev/null +++ b/source/mdec/fsboot.s @@ -0,0 +1,183 @@ +/ disk boot program to load and transfer +/ to a unix file system entry +/ must be assembled with tty.s and +/ appropriate disk driver + +/ entry is made by jsr pc,*$0 +/ so return can be rts pc + +core = 24. / first core loc (in KW) not used +.. = [core*2048.]-512. +start: + +/ copy self to 'core' - 512. bytes +/ strip of UNIX execute header if present + + mov $..,sp + mov sp,r1 + clr r0 + cmp pc,r1 + bhis 2f + cmp (r0),$407 + bne 1f + mov $20,r0 +1: + mov (r0)+,(r1)+ + cmp r1,$core*2048. + blo 1b + jmp (sp) + +/ clear all of core + +2: + clr (r0)+ + cmp r0,sp + blo 2b + +/ prompt +/ read in path name +/ breaking on '/' into 14 ch names + + mov $trvect,r5 + mov $'@,r0 + jsr pc,(r5) + mov $names,r2 +1: + mov r2,r1 +2: + jsr pc,getc + cmp r0,$'\n + beq 1f + cmp r0,$'/ + beq 3f + movb r0,(r1)+ + br 2b +3: + cmp r2,r1 + beq 2b + add $14.,r2 + br 1b +1: + +/ start of path name decoding +/ start with first name and root ino + + mov $names,r2 + mov $1,r0 + +/ get next inode + +1: + clr bno + jsr pc,iget + tst (r2) + beq 1f + +/ read next directory looking for next name + +2: + jsr pc,rmblk + br start + mov $buf,r1 +3: + mov r2,r3 + mov r1,r4 + add $16.,r1 + tst (r4)+ + beq 5f +4: + cmpb (r3)+,(r4)+ + bne 5f + cmp r4,r1 + blo 4b + mov -16.(r1),r0 + add $14.,r2 + br 1b +5: + cmp r1,$buf+512. + blo 3b + br 2b + +/ last entry was found +/ read into 0. + +1: + clr r2 +1: + jsr pc,rmblk + br callout + mov $buf,r1 +2: + mov (r1)+,(r2)+ + cmp r1,$buf+512. + blo 2b + br 1b + +/ subroutine will read in inode +/ number specified in r0 +iget: + add $31.,r0 + mov r0,r5 + ash $-4.,r0 + jsr pc,rblka + bic $!17,r5 + ash $5.,r5 + add $buf,r5 + mov $inod,r4 +1: + mov (r5)+,(r4)+ + cmp r4,$addr+16. + blo 1b + rts pc + +/ routine to read in block +/ number specified by bno +/ after applying file system +/ mapping algorithm in inode. +/ bno is incremented, success +/ return is a skip, error (eof) +/ is direct return. +rmblk: + add $2,(sp) + mov bno,r0 + inc bno + bit $LRG,mode + bne 1f + asl r0 + mov addr(r0),r0 + bne rblka +2: + sub $2,(sp) + rts pc +/ large algorithm +/ huge algorithm is not implemented +1: + clr -(sp) + movb r0,(sp) + clrb r0 + swab r0 + asl r0 + mov addr(r0),r0 + beq 2b + jsr pc,rblka + mov (sp)+,r0 + asl r0 + mov buf(r0),r0 + beq 2b +rblka: + mov r0,dska + br rblk + +ba: buf +wc: -256. +.bss +end: +inod = ..-1024. +mode = inod +addr = inod+8. +buf = inod+32. +bno = buf+514. +dska = bno+2 +names = dska+2 +LRG = 10000 +.text diff --git a/source/mdec/hp.s b/source/mdec/hp.s new file mode 100644 index 0000000..06edd60 --- /dev/null +++ b/source/mdec/hp.s @@ -0,0 +1,38 @@ +/ rp04 disk driver + +hpcs1 = 176700 +hpda = 176706 +hpcs2 = 176710 +hpof = 176732 +hpca = 176734 + +fmt22 = 010000 +preset = 021 +clear = 040 + +first = .+2 / dirty, but i need the space + tst $0 + bne 1f + mov $clear,*$hpcs2 + mov $preset,*$hpcs1 + mov $fmt22,*$hpof + inc first +1: + mov dska,r1 + clr r0 + div $22.,r0 + mov r1,-(sp) + mov r0,r1 + clr r0 + div $19.,r0 + bisb r1,1(sp) + mov r0,*$hpca + mov $hpda,r1 + mov (sp)+,(r1) + mov ba,-(r1) + mov wc,-(r1) + mov $iocom,-(r1) +1: + tstb (r1) + bpl 1b + rts pc diff --git a/source/mdec/ht.s b/source/mdec/ht.s new file mode 100644 index 0000000..f487c80 --- /dev/null +++ b/source/mdec/ht.s @@ -0,0 +1,70 @@ +htcs1 = 172440 +htba = 172444 +htfc = 172446 +htcs2 = 172450 +htds = 172452 +httc = 172472 + +P800 = 1300 +P1600 = 2300 +PIP = 20000 +MOL = 10000 +ERR = 40000 +REV = 33 +READ = 71 +REW = 7 + +tread: +1: + mov ba,mtma + cmp mtapa,tapa + beq 1f + bhi 2f + jsr pc,rrec + br 1b +2: + jsr pc,rew + br 1b +1: + mov wc,r1 +1: + jsr pc,rrec + add $256.,r1 + bmi 1b + rts pc + +rrec: + mov $htds,r0 + tstb (r0) + bpl rrec + bit $PIP,(r0) + bne rrec + bit $MOL,(r0) + beq rrec + mov $htfc,r0 + mov $-512.,(r0) + mov mtma,-(r0) + mov $-256.,-(r0) + mov $READ,-(r0) +1: + tstb (r0) + bpl 1b + bit $ERR,*$htds + bpl 1f + mov $-1,*$htfc + mov $REV,(r0) + br rrec +1: + add $512.,mtma + inc mtapa + rts pc + +rew: + clr *$htcs2 + mov $P800,*$httc + mov $REW,*$htcs1 + clr mtapa + rts pc + +mtapa: 0 +mtma: 0 diff --git a/source/mdec/mboot.s b/source/mdec/mboot.s new file mode 100644 index 0000000..9fd308b --- /dev/null +++ b/source/mdec/mboot.s @@ -0,0 +1,256 @@ +/ tape boot program to load and transfer +/ to a 'tp' entry + +/ entry is made by jsr pc,*$0 +/ so return can be rts pc +/ jsr pc,(r5) is putc +/ jsr pc,2(r5) is getc +/ jsr pc,4(r5) is mesg + +core = 24. +.mt. = 1 +.. = [core*2048.]-512. +start: + mov $..,sp + mov $name,r4 + mov sp,r1 + cmp pc,r1 + bhis 2f + clr r0 + cmp (r0),$407 + bne 1f + mov $20,r0 +1: + mov (r0)+,(r1)+ + cmp r1,$end + blo 1b + jmp (sp) + +2: + jsr pc,rew + mov $tvec,r5 + mov $'=,r0 + jsr pc,(r5) +2: + mov r4,r1 +1: + jsr pc,2(r5) + cmp r0,$'\n + beq 1f + cmp r0,$'@ + beq 2b + movb r0,(r1)+ + cmp r0,$'# + bne 1b + sub $2,r1 + cmp r1,r4 + blo 2b + br 1b +1: + clrb (r1) + cmp r1,r4 + blos start + mov $1,tapa + mov $-6144.,wc + jsr pc,taper + clr r1 +1: + mov r1,r2 + mov r4,r0 +2: + cmpb (r0)+,(r1) + bne 2f + tstb (r1)+ + bne 2b + br 1f +2: + mov r2,r1 + add $64.,r1 + cmp r1,$12288. + blo 1b + jsr pc,rew + br start +1: + mov 44.(r2),tapa + mov 38.(r2),r0 + inc r0 + clc + ror r0 + neg r0 + mov r0,wc + clr r0 +1: + clr (r0)+ + cmp r0,sp + blo 1b + jsr pc,taper + jsr pc,rew + clr r0 + cmp (r0),$407 / unix a.out? + bne 2f +1: + mov 20(r0),(r0)+ + cmp r0,sp + blo 1b +2: + jsr pc,*$0 + br start + +.if .mt. +mts = 172520 +mtc = 172522 +mtbrc = 172524 +mtcma = 172526 + +taper: + clr mtma + cmp mtapa,tapa + beq 1f + bhi 2f + jsr pc,rrec + br taper +2: + jsr pc,rew + br taper +1: + mov wc,r1 +1: + jsr pc,rrec + add $256.,r1 + bmi 1b + rts pc + +rrec: + bit $2,*$mts + bne rrec + tstb *$mtc + bge rrec + mov $-512.,*$mtbrc + mov mtma,*$mtcma + mov $60003,*$mtc +1: + tstb *$mtc + bge 1b + tst *$mtc + bge 1f + mov $-1,*$mtbrc + mov $60013,*$mtc + br rrec +1: + add $512.,mtma + inc mtapa + rts pc + +rew: + mov $60017,*$mtc + clr mtapa + rts pc +.endif + +.if .mt.-1 +tcdt = 177350 +tccm = 177342 +taper: + mov $tcdt,r0 + mov $tccm,r1 +for: + mov $3,(r1) / rbn for +1: + tstb (r1) + bge 1b + tst (r1) + blt rev + cmp tapa,(r0) + beq rd + bgt for + +rev: + mov $4003,(r1) / rbn bac +1: + tstb (r1) + bge 1b + tst (r1) + blt for + mov (r0),r2 + add $5,r2 + cmp tapa,r2 + blt rev + br for + +rd: + clr -(r0) / bus addr + mov wc,-(r0) / wc + mov $5,-(r0) / read +1: + tstb (r1) + bge 1b + tst (r1) + blt taper + rts pc + +rew: + mov $4003,tccm + rts pc +.endif + +tvec: + br putc + br getc + br mesg + +tks = 177560 +tkb = 177562 +getc: + mov $tks,r0 + inc (r0) +1: + tstb (r0) + bge 1b + mov tkb,r0 + bic $!177,r0 + cmp r0,$'A + blo 1f + cmp r0,$'Z + bhi 1f + add $40,r0 +1: + cmp r0,$'\r + bne putc + mov $'\n,r0 + +tps = 177564 +tpb = 177566 +putc: + tstb tps + bge putc + cmp r0,$'\n + bne 1f + mov $'\r,r0 + jsr pc,(r5) + mov $'\n+200,r0 + jsr pc,(r5) + clr r0 + jsr pc,(r5) + mov $'\n,r0 + rts pc +1: + mov r0,tpb + rts pc + +mesg: + movb *(sp),r0 + beq 1f + jsr pc,(r5) + inc (sp) + br mesg +1: + add $2,(sp) + bic $1,(sp) + rts pc + +end: +tapa: .=.+2 +mtapa: .=.+2 +mtma: .=.+2 +wc: .=.+2 +name: .=.+32. diff --git a/source/mdec/mcopy.s b/source/mdec/mcopy.s new file mode 100644 index 0000000..12a0232 --- /dev/null +++ b/source/mdec/mcopy.s @@ -0,0 +1,59 @@ +/ copy mag tape to disk +/ load with proper tape and disk drivers + + jsr pc,rew +2: + jsr pc,4(r5) + + .even + jsr pc,numb + mov r0,dska + jsr pc,4(r5) + + .even + jsr pc,numb + mov r0,tapa + jsr pc,4(r5) + + .even + jsr pc,numb + mov r0,r2 +1: + jsr pc,tread + jsr pc,wblk + inc tapa + inc dska + dec r2 + bne 1b + jsr pc,rew + rts pc + +numb: + clr r1 +1: + jsr pc,2(r5) + cmp r0,$'\n + beq 1f + sub $'0,r0 + cmp r0,$9 + bhi 2f + mul $10.,r1 + add r0,r1 + br 1b +1: + mov r1,r0 + rts pc +2: + jsr pc,4(r5) + + .even + tst (sp)+ + rts pc + +ba: buf +wc: -256. +.bss +buf: .=.+512. +dska: .=.+2 +tapa: .=.+2 +.text diff --git a/source/mdec/reset.s b/source/mdec/reset.s new file mode 100644 index 0000000..a64688e --- /dev/null +++ b/source/mdec/reset.s @@ -0,0 +1,3 @@ +/ reset + 5 + rts pc diff --git a/source/mdec/rhp.s b/source/mdec/rhp.s new file mode 100644 index 0000000..1ff98c0 --- /dev/null +++ b/source/mdec/rhp.s @@ -0,0 +1,5 @@ +/ hpread + +rblk: + +iocom = 71 diff --git a/source/mdec/rk.s b/source/mdec/rk.s new file mode 100644 index 0000000..137a9b1 --- /dev/null +++ b/source/mdec/rk.s @@ -0,0 +1,17 @@ +/ rk05 disk driver + +rkda = 177412 + mov dska,r1 + clr r0 + div $12.,r0 + ash $4.,r0 + bis r1,r0 + mov $rkda,r1 + mov r0,(r1) + mov ba,-(r1) + mov wc,-(r1) + mov $iocom,-(r1) +1: + tstb (r1) + bpl 1b + rts pc diff --git a/source/mdec/rkf.s b/source/mdec/rkf.s new file mode 100644 index 0000000..d8c1d83 --- /dev/null +++ b/source/mdec/rkf.s @@ -0,0 +1,37 @@ +/ format RK03/05 disk packs + +rkda = 177412 + + jsr pc,4(r5) + ; .even + jsr pc,2(r5) + mov r0,-(sp) + mov $'\n,r0 + jsr pc,(r5) + cmp (sp)+,$'y + beq 1f + rts pc +1: + mov $203.*2,r4 + clr r3 +1: + mov $rkda+2,r0 + mov r3,-(r0) + mov $buf,-(r0) + mov $-12.*256.,-(r0) + mov $6003,-(r0) +2: + tstb (r0) + bge 2b + tst (r0) + blt 1f + add $20,r3 + dec r4 + bne 1b + rts pc +1: + jsr pc,4(r5) + ; .even + rts pc + +buf: .=.+2 diff --git a/source/mdec/rp.s b/source/mdec/rp.s new file mode 100644 index 0000000..c114324 --- /dev/null +++ b/source/mdec/rp.s @@ -0,0 +1,21 @@ +/ rp03 disk driver + +rpda = 176724 + mov dska,r1 + clr r0 + div $10.,r0 + mov r1,-(sp) + mov r0,r1 + clr r0 + div $20.,r0 + bisb r1,1(sp) + mov $rpda,r1 + mov (sp)+,(r1) + mov r0,-(r1) + mov ba,-(r1) + mov wc,-(r1) + mov $iocom,-(r1) +1: + tstb (r1) + bpl 1b + rts pc diff --git a/source/mdec/rrk.s b/source/mdec/rrk.s new file mode 100644 index 0000000..02f7ac3 --- /dev/null +++ b/source/mdec/rrk.s @@ -0,0 +1,4 @@ +/ read rk + +rblk: +iocom = 5 diff --git a/source/mdec/rrp.s b/source/mdec/rrp.s new file mode 100644 index 0000000..584e044 --- /dev/null +++ b/source/mdec/rrp.s @@ -0,0 +1,4 @@ +/ read rp + +rblk: +iocom = 5 diff --git a/source/mdec/run b/source/mdec/run new file mode 100644 index 0000000..fe12c0e --- /dev/null +++ b/source/mdec/run @@ -0,0 +1,71 @@ +as fsboot.s tty.s rrk.s rk.s +strip a.out +ls -l a.out +cp a.out /usr/mdec/rkuboot + +as fsboot.s tty.s rrp.s rp.s +strip a.out +ls -l a.out +cp a.out /usr/mdec/rpuboot + +as fsboot.s tty.s rhp.s hp.s +strip a.out +ls -l a.out +cp a.out /usr/mdec/hpuboot + +as tpboot.s tty.s tc.s +strip a.out +ls -l a.out +cp a.out /usr/mdec/tboot + +as tpboot.s tty.s tm.s +strip a.out +ls -l a.out +cp a.out /usr/mdec/mboot + +as tpboot.s tty.s ht.s +strip a.out +ls -l a.out +cp a.out /usr/mdec/hboot + +as tcf.s +strip a.out +cp a.out /usr/mdec/tcf + +as rkf.s +strip a.out +cp a.out /usr/mdec/rkf + +as reset.s +strip a.out +cp a.out /usr/mdec/reset + +as dldr.s +strip a.out +cp a.out /usr/mdec/dldr + +as mcopy.s tm.s wrk.s rk.s +strip a.out +cp a.out /usr/mdec/tmrk + +as mcopy.s tm.s wrp.s rp.s +strip a.out +cp a.out /usr/mdec/tmrp + +as mcopy.s tm.s whp.s hp.s +strip a.out +cp a.out /usr/mdec/tmhp + +as mcopy.s ht.s wrk.s rk.s +strip a.out +cp a.out /usr/mdec/htrk + +as mcopy.s ht.s wrp.s rp.s +strip a.out +cp a.out /usr/mdec/htrp + +as mcopy.s ht.s whp.s hp.s +strip a.out +cp a.out /usr/mdec/hthp + +rm a.out diff --git a/source/mdec/tboot.s b/source/mdec/tboot.s new file mode 100644 index 0000000..80209cb --- /dev/null +++ b/source/mdec/tboot.s @@ -0,0 +1,256 @@ +/ tape boot program to load and transfer +/ to a 'tp' entry + +/ entry is made by jsr pc,*$0 +/ so return can be rts pc +/ jsr pc,(r5) is putc +/ jsr pc,2(r5) is getc +/ jsr pc,4(r5) is mesg + +core = 24. +.mt. = 0 +.. = [core*2048.]-512. +start: + mov $..,sp + mov $name,r4 + mov sp,r1 + cmp pc,r1 + bhis 2f + clr r0 + cmp (r0),$407 + bne 1f + mov $20,r0 +1: + mov (r0)+,(r1)+ + cmp r1,$end + blo 1b + jmp (sp) + +2: + jsr pc,rew + mov $tvec,r5 + mov $'=,r0 + jsr pc,(r5) +2: + mov r4,r1 +1: + jsr pc,2(r5) + cmp r0,$'\n + beq 1f + cmp r0,$'@ + beq 2b + movb r0,(r1)+ + cmp r0,$'# + bne 1b + sub $2,r1 + cmp r1,r4 + blo 2b + br 1b +1: + clrb (r1) + cmp r1,r4 + blos start + mov $1,tapa + mov $-6144.,wc + jsr pc,taper + clr r1 +1: + mov r1,r2 + mov r4,r0 +2: + cmpb (r0)+,(r1) + bne 2f + tstb (r1)+ + bne 2b + br 1f +2: + mov r2,r1 + add $64.,r1 + cmp r1,$12288. + blo 1b + jsr pc,rew + br start +1: + mov 44.(r2),tapa + mov 38.(r2),r0 + inc r0 + clc + ror r0 + neg r0 + mov r0,wc + clr r0 +1: + clr (r0)+ + cmp r0,sp + blo 1b + jsr pc,taper + jsr pc,rew + clr r0 + cmp (r0),$407 / unix a.out? + bne 2f +1: + mov 20(r0),(r0)+ + cmp r0,sp + blo 1b +2: + jsr pc,*$0 + br start + +.if .mt. +mts = 172520 +mtc = 172522 +mtbrc = 172524 +mtcma = 172526 + +taper: + clr mtma + cmp mtapa,tapa + beq 1f + bhi 2f + jsr pc,rrec + br taper +2: + jsr pc,rew + br taper +1: + mov wc,r1 +1: + jsr pc,rrec + add $256.,r1 + bmi 1b + rts pc + +rrec: + bit $2,*$mts + bne rrec + tstb *$mtc + bge rrec + mov $-512.,*$mtbrc + mov mtma,*$mtcma + mov $60003,*$mtc +1: + tstb *$mtc + bge 1b + tst *$mtc + bge 1f + mov $-1,*$mtbrc + mov $60013,*$mtc + br rrec +1: + add $512.,mtma + inc mtapa + rts pc + +rew: + mov $60017,*$mtc + clr mtapa + rts pc +.endif + +.if .mt.-1 +tcdt = 177350 +tccm = 177342 +taper: + mov $tcdt,r0 + mov $tccm,r1 +for: + mov $3,(r1) / rbn for +1: + tstb (r1) + bge 1b + tst (r1) + blt rev + cmp tapa,(r0) + beq rd + bgt for + +rev: + mov $4003,(r1) / rbn bac +1: + tstb (r1) + bge 1b + tst (r1) + blt for + mov (r0),r2 + add $5,r2 + cmp tapa,r2 + blt rev + br for + +rd: + clr -(r0) / bus addr + mov wc,-(r0) / wc + mov $5,-(r0) / read +1: + tstb (r1) + bge 1b + tst (r1) + blt taper + rts pc + +rew: + mov $4003,tccm + rts pc +.endif + +tvec: + br putc + br getc + br mesg + +tks = 177560 +tkb = 177562 +getc: + mov $tks,r0 + inc (r0) +1: + tstb (r0) + bge 1b + mov tkb,r0 + bic $!177,r0 + cmp r0,$'A + blo 1f + cmp r0,$'Z + bhi 1f + add $40,r0 +1: + cmp r0,$'\r + bne putc + mov $'\n,r0 + +tps = 177564 +tpb = 177566 +putc: + tstb tps + bge putc + cmp r0,$'\n + bne 1f + mov $'\r,r0 + jsr pc,(r5) + mov $'\n+200,r0 + jsr pc,(r5) + clr r0 + jsr pc,(r5) + mov $'\n,r0 + rts pc +1: + mov r0,tpb + rts pc + +mesg: + movb *(sp),r0 + beq 1f + jsr pc,(r5) + inc (sp) + br mesg +1: + add $2,(sp) + bic $1,(sp) + rts pc + +end: +tapa: .=.+2 +mtapa: .=.+2 +mtma: .=.+2 +wc: .=.+2 +name: .=.+32. diff --git a/source/mdec/tc.s b/source/mdec/tc.s new file mode 100644 index 0000000..cae6d44 --- /dev/null +++ b/source/mdec/tc.s @@ -0,0 +1,43 @@ +tcdt = 177350 +tccm = 177342 +tread: + mov $tcdt,r0 + mov $tccm,r1 +for: + mov $3,(r1) / rbn for +1: + tstb (r1) + bge 1b + tst (r1) + blt rev + cmp tapa,(r0) + beq rd + bgt for + +rev: + mov $4003,(r1) / rbn bac +1: + tstb (r1) + bge 1b + tst (r1) + blt for + mov (r0),r2 + add $5,r2 + cmp tapa,r2 + blt rev + br for + +rd: + mov ba,-(r0) / bus addr + mov wc,-(r0) / wc + mov $5,-(r0) / read +1: + tstb (r1) + bge 1b + tst (r1) + blt tread + rts pc + +rew: + mov $4003,tccm + rts pc diff --git a/source/mdec/tcf.s b/source/mdec/tcf.s new file mode 100644 index 0000000..fcd9bb4 --- /dev/null +++ b/source/mdec/tcf.s @@ -0,0 +1,332 @@ +/ unix DEC-tape time/mtrack track formatter + +nword = 256. +nblock = 578. +endz = 7200. + +ps = 177776 +tcst = 177340 +tccm = 177342 +tcwc = 177344 +tcba = 177346 +tcdt = 177350 + + mov r5,savr5 + mov sp,savsp + + jsr pc,4(r5) + ; .even + jsr pc,2(r5) + mov r0,-(sp) + mov $'\n,r0 + jsr pc,(r5) + cmp (sp)+,$'y + beq 1f + rts pc +1: + clr r0 + mov $cobtab,r1 +1: + jsr pc,bcomobv + mov r2,(r1)+ + inc r0 + cmp r0,$512. + bne 1b + + mov $buffer,r0 +1: + mov $-1,(r0)+ + cmp r0,$buffer+nword+nword + blo 1b + + mov savr5,r5 + jsr pc,2(r5) + + mov $340,ps + mov $tcdt,r5 + mov $13,tccm + jsr pc,flag + +/ 8Kch for end zone + + mov $endz,r4 +1: + jsr r0,mtrack; 101101 + dec r4 + bne 1b + +/ foreward guard + + mov $199.,r4 +1: + jsr r0,mtrack; 10101 + dec r4 + bne 1b + +/ blocks + + mov $nblock,r3 +1: + jsr r0,mtrack; 10101 + jsr r0,mtrack; 10110 + jsr r0,mtrack; 11010 + jsr r0,mtrack; 01000 + jsr r0,mtrack; 01000 + jsr r0,mtrack; 01000 + jsr r0,mtrack; 01000 + mov $nword-4,r4 +2: + jsr r0,mtrack; 111000 + dec r4 + bne 2b + jsr r0,mtrack; 111011 + jsr r0,mtrack; 111011 + jsr r0,mtrack; 111011 + jsr r0,mtrack; 111011 + jsr r0,mtrack; 101001 + jsr r0,mtrack; 100101 + jsr r0,mtrack; 10101 + dec r3 + bne 1b + +/ rear guard + + mov $199.,r4 +1: + jsr r0,mtrack; 10101 + dec r4 + bne 1b + +/ rear end zone + + mov $endz,r4 +1: + jsr r0,mtrack; 10010 + dec r4 + bne 1b + clr tccm + +/ end of mtrack pass +/ go back 12 blocks + + mov $12.,r0 + mov $4002,tccm +1: + incb tccm + jsr pc,flag + dec r0 + bne 1b + +/ put comobv(nblock-1) in everything +/ up to end zone + + mov $nblock-1,r0 + mov r0,bn + jsr pc,comobv + mov $17,tccm + jsr pc,flag +1: + movb r1,tcst + mov r0,(r5) + jsr pc,flag1 + br 1b + +/ reverse pass put in +/ foreward and reverse +/ block numbers + + mov $4017,tccm + jsr pc,flag +1: + mov $nword+3.,r4 +2: + clrb tcst + clr (r5) + jsr pc,flag + dec r4 + bne 2b + + clrb tcst + clr (r5) + mov bn,r0 + jsr pc,comobv + jsr pc,flag + movb r1,tcst + mov r0,(r5) + jsr pc,flag + dec bn + blt check + clrb tcst + clr (r5) + jsr pc,flag + clrb tcst + clr (r5) + jsr pc,flag + clrb tcst + mov bn,(r5) + jsr pc,flag + clrb tcst + clr (r5) + jsr pc,flag + clrb tcst + clr (r5) + jsr pc,flag + br 1b + +/ foreward pass +/ confirm block numbers +/ write all 1's in data + +check: + clrb tcst + clr (r5) + jsr pc,flag1 + br check + clr r4 +1: + mov $3,tccm + jsr pc,flag + cmp (r5),r4 + bne error1 + mov $-nword,tcwc + mov $buffer,tcba + mov $15,tccm + jsr pc,flag + inc r4 + cmp r4,$nblock + bne 1b + mov $3,tccm + jsr pc,flag1 + br error2 + +/ reverse pass +/ confirm block numbers +/ read data and compare +/ to all 1's + +1: + mov $4003,tccm + jsr pc,flag + dec r4 + cmp r4,(r5) + bne error3 + mov $-nword,tcwc + mov $buffer,tcba + mov $4005,tccm + jsr pc,compare + jsr pc,flag + tst r4 + bne 1b + mov $4003,tccm + jsr pc,flag1 + br error4 + jsr pc,compare + mov savr5,r5 + mov savsp,sp + rts pc + +error1: + mov $1,r0 + br 1f +error2: + mov $1,r0 + br 1f +error3: + mov $3,r0 + br 1f +error4: + mov $4,r0 + br 1f +error5: + mov $5,r0 + br 1f +error6: + mov $6,r0 + br 1f +error7: + mov $7,r0 +1: + mov $1,tccm + mov savr5,r5 + mov savsp,sp + jsr pc,4(r5) + ; .even + rts pc + +compare: + mov r0,-(sp) + mov $buffer,r0 +1: + cmp (r0)+,$-1 + bne error5 + cmp r0,$buffer+nword+nword + blo 1b + mov (sp)+,r0 + rts pc + +mtrack: + mov (r0)+,(r5) + jsr pc,flag + rts r0 + +flag: + bit $100200,tccm + beq flag + blt error6 + rts pc + +flag1: + bit $100200,tccm + beq flag1 + bge 1f + tst tcst + bge error7 + add $2,(sp) +1: + rts pc + +comobv: + mov r0,r4 + bic $!777,r0 + asl r0 + mov cobtab(r0),r0 + swab r0 + clr r1 + ror r0 + rol r1 + asl r0 + asl r0 + rol r1 + swab r4 + bic $177401,r4 + bis cobtab(r4),r0 + rts pc + +bcomobv: + mov r0,r2 + bic $!70,r2 + mov r0,r3 + mov $6.,r4 +1: + asr r3 + dec r4 + bne 1b + bic $!7,r3 + bis r3,r2 + mov r0,r3 + mov $6.,r4 +1: + asl r3 + dec r4 + bne 1b + bic $!700,r3 + bis r3,r2 + com r2 + bic $!777,r2 + rts pc + +bn: .=.+2 +savr5: .=.+2 +savsp: .=.+2 +cobtab: .=.+1024. +buffer: .=.+nword+nword diff --git a/source/mdec/tm.s b/source/mdec/tm.s new file mode 100644 index 0000000..503c676 --- /dev/null +++ b/source/mdec/tm.s @@ -0,0 +1,55 @@ +mts = 172520 +mtc = 172522 +mtbrc = 172524 +mtcma = 172526 + +tread: +1: + mov ba,mtma + cmp mtapa,tapa + beq 1f + bhi 2f + jsr pc,rrec + br 1b +2: + jsr pc,rew + br 1b +1: + mov wc,r1 +1: + jsr pc,rrec + add $256.,r1 + bmi 1b + rts pc + +rrec: + mov $mts,r0 + bit $2,(r0)+ / rewind status + bne rrec + tstb (r0)+ / cu ready + bpl rrec + inc r0 + mov $-512.,(r0)+ / byte count + mov mtma,(r0) / bus address + mov $mtc,r0 + mov $60003,(r0) / read 800bpi +1: + tstb (r0) + bpl 1b + tst (r0)+ + bpl 1f + mov $-1,(r0) + mov $60013,-(r0) / backspace + br rrec +1: + add $512.,mtma + inc mtapa + rts pc + +rew: + mov $60017,*$mtc + clr mtapa + rts pc + +mtapa: 0 +mtma: 0 diff --git a/source/mdec/tpboot.s b/source/mdec/tpboot.s new file mode 100644 index 0000000..00a51ac --- /dev/null +++ b/source/mdec/tpboot.s @@ -0,0 +1,92 @@ +/ tape boot program to load and transfer +/ to a 'tp' entry + +/ entry is made by jsr pc,*$0 +/ so return can be rts pc +/ jsr pc,(r5) is putc +/ jsr pc,2(r5) is getc +/ jsr pc,4(r5) is mesg + +core = 24. +.. = [core*2048.]-512. +start: + mov $..,sp + mov sp,r1 + cmp pc,r1 + bhis 2f + clr r0 + cmp (r0),$407 + bne 1f + mov $20,r0 +1: + mov (r0)+,(r1)+ + cmp r1,$core*2048. + blo 1b + jmp (sp) + +2: + mov $trvect,r5 + mov $name,r4 + jsr pc,rew + mov $'=,r0 + jsr pc,(r5) +2: + mov r4,r1 +1: + jsr pc,getc + cmp r0,$'\n + beq 1f + cmp r0,$'@ + beq 2b + movb r0,(r1)+ + cmp r0,$'# + bne 1b + sub $2,r1 + cmp r1,r4 + blo 2b + br 1b +1: + clrb (r1) + cmp r1,r4 + blos start + mov $1,tapa + mov $-6144.,wc + jsr pc,tread + clr r1 +1: + mov r1,r2 + mov r4,r0 +2: + cmpb (r0)+,(r1) + bne 2f + tstb (r1)+ + bne 2b + br 1f +2: + mov r2,r1 + add $64.,r1 + cmp r1,$12288. + blo 1b + jsr pc,rew + br start +1: + mov 44.(r2),tapa + mov 38.(r2),r0 + inc r0 + clc + ror r0 + neg r0 + mov r0,wc + clr r0 +1: + clr (r0)+ + cmp r0,sp + blo 1b + jsr pc,tread + jsr pc,rew + br callout + +tapa: 0 +wc: 0 +ba: 0 +name = ..-32. diff --git a/source/mdec/tty.s b/source/mdec/tty.s new file mode 100644 index 0000000..1d0319f --- /dev/null +++ b/source/mdec/tty.s @@ -0,0 +1,64 @@ +/ read and echo character from tty. +/ perform normal cr/lf uc/lc mapping. +tks = 177560 +tkb = 177562 +getc: + tstb *$tks + bge getc + mov tkb,r0 + bic $!177,r0 + cmp r0,$'A + blo 1f + cmp r0,$'Z + bhi 1f + add $'a-'A,r0 +1: + cmp r0,$'\r + bne putc + mov $'\n,r0 + +/ put a character on the tty. +/ also performs delay. +tps = 177564 +tpb = 177566 +putc: + cmp r0,$'\n + bne 1f + mov $'\r,r0 + jsr pc,(r5) + mov $'\n,r0 +1: + tstb tps + bpl 1b + mov r0,tpb + rts pc + +/ write a string to tty +/ jsr pc, mesg; ; .even +mesg: + movb *(sp),r0 + beq 1f + jsr pc,(r5) + inc (sp) + br mesg +1: + add $2,(sp) + bic $1,(sp) + rts pc + +callout: + clr r0 + cmp (r0),$407 + bne 2f +1: + mov 20(r0),(r0)+ + cmp r0,sp + blo 1b +2: + mov $start,-(sp) + clr pc + +trvect: + br putc + br getc + br mesg diff --git a/source/mdec/uboot.s b/source/mdec/uboot.s new file mode 100644 index 0000000..f9f334c --- /dev/null +++ b/source/mdec/uboot.s @@ -0,0 +1,239 @@ +/ disk boot program to load and transfer +/ to a unix entry + +/ entry is made by jsr pc,*$0 +/ so return can be rts pc + +core = 24. +.. = [core*2048.]-512. +start: + mov $..,sp + mov sp,r1 + cmp pc,r1 + bhis 2f + reset + clr r0 + cmp (r0),$407 + bne 1f + mov $20,r0 +1: + mov (r0)+,(r1)+ + cmp r1,$end + blo 1b + jmp (sp) + +2: + mov $inod,r0 +1: + clr (r0)+ + cmp r0,sp + blo 1b + jsr pc,getc + cmp r0,$'k + bne 3f + mov $rkblk,r0 + br 1f +3: + cmp r0,$'p + bne 2b + mov $rpblk,r0 +1: + mov r0,rxblk + mov $'\n,r0 + jsr pc,putc + mov $names,r1 + +1: + mov r1,r2 +2: + jsr pc,getc + cmp r0,$'\n + beq 1f + cmp r0,$'/ + beq 3f + movb r0,(r2)+ + br 2b +3: + cmp r1,r2 + beq 2b + add $14.,r1 + br 1b +1: + mov $names,r1 + mov $1,r0 +1: + clr bno + jsr pc,iget + tst (r1) + beq 1f +2: + jsr pc,rmblk + br start + mov $buf,r2 +3: + mov r1,r3 + mov r2,r4 + add $16.,r2 + tst (r4)+ + beq 5f +4: + cmpb (r3)+,(r4)+ + bne 5f + cmp r4,r2 + blo 4b + mov -16.(r2),r0 + add $14.,r1 + br 1b +5: + cmp r2,$buf+512. + blo 3b + br 2b +1: + clr r1 +1: + jsr pc,rmblk + br 1f + mov $buf,r2 +2: + mov (r2)+,(r1)+ + cmp r2,$buf+512. + blo 2b + br 1b +1: + clr r0 + cmp (r0),$407 + bne 2f +1: + mov 20(r0),(r0)+ + cmp r0,sp + blo 1b +2: + jsr pc,*$0 + br start + +iget: + add $31.,r0 + mov r0,r5 + ash $-4.,r0 + jsr pc,rblk + bic $!17,r5 + ash $5.,r5 + add $buf,r5 + mov $inod,r4 +1: + mov (r5)+,(r4)+ + cmp r4,$addr+16. + blo 1b + rts pc + +rmblk: + add $2,(sp) + mov bno,r0 + inc bno + bit $LRG,mode + bne 1f + asl r0 + mov addr(r0),r0 + bne rblk +2: + sub $2,(sp) + rts pc +1: + clr -(sp) + movb r0,(sp) + clrb r0 + swab r0 + asl r0 + mov addr(r0),r0 + beq 2b + jsr pc,rblk + mov (sp)+,r0 + asl r0 + mov buf(r0),r0 + beq 2b + +rblk: + mov r1,-(sp) + mov r0,r1 + clr r0 + jmp *rxblk + +rpda = 176724 +rpblk: + div $10.,r0 + mov r1,-(sp) + mov r0,r1 + clr r0 + div $20.,r0 + bisb r1,1(sp) + mov $rpda,r1 + mov (sp)+,(r1) + br 1f + +rkda = 177412 +rkblk: + div $12.,r0 + ash $4.,r0 + bis r1,r0 + mov $rkda+2,r1 + +1: + mov r0,-(r1) + mov $buf,-(r1) + mov $-256.,-(r1) + mov $5,-(r1) +1: + tstb (r1) + bge 1b + mov (sp)+,r1 + rts pc + +tks = 177560 +tkb = 177562 +getc: + mov $tks,r0 + inc (r0) +1: + tstb (r0) + bge 1b + mov tkb,r0 + bic $!177,r0 + cmp r0,$'A + blo 1f + cmp r0,$'Z + bhi 1f + add $40,r0 +1: + cmp r0,$'\r + bne putc + mov $'\n,r0 + +tps = 177564 +tpb = 177566 +putc: + tstb tps + bge putc + cmp r0,$'\n + bne 1f + mov $'\r,r0 + jsr pc,putc + mov $'\n+200,r0 + jsr pc,putc + clr r0 + jsr pc,putc + mov $'\n,r0 + rts pc +1: + mov r0,tpb + rts pc + +end: +inod = ..-1024. +mode = inod +addr = inod+8. +buf = inod+32. +bno = buf+514. +rxblk = bno+2 +names = rxblk+2 +LRG = 10000 +reset = 5 diff --git a/source/mdec/whp.s b/source/mdec/whp.s new file mode 100644 index 0000000..d4c986f --- /dev/null +++ b/source/mdec/whp.s @@ -0,0 +1,5 @@ +/ hpwrite + +wblk: + +iocom = 61 diff --git a/source/mdec/wrk.s b/source/mdec/wrk.s new file mode 100644 index 0000000..885256a --- /dev/null +++ b/source/mdec/wrk.s @@ -0,0 +1,4 @@ +/ write rk + +wblk: +iocom = 3 diff --git a/source/mdec/wrp.s b/source/mdec/wrp.s new file mode 100644 index 0000000..06e851f --- /dev/null +++ b/source/mdec/wrp.s @@ -0,0 +1,4 @@ +/ write rp + +wblk: +iocom = 3 diff --git a/source/rat/lex.c b/source/rat/lex.c new file mode 100644 index 0000000..4da5ece --- /dev/null +++ b/source/rat/lex.c @@ -0,0 +1,281 @@ +# include "r.h" + +char *keyword []{ + "do", "DO", /* have to be first */ + "if", "IF", + "else", "ELSE", + "for", "FOR", + "repeat", "REPEAT", + "until", "UNTIL", + "while", "WHILE", + "break", "BREAK", + "next", "NEXT", + "define", "DEFINE", + "include", "INCLUDE", + 0}; + +#include "y.tab.c" + +int keytran[]{ + 0, 0, + XIF, XIF, + XELSE, XELSE, + XFOR, XFOR, + REPEAT, REPEAT, + UNTIL, UNTIL, + XWHILE, XWHILE, + XBREAK, XBREAK, + NEXT, NEXT, + XDEFINE, XDEFINE, + XINCLUDE, XINCLUDE, + 0}; + +int svargc; +char **svargv; +int infile 0; +int fd 0; +int ninclude 0; +int filestack[10]; +int linect[10]; + +main(argc,argv) int argc; char **argv; { + contfld = errorflag = 0; + if(argc>1 && argv[1][0]=='-'){ + if(argv[1][1]=='6') + contfld=6; + argc--; + argv++; + } + svargc = argc; + svargv = argv; + filestack[0] = infile = fd = ninclude = linect[0] = 0; + if(--svargc>0) + if( (fd = filestack[0] = copen(svargv[++infile],'r')) < 0 ) { + error("can't open %s", svargv[infile]); + cexit(1); + } + yyparse(); + cexit(errorflag); +} + +int peek -1; +int nextchar '\n'; + +getc(){ + nextchar = (peek<0) ? gchar(): peek; + peek = -1; + return(nextchar); +} + +int gcp 0; +char gcbuf[300]; +int apos -1; + +gchar(){ + extern int linect[], nnames; + extern char *names[], *nameptr[]; + int c,i,atype,t; + if( c=gcbuf[gcp++] ) + return(c); + loop: + for(gcp=0; (c=gcbuf[gcp]=cgetc(fd))!='\0' ; gcp++ ){ + if( gcbuf[0]== '%' ){ + while(putchar(cgetc(fd))!='\n'); + gcp = -1; + ++linect[ninclude]; + continue; + } + if( (atype=alphanum(c)) && apos < 0 ){ + apos = gcp; + continue; + } + if( !atype ) + if( apos >= 0 ){ + gcbuf[gcp] = '\0'; + if( nnames>0 && (t=lookup(&gcbuf[apos],names))>=0){ + for(i=0;gcbuf[apos++]=nameptr[t][i];i++); + gcp = apos-1; + } + apos = -1; + gcbuf[gcp] = c; + } + if( c < ' ' && (c!='\n' && c!='\t') ) /* strip crap */ + c = gcbuf[gcp] = ' '; + if( c=='#' ){ + gcbuf[gcp] = '\n'; + while( (c=cgetc(fd))!='\n' && c!='\0'); + } + if( c=='"' || c=='\'' ){ + while( (gcbuf[++gcp]=t=cgetc(fd)) != c ) + if( t=='\n' ) { + error("unbalanced quote"); + gcbuf[gcp] = c; + gcbuf[++gcp] = c = '\n'; + goto newline; + } + continue; + } + newline: + if( c=='\n' ){ + gcbuf[gcp+1] = '\0'; + gcp = 1; + ++linect[ninclude]; + return(gcbuf[0]); + } + } + if(ninclude){ + cclose(filestack[ninclude--]); + fd = filestack[ninclude]; + goto loop; + } + cclose(filestack[ninclude]); + if(--svargc>0){ + if( (fd = filestack[ninclude] = copen(svargv[++infile],'r')) < 0) { + error("can't open %s", svargv[infile]); + cexit(1); + } + linect[0] = 0; + goto loop; + } + return(0); +} + +inclstat(){ + int i,c; + char fname[100]; + while( (c=getc())==' ' || c=='\t' ); + peek = c; + for(i=0; (fname[i]=c=getc())!='\n' && c!=';' && c!=' ' && c!='\t'; i++); + fname[i] = '\0'; + if( (fd = copen(fname,'r')) < 0 ) { + error("can't open %s", fname); + cexit(1); + } + else { + filestack[++ninclude] = fd; + linect[ninclude] = 0; + } +} + +lookup(string,tbl) char *string; char *tbl[]; { + register i,j, r; + for(i=0; tbl[i]!=0; i++){ + for( j=0; (r=tbl[i][j])==string[j] && r!='\0'; j++); + if( r == string[j] ) + return(i); + } + return( -1 ); +} + +char str[200]; +int strp; +int nstr; + +yylex(){ + int c, type; + top: + while( (c=getc())==' ' || c=='\n' || c=='\t' ); + yylval = c; + switch(c){ + + case '\0': + return('\0'); + case ';': + return(SCOL); + case'{': + return(LCURL); + case '}': + return(RCURL); + } + peek = c; + nstr = getstr(str); + yylval = &str[0]; + if( alldigits(str) ) + return(DIGITS); + type = lookup(str,keyword); + if( keytran[type]==XDEFINE ) { + defstat(); + goto top; + } else if( keytran[type]==XINCLUDE ) { + inclstat(); + goto top; + } else if( type > 1 ) + return(keytran[type]); + else if( type < 0 ) + return(XGOK); + while( (c=getc())==' ' || c=='\t' || c=='\n' ); + peek = c; + if( c>='a' && c<='z' || c>='A' && c<='Z' ) + return(NEWDO); + else + return(OLDDO); +} + +getstr(s) char *s; { + int c, sp; + for (sp=0; (c=s[sp++]=getc())!=' ' && c!='\t' && c!='\n' && c!='{' && c!='}' + && c!=';' && c!='(' && c!=')' ; ) + if( c=='\'' || c=='"' ) + while( (s[sp++]=getc())!=c ); + peek = c; + s[--sp]='\0'; + return(sp); +} + +alldigits(s) char *s; { + int c; + if( *s == '\0' ) + return(0); + while( (c = *s++) != '\0' ) + if( c<'0' || c>'9' ) + return(0); + return(1); +} + +int dbg 0; + +yyerror(){;} + +alphanum(c) int c; { + if(c>='0' && c<='9') return(1); + if(c>='a' && c<='z') return(1); + if(c>='A' && c<='Z') return(1); + return(0); +} + +#define MAXNAMES 100 + +char *names[MAXNAMES]; +char *nameptr[MAXNAMES]; +int nnames 0; + +defstat(){ + int c,i,index; + extern int peek,nstr; + extern char str[]; + char *getvec(); + while( (c=getc())==' ' || c=='\t' ); + peek = c; + for(nstr=0; c=getc(); nstr++ ){ + if(c==' ' || c=='\t' || c=='\n') break; + str[nstr] = c; + } + peek = c; + str[nstr] = '\0'; + if( (index=lookup(str,names)) >= 0 ) + nameptr[index] = 0; + else if( (index = nnames++)>=MAXNAMES-1 ){ + error("too many defined names"); + cexit(1); + } + names[index] = getvec(nstr+1); + for( i=0; names[index][i]=str[i]; i++ ); + while( (c=getc())==' ' || c=='\t' ); + peek = c; + for( i=0; (c=getc())!='\n' && c!='\0'; i++ ) + str[i] = c; + str[i] = '\0'; + nameptr[index] = getvec(i+1); + for( i=0; nameptr[index][i]=str[i]; i++ ); +} + diff --git a/source/rat/r.g b/source/rat/r.g new file mode 100644 index 0000000..e6142f4 --- /dev/null +++ b/source/rat/r.g @@ -0,0 +1,40 @@ +%term LCURL RCURL LPAR RPAR SCOL DIGITS +%term XIF XELSE XFOR XWHILE XBREAK NEXT +%term OLDDO NEWDO +%term XGOK XDEFINE XINCLUDE +%term REPEAT UNTIL +%% + +statl : statl stat + | + ; +stat : if stat ={ outcont($1); } + | ifelse stat ={ outcont($1+1); } + | while stat ={ whilestat($1); } + | for stat ={ forstat($1); } + | repeat stat UNTIL ={ untils($1); } + | XBREAK ={ breakcode($1); } + | NEXT ={ nextcode($1); } + | newdo stat ={ dostat($1); } + | OLDDO ={ docode(0,$1); } + | XGOK ={ gokcode($1); } + | SCOL + | LCURL statl RCURL + | label stat + | error ={ errcode($1); yyclearin; } + ; +label : DIGITS ={ outcode($1); outcode("\t"); } + ; +if : XIF ={ ifcode($1); } + ; +ifelse : if stat XELSE ={ outgoto($1+1); outcont($1); } + ; +while : XWHILE ={ whilecode($1); } + ; +for : XFOR ={ forcode($1); } + ; +repeat : REPEAT ={ repcode($1); } + ; +newdo : NEWDO ={ docode(1,$1); } + ; +%% diff --git a/source/rat/r.h b/source/rat/r.h new file mode 100644 index 0000000..388914c --- /dev/null +++ b/source/rat/r.h @@ -0,0 +1,8 @@ +# +extern int contfld; +extern int dbg; +extern int yyval; +extern int *yypv; +extern int yylval; +extern int peek; +extern int errorflag; diff --git a/source/rat/r1.c b/source/rat/r1.c new file mode 100644 index 0000000..b5abb00 --- /dev/null +++ b/source/rat/r1.c @@ -0,0 +1,259 @@ +#include "r.h" + +char scrat[500]; + +int brkptr -1; +int brkstk[10]; +int forptr 0; +int forstk[10]; + +repcode() { + outcont(0); + yyval = genlab(); + outcont(yyval); + brkstk[++brkptr] = yyval+1; + genlab(); + genlab(); +} + +untils(p1) int p1; { + outnum(p1+1); + outcode("\tif(.not."); + balpar(scrat); + outcode(scrat); + outcode(")"); + outgoto(p1); + outcont(p1+2); + brkptr--; +} + +ifcode(p1) int p1; { + outcode("\tif(.not."); + balpar(scrat); + outcode(scrat); + outcode(")"); + outgoto(yyval=genlab()); genlab(); +} + +whilecode(p1) int p1; { + outcont(0); + brkstk[++brkptr] = yyval = genlab(); genlab(); + outnum(yyval); + outcode("\tif(.not."); + balpar(scrat); + outcode(scrat); + outcode(")"); + outgoto(yyval+1); +} + +whilestat(p1) int p1; { + outgoto(p1); + outcont(p1+1); + brkptr--; +} + +balpar(bp) char *bp; { + int i, c, lpar; + extern int peek; + while( (c=getc()) == ' ' || c == '\t' || c=='\n' ); + peek = c; + if( c != '(' ){ + error("missing left paren"); + bp[0] = '\0'; + return(bp); + } + for( lpar=i=0; (bp[i++]=c=getc())!='\0'; ){ + if( c=='\'' || c=='"' ) + while( (bp[i++]=getc()) != c ); + if( i>=499 || c=='{' || c=='}' ){ + error("missing right parenthesis at %.20s", bp); + break; + } + if( c=='(' ) + lpar++; + else if( c==')' ) + lpar--; + if( lpar == 0 ) + break; + } + bp[i] = '\0'; + return(bp); +} + +int labval 23000; + +genlab(){ + return(++labval); +} + +gokcode(p1) char *p1; { + outcode("\t"); + outcode(p1); + eatup(p1,scrat); + outcode(scrat); + outcode(0); +} + +eatup(p1,bp) char *p1, *bp; { + extern int peek; + int i,c,lnb,lpar; + lnb = '\n'; + while( c = *p1++ ) + if( c!=' ' ) + lnb = c; + i = lpar = 0; + more: + for( ; (bp[i++]=c=getc())!=';' && c!='{' && c!='\n' && c!='}'; ){ + if( i>=499 ){ + error("statement too long at %.20s", bp); + break; + } + if( c != ' ' && c != '\t' ) + lnb = c; + if( c=='\'' || c=='"' ) + while( (bp[i++]=getc()) != c ); + if( c=='(' ) + lpar++; + else if( c==')' ) { + lpar--; + if( lpar < 0 ) + error("missing left paren at %.20s",bp); + } + } + if( c == '\n' ){ + if( lnb=='\n' || lnb=='+' || lnb=='-' || lnb=='*' || lnb=='(' + || lnb=='/' || lnb==',' || lnb=='&' || lnb=='|' + || lnb=='=' ) + goto more; + c = ';'; + } + if( c!=';' ) + peek = c; + bp[i-1] = '\0'; + if( lpar > 0 ) + error("missing right paren at %.20s",bp); + return(bp); +} + +forcode(){ + extern int peek; + int i,j,c; + char *bp, *getvec(); + outcont(0); + balpar(scrat); + yyval = genlab(); genlab(); genlab(); + brkstk[++brkptr] = yyval+1; + if( scrat[0] == '\0' ){ + forstk[forptr++] = bp = getvec(1); + *bp = '\0'; + return; + } + scrat[0] = '\t'; + for( i=1; (c=scrat[i++])!=';' && c!='\0' ; ) + if( c=='\'' || c=='"' ) + while( scrat[i++] != c ); + scrat[i-1] = '\0'; + if( nonblank(scrat) ){ + outcode(scrat); + outcode(0); + } + for( j=i; (c=scrat[i++])!=';' && c!='\0' ; ) + if( c=='\'' || c=='"' ) + while( scrat[i++] != c ); + scrat[i-1] = '\0'; + if( nonblank(&scrat[j]) ){ + outnum(yyval); + outcode("\tif(.not.("); + outcode(&scrat[j]); + outcode("))"); + outgoto(yyval+2); + } + else + outcont(yyval); + for( j=0; scrat[i+1]!='\0'; ) + scrat[j++] = scrat[i++]; + scrat[j] = '\0'; + forstk[forptr++] = bp = getvec(j+1); + for(i=0; *bp++ = scrat[i++]; ); +} + +forstat(p1) int p1; { + char *bp, *q; + int i; + bp = forstk[--forptr]; + outnum(p1+1); + if( nonblank(bp) ){ + outcode("\t"); + outcode(bp); + outcode(0); + } + outgoto(p1); + outcont(p1+2); + for( q=bp; *q++; ); + relvec(bp, q-bp); + brkptr--; +} + +docode(new,p1) int new; char *p1; { + outcode("\t"); + outcode(p1); + eatup(p1,scrat); + yyval = 0; + if(new){ + yyval = genlab(); genlab(); + brkstk[++brkptr] = yyval; + outnum(yyval); + } + outcode(scrat); + outcode(0); +} + +dostat(p1) int p1; { + if( p1==0 ) + return; + outcont(p1); + outcont(p1+1); + brkptr--; +} + +breakcode(p1) int p1; { + if(brkptr<0){ + error("illegal BREAK"); + return; + } + outgoto(brkstk[brkptr]+1); +} + +nextcode(p1) int p1; { + if(brkptr<0){ + error("illegal NEXT"); + return; + } + outgoto(brkstk[brkptr]); +} + +nonblank(s) char *s; { + int c; + while( c = *s++ ) + if( c!=' ' && c!='\t' && c!='\n' ) + return(1); + return(0); +} + +error(s1, s2) char *s1, *s2; { + extern int linect[],ninclude,infile; + printf( 2, "error at line %d, file %d: ",linect[ninclude],infile); + printf( 2, s1,s2); + printf( 2, "\n"); + errorflag = 1; +} + +errcode(p1) char *p1; { + int c; + extern int yychar; + extern int linect[],ninclude,infile; + printf( 2, "\nsyntax error, line %d, file %d\n", linect[ninclude],infile); + while( (c=getc()) != ';' && c != '}' && c != '\n' && c != '\0' ); + yychar = -1; + errorflag = 1; +} diff --git a/source/rat/r2.c b/source/rat/r2.c new file mode 100644 index 0000000..8b8030a --- /dev/null +++ b/source/rat/r2.c @@ -0,0 +1,124 @@ +#include "r.h" + +char outbuf[80]; +int outp 0; +int cont 0; + +outcode(p) char *p; { + int i,j,c,c1; + char *q; + if( p == 0 ){ + outbuf[outp] = '\0'; + printf("%s\n", outbuf); + outp = cont = 0; + return; + } + while( (c = *p++) ){ + c1 = *p; + switch(c){ + + case '"': + case '\'': + for( q=p; *q != c; q++ ); + outnum(q-p); + ptc('h'); + while( p != q ) + ptc(*p++); + p++; + break; + case '>': + if( c1=='=' ){ + pts(".ge."); p++; + } else + pts(".gt."); + break; + case '<': + if( c1=='=' ){ + pts(".le."); p++; + } else if( c1=='>' ){ + pts(".ne."); p++; + } else + pts(".lt."); + break; + case '=': + if( c1=='=' ){ + pts(".eq."); p++; + } else + ptc('='); + break; + case '!': + if( c1=='=' ){ + pts(".ne."); p++; + } else + pts(".not."); + break; + case '&': + if( c1=='&' ) + p++; + pts(".and."); + break; + case '|': + if( c1=='|' ) + p++; + pts(".or."); + break; + case '\t': + tabs(); + break; + case '\n': + ptc(' '); + break; + default: + ptc(c); + break; + } + } +} + +ptc(c) char c; { + if( outp > 71 ) + contcard(); + outbuf[outp++] = c; +} + +pts(s) char *s; { + while(*s) + ptc(*s++); +} + +int contfld 0; + +contcard(){ + outbuf[outp] = '\0'; + printf("%s\n", outbuf); + for( outp=0; outp 0 ) + outnum(n); + outcode("\tcontinue"); + outcode(0); +} + +outgoto(n) int n; { + outcode("\tgoto "); + outnum(n); + outcode(0); +} diff --git a/source/rat/run b/source/rat/run new file mode 100644 index 0000000..4a4fc9a --- /dev/null +++ b/source/rat/run @@ -0,0 +1,5 @@ +yacc r.g +cc -s -O r1.c r2.c lex.c -ly -lp +cmp a.out /usr/lib/ratfor +cp a.out /usr/lib/ratfor +rm *.o a.out y.tab.c diff --git a/source/run b/source/run new file mode 100644 index 0000000..15dbc58 --- /dev/null +++ b/source/run @@ -0,0 +1,20 @@ +chdir /usr/sys; pwd; time sh run + +chdir /usr/source/as; pwd; time sh run +chdir /usr/source/c; pwd; time sh run +chdir /usr/source/cref; pwd; time sh run +chdir /usr/source/fort; pwd; time sh run +chdir /usr/source/iolib; pwd; time sh run +chdir /usr/source/m6; pwd; time sh run +chdir /usr/source/mdec; pwd; time sh run +chdir /usr/source/rat; pwd; time sh run +chdir /usr/source/s1; pwd; time sh run +chdir /usr/source/s2; pwd; time sh run +chdir /usr/source/s3; pwd; time sh run +chdir /usr/source/s4; pwd; time sh run +chdir /usr/source/s5; pwd; time sh run +chdir /usr/source/s7; pwd; time sh run +chdir /usr/source/salloc; pwd; time sh run +chdir /usr/source/sno; pwd; time sh run +chdir /usr/source/tmg; pwd; time sh run +chdir /usr/source/yacc; pwd; time sh run diff --git a/source/s1/ac.c b/source/s1/ac.c new file mode 100644 index 0000000..c1aa0d1 --- /dev/null +++ b/source/s1/ac.c @@ -0,0 +1,285 @@ +# +/* + * acct [ -w wtmp ] [ -d ] [ -p people ] + */ + +#define TSIZE 30 +#define USIZE 200 + +struct { + char name[8]; + char tty; + char fill1; + float time; + int fill2; +} ibuf; + +struct ubuf { + char name[8]; + float utime; +} ubuf[USIZE]; + +struct tbuf { + struct ubuf *userp; + float ttime; +} tbuf[TSIZE]; + +char *wtmp; +int pflag, byday; +double dtime; +double midnight; +double lastime; +double day 1440.; +int pcount; +char **pptr; + +int montab[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +char *monasc[] { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" +}; + +main(argc, argv) +char **argv; +{ + int c, fl; + register i; + register char *ip; + extern fin; + int f; + + wtmp = "/usr/adm/wtmp"; + while (--argc > 0 && **++argv == '-') + switch(*++*argv) { + case 'd': + byday++; + continue; + + case 'w': + if (--argc>0) + wtmp = *++argv; + continue; + + case 'p': + pflag++; + continue; + } + pcount = argc; + pptr = argv; + if (fopen(wtmp, &fin) < 0) { + printf("No %s\n", wtmp); + return; + } + for(;;) { + ip = &ibuf; + for (i=0; i<16; i++) { + if ((c=getc(&fin)) < 0) + goto brk; + *ip++ = c; + } + fl = 0; + for (i=0; i<8; i++) { + c = ibuf.name[i]; + if ('0'<=c&&c<='9'||'a'<=c&&c<='z'||'A'<=c&&c<='Z') { + if (fl) + goto skip; + continue; + } + if (c==' ' || c=='\0') { + fl++; + ibuf.name[i] = '\0'; + } else + goto skip; + } + loop(); + skip:; + } + brk: + ibuf.name[0] = '\0'; + ibuf.tty = '~'; + time(&ibuf.time); + loop(); + print(); +} + +loop() +{ + double ltod(); + register i; + register struct tbuf *tp; + register struct ubuf *up; + + if (ibuf.fill1||ibuf.fill2) + return; + ibuf.time = ltod(&ibuf.time)/60.; + if(ibuf.tty == '|') { + dtime = ibuf.time; + return; + } + if(ibuf.tty == '}') { + if(dtime == 0.) + return; + for(tp = tbuf; tp < &tbuf[TSIZE]; tp++) + tp->ttime =+ ibuf.time-dtime; + dtime = 0.; + return; + } + if (lastime>ibuf.time || lastime+(1.5*day) midnight) { + upall(1); + print(); + newday(); + for (up=ubuf; up < &ubuf[USIZE]; up++) + up->utime = 0.0; + } + if (ibuf.tty == '~') { + ibuf.name[0] = '\0'; + upall(0); + return; + } + if ((i = ibuf.tty) >= 'a') + i =- 'a' - '9'; + i =- '0'; + if (i<0 || i>=TSIZE) + i = TSIZE-1; + tp = &tbuf[i]; + update(tp, 0); +} + +print() +{ + int i; + float ttime, t; + + ttime = 0.0; + for (i=0; i0.0) + ttime =+ t; + if (pflag && ubuf[i].utime > 0.0) { + printf("\t%-8.8s%6.2f\n", + ubuf[i].name, ubuf[i].utime/60.); + } + } + if (ttime > 0.0) { + pdate(); + printf("\ttotal%9.2f\n", ttime/60.); + } +} + +upall(f) +{ + register struct tbuf *tp; + + for (tp=tbuf; tp < &tbuf[TSIZE]; tp++) + update(tp, f); +} + +update(tp, f) +struct tbuf *tp; +{ + int i, j; + struct ubuf *up; + double t, t1; + + if (f) + t = midnight; + else + t = ibuf.time; + if (tp->userp) { + t1 = t - tp->ttime; + if (t1>0.0 && t1 < 1.5*day) + tp->userp->utime =+ t1; + } + tp->ttime = t; + if (f) + return; + if (ibuf.name[0]=='\0') { + tp->userp = 0; + return; + } + for (up=ubuf; up < &ubuf[USIZE]; up++) { + if (up->name[0] == '\0') + break; + for (j=0; j<8 && up->name[j]==ibuf.name[j]; j++); + if (j>=8) + break; + } + for (j=0; j<8; j++) + up->name[j] = ibuf.name[j]; + tp->userp = up; +} + +among(i) +{ + register j, k; + register char *p; + + if (pcount==0) + return(1); + for (j=0; j midnight) + break; + yrs++; + tim =+ year; + } + days = (midnight-tim-720.)/day; + montab[1] = 28; + if(yrs%4 == 0) + montab[1]++; + for (mons=0; montab[mons]<=days; mons++) + days =- montab[mons]; + mons =% 12; + printf("%s %2d", monasc[mons], days+1); +} diff --git a/source/s1/ar.s b/source/s1/ar.s new file mode 100644 index 0000000..a42e574 --- /dev/null +++ b/source/s1/ar.s @@ -0,0 +1,546 @@ +/ ar -- archive/library + + mov (sp)+,r0 + sub $2,r0 + ble userr + tst (sp)+ + mov (sp)+,r1 + clr r2 +1: + tstb (r1) + beq 1f + cmpb (r1),$'v + bne 2f + inc r1 + incb vflg + br 1b +2: + tst r2 + bne userr + movb (r1)+,r2 + br 1b +1: + tst r2 + beq userr + mov $arglst,r1 +1: + mov (sp)+,(r1)+ + dec r0 + bgt 1b + clr (r1)+ + mov $swlst,r1 +1: + cmp r2,(r1)+ + beq 1f + tst (r1)+ + bne 1b + br userr +1: + jmp *(r1) + +swlst: + 'r; comr + 'u; comu + 'd; comd + 'x; comx + 't; comt + 0; 0 + +userr: + jsr r5,diag + + .even + +putc: + movb r0,ch + mov $1,r0 + sys write; ch; 1 + rts r5 + +print: + movb (r1)+,r0 + beq 1f + jsr r5,putc + br print +1: + rts r5 + +diag: + mov r5,r1 + jsr r5,print + tst tfo + beq 1f + sys unlink; tfil +1: + sys exit + +getaf: + mov arglst,0f + sys open; 0:..; 0 + bes 1f + mov r0,afi + sys read; buf; 2 + cmp buf,magic + bne magerr + tst (r5)+ +1: + rts r5 + +magerr: + mov arglst,r1 + jsr r5,print + jsr r5,diag + < -- not in archive format\n\0> + .even + +mktmp: + sys stat; tfil; buf + bes 1f + incb tfil+8 + cmpb tfil+8,$'z + blo mktmp + br tferr +1: + sys signal; 2; 1 + ror r0 + bcs 1f + sys signal; 2; done +1: + sys creat; tfil; 600 + bes tferr + mov r0,tfo + sys open; tfil; 0 + bes tferr + mov r0,tfi + rts r5 + +tferr: + jsr r5,diag + + .even + +getdir: + mov afi,r0 + sys read; dir; 16. + cmp r0,$16. + bne 1f + jsr r5,mvname + tst (r5)+ +1: + rts r5 + +mvname: + mov name,rname + mov name+2,rname+2 + mov name+4,rname+4 + mov name+6,rname+6 + rts r5 + +skip: + mov size,r0 + inc r0 + bic $1,r0 + mov r0,0f + mov afi,r0 + sys seek; 0:..; 1 + rts r5 + +trim: + mov r0,r2 +1: + tstb (r0) + beq 1f + cmpb (r0)+,$'/ + beq trim + br 1b +1: + rts r5 + +match: + mov $arglst+2,r1 +1: + mov (r1)+,r0 + beq 1f + cmp r0,$-1 + beq 1b + jsr r5,trim + mov $name,r0 +2: + cmp r0,$name+8. + beq 2f + cmpb (r0),(r2)+ + bne 1b + tstb (r0)+ + bne 2b +2: + cmp (r5)+,-(r1) +1: + rts r5 + +mvfil: + mov (r1),9f + mov (r1),0f + sys stat; 0:..; buf + bes operr + sys open; 9:..; 0 + bes operr + mov r0,fio + mov (r1),r0 + mov $-1,(r1) + jsr r5,trim + mov $name,r0 +1: + cmp r0,$name+8. + beq 1f + movb (r2)+,(r0)+ + bne 1b +1: + mov buf+32.,mtim + mov buf+34.,mtim+2 + movb buf+7.,ouid + movb buf+4.,mode + mov buf+10.,size + mov tfo,r0 + sys write; dir; 16. + mov size,r2 +1: + mov fio,r0 + sys read; buf; 512. + sub r0,r2 + mov r0,0f + beq 1f + mov tfo,r0 + sys write; buf; 0:.. + br 1b +1: + tst r2 + bne phserr + bit $1,size + beq 1f + mov tfo,r0 + sys seek; 1; 1 +1: + mov fio,r0 + sys close + jsr r5,mvname + rts r5 + +operr: + mov 9b,r1 + jsr r5,print + jsr r5,diag + < -- cannot open\n\0> + .even + +phserr: + mov 9b,r1 + jsr r5,print + jsr r5,diag + < -- phase error\n\0> + .even + +copyfl: + mov tfo,r0 + sys write; dir; 16. + mov size,r1 + mov $rname,9b +1: + mov r1,0f + beq 1f + cmp r1,$512. + blo 2f + mov $512.,0f +2: + mov afi,r0 + sys read; buf; 0:.. + sub r0,r1 + mov r0,0f + beq phserr + mov tfo,r0 + sys write; buf; 0:.. + br 1b +1: + bit $1,size + beq 1f + mov afi,r0 + sys seek; 1; 1 + mov tfo,r0 + sys seek; 1; 1 +1: + rts r5 + +xtract: +/ movb mode,0f + sys creat; rname; 0:666 + bes noxerr + mov r0,fio + mov size,r1 + mov $rname,9b +1: + mov r1,0f + beq 1f + cmp r1,$512. + blo 2f + mov $512.,0f +2: + mov afi,r0 + sys read; buf; 0:.. + sub r0,r1 + mov r0,0f + beq phserr + mov fio,r0 + sys write; buf; 0:.. + br 1b +1: + mov fio,r0 + sys close + bit $1,size + beq 1f + mov afi,r0 + sys seek; 1; 1 +1: + mov r0,-(sp) + mov r1,-(sp) + mov mtim+2,r1 + mov mtim,r0 +/ sys mdate + mov (sp)+,r1 + mov (sp)+,r1 + rts r5 + +noxerr: + mov $rname,r1 + jsr r5,print + jsr r5,diag + < -- cannot create\n\0> + .even + +table: + mov $rname,r1 + jsr r5,print + mov $'\n,r0 + jsr r5,putc + rts r5 + +mesg: + mov r1,-(sp) + mov (r5)+,r0 + tstb vflg + beq 1f + jsr r5,putc + mov $' ,r0 + jsr r5,putc + mov $rname,r1 + jsr r5,print + mov $'\n,r0 + jsr r5,putc +1: + mov (sp)+,r1 + rts r5 + +oldnew: + sys stat; rname; buf + bes 1f + cmp buf+32.,mtim + blo 1f + bhi 2f + cmp buf+34.,mtim+2 + blos 1f +2: + tst (r5)+ + mov $rname,tname + mov $tname,r1 +1: + rts r5 + +comr: + jsr r5,mktmp + jsr r5,getaf + br copfl +1: + jsr r5,getdir + br copfl + jsr r5,match + br 2f + jsr r5,mesg; 'r + jsr r5,skip + jsr r5,mvfil + br 1b +2: + jsr r5,copyfl + jsr r5,mesg; 'c + br 1b + +comu: + jsr r5,mktmp + jsr r5,getaf + br noaf +1: + jsr r5,getdir + br copfl + tst arglst+2 + beq 2f + jsr r5,match + br 3f + mov $-1,(r1) +2: + jsr r5,oldnew + br 3f + jsr r5,mesg; 'r + jsr r5,skip + jsr r5,mvfil + br 1b +3: + jsr r5,copyfl + jsr r5,mesg; 'c + br 1b + +comd: + jsr r5,mktmp + jsr r5,getaf + br noaf +1: + jsr r5,getdir + br 1f + jsr r5,match + br 2f + mov $-1,(r1) + jsr r5,skip + jsr r5,mesg; 'd + br 1b +2: + jsr r5,copyfl + jsr r5,mesg; 'c + br 1b +1: + jsr r5,nfound + br copfl + +noaf: + jsr r5,diag + + .even + +crterr: + jsr r5,diag + + .even + +copfl: + mov $arglst,r1 + mov (r1)+,0f +1: + tst (r1)+ + beq 1f + cmp -2(r1),$-1 + beq 1b + tst -(r1) + jsr r5,mvfil + jsr r5,mesg; 'a + br 1b +1: + sys signal; 2; 1 / no interrupts during copy back + sys creat; 0:..; 666 + bes crterr + mov r0,afo + sys write; magic; 2 +1: + mov tfi,r0 + sys read; buf; 512. + mov r0,0f + beq done + mov afo,r0 + sys write; buf; 0:.. + br 1b + +done: + jsr r5,diag + <\0> + .even + +comx: + jsr r5,getaf + br noaf +1: + jsr r5,getdir + br 1f + tst arglst+2 + beq 3f + jsr r5,match + br 2f + mov $-1,(r1) +3: + jsr r5,xtract + jsr r5,mesg; 'x + br 1b +2: + jsr r5,skip + br 1b +1: + jsr r5,nfound + br done + +comt: + jsr r5,getaf + br noaf +1: + jsr r5,getdir + br 1f + tst arglst+2 + beq 2f + jsr r5,match + br 3f + mov $-1,(r1) +2: + jsr r5,table +3: + jsr r5,skip + br 1b +1: + jsr r5,nfound + br done + +nfound: + mov $arglst+2,r2 +1: + mov (r2)+,r1 + beq 1f + cmp r1,$-1 + beq 1b + mov $-1,-(r2) + jsr r5,print + mov $notfnd,r1 + jsr r5,print + br 1b +1: + rts r5 + +notfnd: + < -- not found\n\0> + .even + +tfil: + .even +magic: -147. + + .bss + +afi: .=.+2 +afo: .=.+2 +tfi: .=.+2 +tfo: .=.+2 +fio: .=.+2 +rname: .=.+9. +ch: .=.+1 +vflg: .=.+1 + .even +tname: .=.+2 +dir: + name: .=.+8. + mtim: .=.+4 + ouid: .=.+1 + mode: .=.+1 + size: .=.+2 +arglst: .=.+200. +buf: .=.+512. + diff --git a/source/s1/banner.c b/source/s1/banner.c new file mode 100644 index 0000000..0fb1bef --- /dev/null +++ b/source/s1/banner.c @@ -0,0 +1,132 @@ +#define nchars 64 /*number of chars in char set*/ +#define nlines 6 /*number of lines in a banner character*/ +#define pposs 85 /*number of print positions on a line (must be multiple of 4)*/ + /*followed by end of string character*/ +#define pospch 8 /*number of char positions per banner char*/ +#define chpln 10 /*number of banner characters per line*/ + +struct bann{ + char alpha[nlines][pposs]; +}; +struct bann buffer,*bp buffer; +char ctbl[nchars][nlines]{ + 036,041,046,051,046,035, /*@*/ + 014,022,041,077,041,041, /*A*/ + 076,041,076,041,041,076, /*B*/ + 036,041,040,040,041,036, /*C*/ + 076,041,041,041,041,076, /*D*/ + 077,040,076,040,040,077, /*E*/ + 077,040,076,040,040,040, /*F*/ + 036,041,040,047,041,036, /*G*/ + 041,041,077,041,041,041, /*H*/ + 004,004,004,004,004,004, /*I*/ + 001,001,001,001,041,036, /*J*/ + 041,042,074,044,042,041, /*K*/ + 040,040,040,040,040,077, /*L*/ + 041,063,055,041,041,041, /*M*/ + 041,061,051,045,043,041, /*N*/ + 036,041,041,041,041,036, /*O*/ + 076,041,041,076,040,040, /*P*/ + 036,041,041,045,042,035, /*Q*/ + 076,041,041,076,042,041, /*R*/ + 036,040,036,001,041,036, /*S*/ + 037,004,004,004,004,004, /*T*/ + 041,041,041,041,041,036, /*U*/ + 041,041,041,041,022,014, /*V*/ + 041,041,041,055,063,041, /*W*/ + 041,022,014,014,022,041, /*X*/ + 021,012,004,004,004,004, /*Y*/ + 077,002,004,010,020,077, /*Z*/ + 016,010,010,010,010,016, /*[*/ + 040,020,010,004,002,001, /*\*/ + 034,004,004,004,004,034, /*]*/ + 004,012,000,000,000,000, /*^*/ + 000,000,000,000,000,077, /*_*/ + 000,000,000,000,000,000, /* */ + 010,010,010,010,000,010, /*!*/ + 022,022,000,000,000,000, /*"*/ + 022,077,022,022,077,022, /*#*/ + 036,054,036,015,055,036, /*$*/ + 001,062,064,013,023,040, /*%*/ + 014,022,014,024,042,035, /*&*/ + 010,010,000,000,000,000, /*'*/ + 004,010,010,010,010,004, /*(*/ + 010,004,004,004,004,010, /*)*/ + 000,022,014,014,022,000 /***/ +}; +char blank ' '; +char plot 'X'; +int msk 040; /*mask at sixth bit*/ + +main(argc,argp) +char **argp;int argc; +{ + int i; + + /*if invoked with no arguments, prints error comment; + if invoked with an argument, prints it in banner form. + */ + + if(argc<2){ + printf("missing argument\n"); + exit(); + } + banner(argp[1],bp); + banprt(bp); +} + +banner(s,bufp) +char *s;struct bann *bufp; +{ + char c,*p,*q,*r; + p=s; + r=bufp; + banset(blank,bufp); + + while((c= *s++)!=0){ + if((s-p)>chpln)return(s-p); + if(c>='`')c =- ' '; /*map lower to upper case*/ + if(c<' ')c='#'; + if(c>'?')c=- 0100; + q=ctbl[c]; + banfil(q,r); + r=+pospch; + } +} + +banfil(c,p) +char *c; +struct bann *p; +{ + int i,j; + for(i=0;ialpha[i][j] = plot; + } + } + return(0); +} + +banset(c,p) +char c; +struct bann *p; +{ + int i,j; + for(i=0;ialpha[i][j] = c; +} + +banprt(ptr) +struct bann *ptr; +{ + int i,j; + for(i=0;ialpha[i][pposs-1]='\0'; + for(j=pposs-2;j>=0;j--){ + if(ptr->alpha[i][j]!=blank)break; + ptr->alpha[i][j]='\0'; + } + printf("%s\n",ptr->alpha[i]); + } +} diff --git a/source/s1/bas.s b/source/s1/bas.s new file mode 100644 index 0000000..6cb8d71 --- /dev/null +++ b/source/s1/bas.s @@ -0,0 +1,2113 @@ +/ +/ + +/ bas0 -- basic + +scope = 1 +.globl main +.globl sin, cos, log, exp, atan, pow, sqrt +.globl rand, srand +.globl fptrap +.globl fopen, getc + +indir = 0 /for indirect sys calls. (not in as) +one = 40200 + +main: + mov $1,prfile /initial print file + sys signal; 4; fptrap + setd + sys time + mov r1,r0 + mov r0,randx + jsr pc,srand + sys signal; 2; intrup + mov sp,gsp + clr seeka + mov $'a,r1 +1: + movb r1,tmpf+8 + sys stat; tmpf; line + bes 1f + inc r1 + cmp r1,$'z + blos 1b + br 2f +1: + sys creat; tmpf; 600 + bes 2f + mov r0,tfo + sys open; tmpf; 0 + bec 1f +2: + mov $3f,r0 + jsr pc,print + sys exit +3: + ; .even +1: + mov r0,tfi + + mov gsp,sp + cmp (sp),$2 /is there a file argument + blt noarg + mov 4(sp),r0 + mov $argname,r1 +1: + movb (r0)+,(r1)+ + bne 1b +aftered: / after edit + mov $argname,r0 + jsr r5,fopen; iobuf + bes 1f +noarg: + jsr pc,isymtab + br loop +1: + mov $1f,r0 + jsr pc,print + br loop +1: + ; .even + +intrup: + sys signal; 2; intrup + mov $'\n,r0 + jsr r5,xputc + jsr r5,error + ; .even + +loop: + mov gsp,sp + clr lineno + jsr pc,rdline + mov $line,r3 +1: + movb (r3),r0 + jsr pc,digit + br 1f + jsr r5,atoi + cmp r0,$' / + beq 3f + cmp r0,$' /tab + bne 1f +3: + mov $lintab,r3 + mov r1,r0 + bgt 2f + jsr pc,serror +2: + cmp r0,(r3) + beq 2f + tst (r3) + beq 2f + add $6,r3 + br 2b +2: + cmp r3,$elintab-12. + blo 2f + jsr r5,error + ; .even +2: + mov r0,(r3)+ + mov seeka,(r3)+ + mov tfo,r0 + mov seeka,seekx + sys indir; sysseek + mov $line,r0 + jsr pc,size + inc r0 + add r0,seeka + mov r0,wlen + mov tfo,r0 + mov $line,wbuf + sys indir;syswrit + br loop +1: + mov $line,r3 + jsr pc,singstat + br loop + +nextc: + movb (r3)+,r0 + rts r5 + +size: + clr -(sp) +1: + inc (sp) + cmpb (r0),$'\n + beq 1f + cmpb (r0),$0 + beq 1f + inc r0 + br 1b +1: + mov (sp)+,r0 + rts pc + +rdline: / read input (file or tty) to carr. ret. + mov $line,r1 +1: + jsr r5,getc; iobuf + bes 2f + tst r0 + beq 2f + cmp r1,$line+99. + bhis 2f / bad check, but a check + movb r0,(r1)+ + cmpb r0,$'\n + bne 1b + clrb (r1) + rts pc +2: + mov fi,r0 + beq 1f + sys close + clr fi + br 1b +1: + jmp _done + +error: + tst fi + beq 1f + sys close + clr fi +1: + tst lineno + beq 1f + jsr pc,nextlin + br 1f + mov $line,r0 + jsr pc,print +1: + mov r5,r0 + jsr pc,print + jmp loop + +serror: + dec r3 + tst fi + beq 1f + sys close + clr fi +1: + mov $line,r1 +1: + cmp r1,r3 + bne 2f + mov $'_,r0 + jsr r5,xputc + mov $10,r0 + jsr r5,xputc +2: + movb (r1),r0 + jsr r5,xputc + cmpb (r1)+,$'\n + bne 1b + jmp loop + +print: + mov r0,wbuf + jsr pc,size + mov r0,wlen + mov prfile,r0 + sys indir; syswrit + rts pc + +digit: + cmp r0,$'0 + blo 1f + cmp r0,$'9 + bhi 1f + add $2,(sp) +1: + rts pc + +alpha: + cmp r0,$'a + blo 1f + cmp r0,$'z + bhi 1f + add $2,(sp) +1: + cmp r0,$'A + blo 1f + cmp r0,$'Z + bhi 1f + add $2,(sp) +1: + rts pc + +name: + mov $nameb,r1 + clr (r1) + clr 2(r1) +1: + cmp r1,$nameb+4 + bhis 2f + movb r0,(r1)+ +2: + movb (r3)+,r0 + jsr pc,alpha + br 2f + br 1b +2: + jsr pc,digit + br 2f + br 1b +2: + mov $resnam,r1 +1: + cmp nameb,(r1) + bne 2f + cmp nameb+2,2(r1) + bne 2f + sub $resnam,r1 + asr r1 + add $2,(sp) + rts pc +2: + add $4,r1 + cmp r1,$eresnam + blo 1b + mov $symtab,r1 +1: + tst (r1) + beq 1f + cmp nameb,(r1) + bne 2f + cmp nameb+2,2(r1) + bne 2f + rts pc +2: + add $14.,r1 + br 1b +1: + cmp r1,$esymtab-28. + blo 1f + jsr r5,error + ; .even +1: + mov nameb,(r1) + mov nameb+2,2(r1) + clr 4(r1) + clr 14.(r1) + rts pc + +skip: + cmp r0,$' / + beq 1f + cmp r0,$' / tab + bne 2f +1: + movb (r3)+,r0 + br skip +2: + rts pc + +xputc: +.if scope / for plotting + tstb drflg + beq 1f + jsr pc,drput + rts r5 +1: +.endif + mov r0,ch + mov $1,r0 + sys write; ch; 1 + rts r5 + +nextlin: + clr -(sp) + mov $lintab,r1 +1: + tst (r1) + beq 1f + cmp lineno,(r1) + bhi 2f + mov (sp),r0 + beq 3f + cmp (r0),(r1) + blos 2f +3: + mov r1,(sp) +2: + add $6,r1 + br 1b +1: + mov (sp)+,r1 + beq 1f + mov (r1)+,lineno + mov (r1)+,seekx + mov tfi,r0 + sys indir; sysseek + mov tfi,r0 + sys read; line; 100. + add $2,(sp) +1: + rts pc + +getloc: + mov $lintab,r1 +1: + tst (r1) + beq 1f + cmp r0,(r1) + beq 2f + add $6,r1 + br 1b +1: + jsr r5,error + +argname: +vt: +.even +pname: <\0\0\0\0\0\0> + .even + +resnam: + + + + + + / prompt is like print without \n (cr) + + + + + + + + + + + + / comment +.if scope / for plotting + + + +.endif +eresnam: + +symtnam: + + + + + + + + + + + +esymtnam: + +/ indirect sys calls: +sysseek: sys seek; seekx: 0; 0 +syswrit: sys write; wbuf: 0; wlen: 0 +sysread: sys read; rbuf: 0; rlen: 0 +sysopen: sys open; ofile: 0 ; omode: 0 +syscreat: sys creat; cfile: 0; cmode: 0 +.bss +drx: .=.+8 +dry: .=.+8 +drfo: .=.+2 +ch: .=.+2 +drflg: .=.+2 +randx: .=.+2 +gsp: .=.+2 +forp: .=.+2 +exprloc:.=.+2 +sstack: .=.+2 +sublev: .=.+2 +val: .=.+2 +splimit: .=.+2 / statement size limit +iflev: .=.+20. / nested if compile stack: 10 deep +ifp: .=.+2 / current pointer to iflev +line: .=.+100. +prfile: .=.+2 / output from _list or _save +tfi: .=.+2 / input file +func: .=.+2 / alternate functions, eg: _list or _save +seeka: .=.+2 / seek offset 1 +lineno: .=.+2 +nameb: .=.+4 +tfo: .=.+2 +symtab: .=.+2800.; esymtab: / symbol=7wds; symtab for 200 +space: .=.+8000.; espace: / code space +exline: .=.+1000.; eexline: / line execute space +lintab: .=.+1800.; elintab: / 3wds per statement = 300 stmts +stack: .=.+800.; estack: + +iobuf: fi: .=.+518. / should be aquired?? diff --git a/source/s1/bc.y b/source/s1/bc.y new file mode 100644 index 0000000..ff2ddc1 --- /dev/null +++ b/source/s1/bc.y @@ -0,0 +1,567 @@ +%right '=' +%left '+' '-' +%left '*' '/' '%' +%right '^' +%left UMINUS + +%term LETTER DIGIT SQRT _IF FFF EQ +%term _WHILE _FOR NE LE GE INCR DECR +%term _RETURN _BREAK _DEFINE BASE OBASE SCALE +%term EQPL EQMI EQMUL EQDIV EQREM EQEXP +%term _AUTO DOT +%term QSTR + +%{ +char cary[1000], *cp { cary }; +char string[1000], *str {string}; +int crs '0'; +int rcrs '0'; /* reset crs */ +int bindx 0; +int lev 0; +int bstack[10] { 0 }; +char *numb[15] { + " 0", " 1", " 2", " 3", " 4", " 5", + " 6", " 7", " 8", " 9", " 10", " 11", + " 12", " 13", " 14" }; +int *pre, *post; +%} +%% +start : + | start stat tail + = output( $2 ); + | start def dargs ')' '{' dlist slist '}' + ={ bundle( pre, $7, post ); + conout( $$, $2 ); + rcrs = crs; + output( "" ); + lev = bindx = 0; + } + ; + +dlist : tail + | dlist _AUTO dlets tail + ; + +stat : e + ={ bundle( $1, "ps." ); } + | + ={ bundle( "" ); } + | QSTR + ={ bundle("[",$1,"]P");} + | LETTER '=' e + ={ bundle( $3, "s", $1 ); } + | LETTER '[' e ']' '=' e + ={ bundle( $6, $3, ":", geta($1)); } + | LETTER EQOP e + ={ bundle( "l", $1, $3, $2, "s", $1 ); } + | LETTER '[' e ']' EQOP e + ={ bundle($3, ";", geta($1), $6, $5, $3, ":", geta($1));} + | _BREAK + ={ bundle( numb[lev-bstack[bindx-1]], "Q" ); } + | _RETURN '(' e ')' + = bundle( $3, post, numb[lev], "Q" ); + | _RETURN '(' ')' + = bundle( "0", post, numb[lev], "Q" ); + | SCALE e + = bundle( $2, "k" ); + | SCALE '=' e + = bundle( $3, "k"); + | SCALE EQOP e + = bundle("K",$3,$2,"k"); + | BASE e + = bundle( $2, "i" ); + | BASE '=' e + = bundle($3, "i"); + | BASE EQOP e + = bundle("I",$3,$2,"i"); + | OBASE e + = bundle( $2, "o" ); + | OBASE '=' e + = bundle($3,"o"); + | OBASE EQOP e + = bundle("O",$3,$2,"o"); + | '{' slist '}' + ={ $$ = $2; } + | FFF + ={ bundle("f"); } + | error + ={ bundle("c"); } + | _IF CRS BLEV '(' re ')' stat + ={ conout( $7, $2 ); + bundle( $5, $2, " " ); + } + | _WHILE CRS '(' re ')' stat BLEV + ={ bundle( $6, $4, $2 ); + conout( $$, $2 ); + bundle( $4, $2, " " ); + } + | fprefix CRS re ';' e ')' stat BLEV + ={ bundle( $7, $5, "s.", $3, $2 ); + conout( $$, $2 ); + bundle( $1, "s.", $3, $2, " " ); + } + | '~' LETTER '=' e + ={ bundle($4,"S",$2); } + ; + +EQOP : EQPL + ={ $$ = "+"; } + | EQMI + ={ $$ = "-"; } + | EQMUL + ={ $$ = "*"; } + | EQDIV + ={ $$ = "/"; } + | EQREM + ={ $$ = "%%"; } + | EQEXP + ={ $$ = "^"; } + ; + +fprefix : _FOR '(' e ';' + ={ $$ = $3; } + ; + +BLEV : + ={ --bindx; } + ; + +slist : stat + | slist tail stat + ={ bundle( $1, $3 ); } + ; + +tail : '\n' + | ';' + ; + +re : e EQ e + = bundle( $1, $3, "=" ); + | e '<' e + = bundle( $1, $3, ">" ); + | e '>' e + = bundle( $1, $3, "<" ); + | e NE e + = bundle( $1, $3, "!=" ); + | e GE e + = bundle( $1, $3, "!>" ); + | e LE e + = bundle( $1, $3, "!<" ); + | e + = bundle( $1, " 0!=" ); + ; + +e : e '+' e + = bundle( $1, $3, "+" ); + | e '-' e + = bundle( $1, $3, "-" ); + | '-' e %prec UMINUS + = bundle( " 0", $2, "-" ); + | e '*' e + = bundle( $1, $3, "*" ); + | e '/' e + = bundle( $1, $3, "/" ); + | e '%' e + = bundle( $1, $3, "%%" ); + | e '^' e + = bundle( $1, $3, "^" ); + | LETTER '[' e ']' + ={ bundle($3, ";", geta($1)); } + | LETTER INCR + = bundle( "l", $1, "d1+s", $1 ); + | INCR LETTER + = bundle( "l", $2, "1+ds", $2 ); + | DECR LETTER + = bundle( "l", $2, "1-ds", $2 ); + | LETTER DECR + = bundle( "l", $1, "d1-s", $1 ); + | LETTER '[' e ']' INCR + = bundle($3,";",geta($1),"d1+",$3,":",geta($1)); + | INCR LETTER '[' e ']' + = bundle($4,";",geta($2),"1+d",$4,":",geta($2)); + | LETTER '[' e ']' DECR + = bundle($3,";",geta($1),"d1-",$3,":",geta($1)); + | DECR LETTER '[' e ']' + = bundle($4,";",geta($2),"1-d",$4,":",geta($2)); + | SCALE INCR + = bundle("Kd1+k"); + | INCR SCALE + = bundle("K1+dk"); + | SCALE DECR + = bundle("Kd1-k"); + | DECR SCALE + = bundle("K1-dk"); + | BASE INCR + = bundle("Id1+i"); + | INCR BASE + = bundle("I1+di"); + | BASE DECR + = bundle("Id1-i"); + | DECR BASE + = bundle("I1-di"); + | OBASE INCR + = bundle("Od1+o"); + | INCR OBASE + = bundle("O1+do"); + | OBASE DECR + = bundle("Od1-o"); + | DECR OBASE + = bundle("O1-do"); + | LETTER '(' cargs ')' + = bundle( $3, "l", getf($1), "x" ); + | LETTER '(' ')' + = bundle( "l", getf($1), "x" ); + | cons + ={ bundle( " ", $1 ); } + | DOT cons + ={ bundle( " .", $2 ); } + | cons DOT cons + ={ bundle( " ", $1, ".", $3 ); } + | cons DOT + ={ bundle( " ", $1, "." ); } + | DOT + ={ $$ = "l."; } + | LETTER + = { bundle( "l", $1 ); } + | LETTER '=' e + ={ bundle( $3, "ds", $1 ); } + | LETTER EQOP e %prec '=' + ={ bundle( "l", $1, $3, $2, "ds", $1 ); } + | '(' e ')' + = { $$ = $2; } + | '?' + ={ bundle( "?" ); } + | SQRT '(' e ')' + ={ bundle( $3, "v" ); } + | '~' LETTER + ={ bundle("L",$2); } + | SCALE e + = bundle($2,"dk"); + | SCALE '=' e + = bundle($3,"dk"); + | SCALE EQOP e %prec '=' + = bundle("K",$3,$2,"dk"); + | BASE e + = bundle($2,"di"); + | BASE '=' e + = bundle($3,"di"); + | BASE EQOP e %prec '=' + = bundle("I",$3,$2,"di"); + | OBASE e + = bundle($2,"do"); + | OBASE '=' e + = bundle($3,"do"); + | OBASE EQOP e %prec '=' + = bundle("O",$3,$2,"do"); + | SCALE + = bundle("K"); + | BASE + = bundle("I"); + | OBASE + = bundle("O"); + ; + +cargs : eora + | cargs ',' eora + = bundle( $1, $3 ); + ; +eora: e + | LETTER '[' ']' + =bundle("l",geta($1)); + ; + +cons : constant + ={ *cp++ = '\0'; } + +constant: + '_' + ={ $$ = cp; *cp++ = '_'; } + | DIGIT + ={ $$ = cp; *cp++ = $1; } + | constant DIGIT + ={ *cp++ = $2; } + ; + +CRS : + ={ $$ = cp; *cp++ = crs++; *cp++ = '\0'; bstack[bindx++] = lev++; } + ; + +def : _DEFINE LETTER '(' + ={ $$ = getf($2); + pre = ""; + post = ""; + lev = 1; + bstack[bindx=0] = 0; + } + ; + +dargs : + | lora + ={ pp( $1 ); } + | dargs ',' lora + ={ pp( $3 ); } + ; + +dlets : lora + ={ tp($1); } + | dlets ',' lora + ={ tp($3); } + ; +lora : LETTER + | LETTER '[' ']' + ={ $$ = geta($1); } + ; + +%% +# define error 256 + +int peekc -1; +int sargc; +int ifile; +char **sargv; +extern int fin; + +char *funtab[26]{ + 01,02,03,04,05,06,07,010,011,012,013,014,015,016,017, + 020,021,022,023,024,025,026,027,030,031,032 }; +char *atab[26]{ + 0241,0242,0243,0244,0245,0246,0247,0250,0251,0252,0253, + 0254,0255,0256,0257,0260,0261,0262,0263,0264,0265,0266, + 0267,0270,0271,0272}; +char *letr[26] { + "a","b","c","d","e","f","g","h","i","j", + "k","l","m","n","o","p","q","r","s","t", + "u","v","w","x","y","z" } ; +char *dot { "." }; +yylex(){ + int c,ch; +restart: + c = getc(); + peekc = -1; + while( c == ' ' || c == '\t' ) c = getc(); + if( c<= 'z' && c >= 'a' ) { + /* look ahead to look for reserved words */ + peekc = getc(); + if( peekc >= 'a' && peekc <= 'z' ){ /* must be reserved word */ + if( c=='i' && peekc=='f' ){ c=_IF; goto skip; } + if( c=='w' && peekc=='h' ){ c=_WHILE; goto skip; } + if( c=='f' && peekc=='o' ){ c=_FOR; goto skip; } + if( c=='s' && peekc=='q' ){ c=SQRT; goto skip; } + if( c=='r' && peekc=='e' ){ c=_RETURN; goto skip; } + if( c=='b' && peekc=='r' ){ c=_BREAK; goto skip; } + if( c=='d' && peekc=='e' ){ c=_DEFINE; goto skip; } + if( c=='s' && peekc=='c' ){ c= SCALE; goto skip; } + if( c=='b' && peekc=='a' ){ c=BASE; goto skip; } + if( c=='o' && peekc=='b' ){ c=OBASE; goto skip; } + if( c=='d' && peekc=='i' ){ c=FFF; goto skip; } + if( c=='a' && peekc=='u' ){ c=_AUTO; goto skip; } + if( c == 'q' && peekc == 'u')getout(); + /* could not be found */ + return( error ); + skip: /* skip over rest of word */ + peekc = -1; + while( (ch = getc()) >= 'a' && ch <= 'z' ); + peekc = ch; + return( c ); + } + + /* usual case; just one single letter */ + + yylval = letr[c-'a']; + return( LETTER ); + } + if( c>= '0' && c <= '9' || c>= 'A' && c<= 'F' ){ + yylval = c; + return( DIGIT ); + } + switch( c ){ + case '.': return( DOT ); + case '=': + switch( peekc = getc() ){ + case '=': c=EQ; goto gotit; + case '+': c=EQPL; goto gotit; + case '-': c=EQMI; goto gotit; + case '*': c=EQMUL; goto gotit; + case '/': c=EQDIV; goto gotit; + case '%': c=EQREM; goto gotit; + case '^': c=EQEXP; goto gotit; + default: return( '=' ); + gotit: peekc = -1; return(c); + } + case '+': return( cpeek( '+', INCR, '+' ) ); + case '-': return( cpeek( '-', DECR, '-' ) ); + case '<': return( cpeek( '=', LE, '<' ) ); + case '>': return( cpeek( '=', GE, '>' ) ); + case '!': return( cpeek( '=', NE, '!' ) ); + case '/': + if((peekc = getc()) == '*'){ + peekc = -1; + while((getc() != '*') || ((peekc = getc()) != '/')); + peekc = -1; + goto restart; + } + else return(c); + case '"': + yylval = str; + while((c=getc()) != '"')*str++ = c; + *str++ = '\0'; + return(QSTR); + default: return( c ); + } + } + +cpeek( c, yes, no ){ + if( (peekc=getc()) != c ) return( no ); + else { + peekc = -1; + return( yes ); + } + } + +getc(){ + int ch; +loop: + ch = (peekc < 0) ? getchar() : peekc; + peekc = -1; + if(ch != '\0')return(ch); + if(++ifile > sargc){ + if(ifile >= sargc+2)getout(); + fin = dup(0); + goto loop; + } +close(fin); + if((fin = open(sargv[ifile],0)) >= 0)goto loop; + yyerror("cannot open input file"); +} +# define b_sp_max 1500 +int b_space [ b_sp_max ]; +int * b_sp_nxt { b_space }; + +bdebug 0; +bundle(a){ + int i, *p, *q; + + i = nargs(); + q = b_sp_nxt; + + if( bdebug ) printf("bundle %d elements at %o\n", i, q ); + + for( p = &a; i-->0; ++p ){ + + if( b_sp_nxt >= & b_space[b_sp_max] ) yyerror( "bundling space exceeded" ); + + * b_sp_nxt++ = *p; + } + * b_sp_nxt++ = 0; + yyval = q; + return( q ); + } + +routput(p) int *p; { + if( bdebug ) printf("routput(%o)\n", p ); + if( p >= &b_space[0] && p < &b_space[b_sp_max]){ + /* part of a bundle */ + while( *p != 0 ) routput( *p++ ); + } + else printf( p ); /* character string */ + } + +output( p ) int *p; { + routput( p ); + b_sp_nxt = & b_space[0]; + printf( "\n" ); + cp = cary; + str = string; + crs = rcrs; + } + +conout( p, s ) int *p; char *s; { + printf("["); + routput( p ); + printf("]s%s\n", s ); + lev--; + str = string; + } + +yyerror( s ) char *s; { + printf("c[%s]pc\n", s ); + cp = cary; + crs = rcrs; + bindx = 0; + lev = 0; + b_sp_nxt = &b_space[0]; + str = string; + } + +pp( s ) char *s; { + /* puts the relevant stuff on pre and post for the letter s */ + + bundle( "S", s, pre ); + pre = yyval; + bundle( post, "L", s, "s." ); + post = yyval; + } + +tp( s ) char *s; { /* same as pp, but for temps */ + bundle( "0S", s, pre ); + pre = yyval; + bundle( post, "L", s, "s." ); + post = yyval; + } + +yyinit(argc,argv) int argc; char *argv[];{ + int (*getout)(); + signal( 2, getout ); /* ignore all interrupts */ + sargv=argv; + sargc= -- argc; + if(sargc == 0)fin=dup(0); + else if((fin = open(sargv[1],0)) < 0) + yyerror("cannot open input file"); + ifile = 1; + } +getout(){ +printf("q"); +exit(); +} + +getf(p) char *p;{ +return(&funtab[*p -0141]); +} +geta(p) char *p;{ + return(&atab[*p - 0141]); +} + +main(argc, argv) +char **argv; +{ + int p[2]; + + + if (argc > 1 && *argv[1] == '-') { + if(argv[1][1] == 'd'){ + yyinit(--argc, ++argv); + yyparse(); + exit(); + } + if(argv[1][1] != 'l'){ + printf("unrecognizable argument\n"); + exit(); + } + argv[1] = "/usr/lib/lib.b"; + } + pipe(p); + if (fork()==0) { + close(1); + dup(p[1]); + close(p[0]); + close(p[1]); + yyinit(argc, argv); + yyparse(); + exit(); + } + close(0); + dup(p[0]); + close(p[0]); + close(p[1]); + execl("/bin/dc", "dc", "-", 0); +} diff --git a/source/s1/bcd.c b/source/s1/bcd.c new file mode 100644 index 0000000..47f6f88 --- /dev/null +++ b/source/s1/bcd.c @@ -0,0 +1,133 @@ +int chtab[]{ +00000, /* */ +03004, /* ! */ +02404, /* " */ +02040, /* sharp */ +02042, /* $ */ +02104, /* % */ +00001, /* & */ +03002, /* ' */ +02201, /* ( */ +02202, /* ) */ +02102, /* * */ +00005, /* + */ +02044, /* , */ +00002, /* - */ +02041, /* . */ +00014, /* / */ +00004, /* 0 */ +00010, /* 1 */ +00020, /* 2 */ +00040, /* 3 */ +00100, /* 4 */ +00200, /* 5 */ +00400, /* 6 */ +01000, /* 7 */ +02000, /* 8 */ +04000, /* 9 */ +02200, /* : */ +02402, /* ; */ +02401, /* < */ +02204, /* = */ +02400, /* > */ +03000, /* ? */ +02100, /* at */ + 011, + 021, + 041, +0101, +0201, +0401, +01001, +02001, +04001, +012, +022, +042, +0102, +0202, +0402, +01002, +02002, +02002, +024, +044, +0104, +0204, +0404, +01004, +02004, +04004, +02020, /* [ */ +03001, /* \ */ +02101, /* ] */ +00006, /* ^ */ +02024 /* _ */ +}; + char s[128]; + char *sp {&s[0]}; +main(argc, argv) +char *argv[]; +{ + char *spp; + int i; + int j; + int c; + int l; + + if (argc<2) { + puts("% "); + while ((c=getchar())!='\0'&c!='\n') + *sp++ = c; + *sp = 0; + sp = &s[0]; + } else + sp = *++argv; + puts("\n\n\n\n"); + puts(" ________________________________"); + puts("________________\n"); + spp = sp; + while(*spp++); + spp--; + l = spp - sp; + putchar('/'); + puts(sp); + i = 49 - l; + while(--i>0) putchar(' '); + puts("|\n"); + j = 0; + spp = sp; + while (j++<12) { + putchar('|'); + i = 0; + spp = sp; + while (i<48) { + c = *spp++ - 040; + i++; + if (c>='a'-040) c = c - 040; + if (i>l) c = 0; + if (c<0 | c>137) c = 0; + if ((chtab[c]>>(j-1))&1) + puts("[]"); + else + putchar(j>3?'0'+j-3:' '); + } + puts("|\n"); + } + putchar('|'); + puts("____________"); + puts("____________________________________"); + puts("|\n"); + puts("\n\n\n\n"); +} + +puts(ss) char *ss; { + int i; + char t; + i = 0; + while(t = *ss++) { + if(t >= 'a' && t <= 'z') + t =+ 'A'-'a'; + putchar(t); + } +} diff --git a/source/s1/cal.c b/source/s1/cal.c new file mode 100644 index 0000000..f5753ed --- /dev/null +++ b/source/s1/cal.c @@ -0,0 +1,207 @@ +char dayw[] +{ + " S M Tu W Th F S" +}; +char *smon[] +{ + "Jan", "Feb", "Mar", "Apr", + "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec", +}; +char string[432]; +main(argc, argv) +char *argv[]; +{ + register y, i, j; + int m; + + if(argc < 2) { + printf("usage: cal [month] year\n"); + exit(); + } + if(argc == 2) + goto xlong; + +/* + * print out just month + */ + + m = number(argv[1]); + if(m<1 || m>12) + goto badarg; + y = number(argv[2]); + if(y<1 || y>9999) + goto badarg; + printf(" %s %l\n", smon[m-1], y); + printf("%s\n", dayw); + cal(m, y, string, 24); + for(i=0; i<6*24; i=+24) + pstr(string+i, 24); + exit(); + +/* + * print out complete year + */ + +xlong: + y = number(argv[1]); + if(y<1 || y>9999) + goto badarg; + printf("\n\n\n"); + printf(" %l\n", y); + printf("\n"); + for(i=0; i<12; i=+3) { + for(j=0; j<6*72; j++) + string[j] = '\0'; + printf(" %s", smon[i]); + printf(" %s", smon[i+1]); + printf(" %s\n", smon[i+2]); + printf("%s %s %s\n", dayw, dayw, dayw); + cal(i+1, y, string, 72); + cal(i+2, y, string+23, 72); + cal(i+3, y, string+46, 72); + for(j=0; j<6*72; j=+72) + pstr(string+j, 72); + } + printf("\n\n\n"); + exit(); + +badarg: + printf("Bad argument\n"); +} + +number(str) +char *str; +{ + register n, c; + register char *s; + + n = 0; + s = str; + while(c = *s++) { + if(c<'0' || c>'9') + return(0); + n = n*10 + c-'0'; + } + return(n); +} + +pstr(str, n) +char *str; +{ + register i; + register char *s; + + s = str; + i = n; + while(i--) + if(*s++ == '\0') + s[-1] = ' '; + i = n+1; + while(i--) + if(*--s != ' ') + break; + s[1] = '\0'; + printf("%s\n", str); +} + +char mon[] +{ + 0, + 31, 29, 31, 30, + 31, 30, 31, 31, + 30, 31, 30, 31, +}; + +cal(m, y, p, w) +char *p; +{ + register d, i; + register char *s; + + s = p; + d = jan1(y); + mon[2] = 29; + mon[9] = 30; + + switch((jan1(y+1)+7-d)%7) { + + /* + * non-leap year + */ + case 1: + mon[2] = 28; + break; + + /* + * 1752 + */ + default: + mon[9] = 19; + break; + + /* + * leap year + */ + case 2: + ; + } + for(i=1; i 9) + *s = i/10+'0'; + s++; + *s++ = i%10+'0'; + s++; + if(++d == 7) { + d = 0; + s = p+w; + p = s; + } + } +} + +/* + * return day of the week + * of jan 1 of given year + */ + +jan1(yr) +{ + register y, d; + +/* + * normal gregorian calendar + * one extra day per four years + */ + + y = yr; + d = 4+y+(y+3)/4; + +/* + * julian calendar + * regular gregorian + * less three days per 400 + */ + + if(y > 1800) { + d =- (y-1701)/100; + d =+ (y-1601)/400; + } + +/* + * great calendar changeover instant + */ + + if(y > 1752) + d =+ 3; + + return(d%7); +} diff --git a/source/s1/cat.s b/source/s1/cat.s new file mode 100644 index 0000000..100e806 --- /dev/null +++ b/source/s1/cat.s @@ -0,0 +1,65 @@ +/ cat -- concatinate files + + mov (sp)+,r5 + tst (sp)+ + mov $obuf,r2 + cmp r5,$1 + beq 3f + +loop: + dec r5 + ble done + mov (sp)+,r0 + cmpb (r0),$'- + bne 2f + clr fin + br 3f +2: + mov r0,0f + sys open; 0:..; 0 + bes loop + mov r0,fin +3: + mov fin,r0 + sys read; ibuf; 512. + bes 3f + mov r0,r4 + beq 3f + mov $ibuf,r3 +4: + movb (r3)+,r0 + jsr pc,putc + dec r4 + bne 4b + br 3b +3: + mov fin,r0 + beq loop + sys close + br loop + +done: + sub $obuf,r2 + beq 1f + mov r2,0f + mov $1,r0 + sys write; obuf; 0:.. +1: + sys exit + +putc: + movb r0,(r2)+ + cmp r2,$obuf+512. + blo 1f + mov $1,r0 + sys write; obuf; 512. + mov $obuf,r2 +1: + rts pc + + .bss +ibuf: .=.+512. +obuf: .=.+512. +fin: .=.+2 + .text + diff --git a/source/s1/cc.c b/source/s1/cc.c new file mode 100644 index 0000000..930078f --- /dev/null +++ b/source/s1/cc.c @@ -0,0 +1,811 @@ +#define SBSIZE 2000 +char sbf[SBSIZE]; +/* C command */ + +char *tmp0; +char *tmp1; +char *tmp2; +char *tmp3; +char *tmp4; +char *tmp5; +char ts[1000]; +char *tsp ts; +char *av[50]; +char *clist[50]; +char *llist[50]; +int instring; +int pflag; +int sflag; +int cflag; +int oflag; +int proflag; +int depth; +int *ibuf; +int *ibuf1; +int *ibuf2; +int *obuf; +char *lp; +char *line; +int lineno; +int exfail; +struct symtab { + char name[8]; + char *value; +} *symtab; +int symsiz 200; +struct symtab *defloc; +struct symtab *incloc; +struct symtab *eifloc; +struct symtab *ifdloc; +struct symtab *ifnloc; +struct symtab *unxloc; +int trulvl; +int flslvl; +char *stringbuf; +char *pass0 "/lib/c0"; +char *pass1 "/lib/c1"; +char *pass2 "/lib/c2"; +char *pref "/lib/crt0.o"; + +main(argc, argv) +char *argv[]; { + char *t; + int nc, nl, i, j, c, f20, nxo; + int dexit(); + + i = nc = nl = f20 = nxo = 0; + while(++i < argc) { + if(*argv[i] == '-') + switch (argv[i][1]) { + default: + goto passa; + case 'S': + sflag++; + cflag++; + break; + case 'O': + oflag++; + break; + case 'p': + proflag++; + pref = "/lib/mcrt0.o"; + break; + case 'P': + pflag++; + case 'c': + cflag++; + break; + + case 'f': + pref = "/lib/fcrt0.o"; + pass0 = "/lib/fc0"; + pass1 = "/lib/fc1"; + break; + + case '2': + if(argv[i][2] == '\0') + pref = "/lib/crt2.o"; + else { + pref = "/lib/crt20.o"; + f20 = 1; + } + break; + case 't': + if (argv[i][2]=='0') + pass0 = "/usr/c/c0"; + if (argv[i][2]=='1') + pass1 = "/usr/c/c1"; + if (argv[i][2]=='2') + pass2 = "/usr/c/c2"; + break; + } + else { + passa: + t = argv[i]; + if(getsuf(t)=='c') { + clist[nc++] = t; + t = setsuf(t, 'o'); + } + if (nodup(llist, t)) { + llist[nl++] = t; + if (getsuf(t)=='o') + nxo++; + } + } + } + if(nc==0) + goto nocom; + if (pflag==0) { + tmp0 = copy("/tmp/ctm0a"); + while((c=open(tmp0, 0))>=0) { + close(c); + tmp0[9]++; + } + while((creat(tmp0, 0400))<0) + tmp0[9]++; + } + if ((signal(2, 1) & 01) == 0) + signal(2, &dexit); + (tmp1 = copy(tmp0))[8] = '1'; + (tmp2 = copy(tmp0))[8] = '2'; + (tmp3 = copy(tmp0))[8] = '3'; + if (oflag) + (tmp5 = copy(tmp0))[8] = '5'; + if (pflag==0) + (tmp4 = copy(tmp0))[8] = '4'; + for (i=0; i1) + printf("%s:\n", clist[i]); + av[0] = "c0"; + if (pflag) + tmp4 = setsuf(clist[i], 'i'); + av[1] = expand(clist[i]); + if (pflag || exfail) + continue; + if (av[1] == 0) { + cflag++; + continue; + } + av[2] = tmp1; + av[3] = tmp2; + if (proflag) { + av[4] = "-P"; + av[5] = 0; + } else + av[4] = 0; + if (callsys(pass0, av)) { + cflag++; + continue; + } + av[0] = "c1"; + av[1] = tmp1; + av[2] = tmp2; + if (sflag) + tmp3 = setsuf(clist[i], 's'); + av[3] = tmp3; + if (oflag) + av[3] = tmp5; + av[4] = 0; + if(callsys(pass1, av)) { + cflag++; + continue; + } + if (oflag) { + av[0] = "c2"; + av[1] = tmp5; + av[2] = tmp3; + av[3] = 0; + callsys(pass2, av); + unlink(tmp5); + } + if (sflag) + continue; + av[0] = "as"; + av[1] = "-"; + av[2] = tmp3; + av[3] = 0; + cunlink(tmp1); + cunlink(tmp2); + cunlink(tmp4); + callsys("/bin/as", av); + t = setsuf(clist[i], 'o'); + cunlink(t); + if(link("a.out", t) || cunlink("a.out")) { + printf("move failed: %s\n", t); + cflag++; + } + } +nocom: + if (cflag==0 && nl!=0) { + i = 0; + av[0] = "ld"; + av[1] = "-X"; + av[2] = pref; + j = 3; + while(i3) { + if (flslvl==0 &&(state+!lookup(namep,-1)->name[0])==5) + trulvl++; + else + flslvl++; + out: + while (c!='\n' && c!= '\0') + c = getch(); + return(c); + } + if (state!=2 || flslvl==0) + { + ungetc(c); + np = lookup(namep, state); + c = getch(); + } + if (state==1) { + if (np==defloc) + state = 2; + else if (np==incloc) + state = 3; + else if (np==ifnloc) + state = 4; + else if (np==ifdloc) + state = 5; + else if (np==eifloc) { + if (flslvl) + --flslvl; + else if (trulvl) + --trulvl; + else error("If-less endif"); + goto out; + } + else { + error("Undefined control"); + while (c!='\n' && c!='\0') + c = getch(); + return(c); + } + } else if (state==2) { + if (flslvl) + goto out; + np->value = stringbuf; + savch(c); + while ((c=getch())!='\n' && c!='\0') + savch(c); + savch('\0'); + return(1); + } + continue; + } else if ((sc=c)=='\'' || sc=='"') { + sch(sc); + filname = lp; + instring++; + while ((c=getch())!=sc && c!='\n' && c!='\0') { + sch(c); + if (c=='\\') + sch(getch()); + } + instring = 0; + if (flslvl) + goto out; + if (state==3) { + if (flslvl) + goto out; + *lp = '\0'; + while ((c=getch())!='\n' && c!='\0'); + if (ibuf==ibuf2) + error("Nested 'include'"); + if (fopen(filname, ibuf2)<0) + error("Missing file %s", filname); + else + ibuf = ibuf2; + return(c); + } + } + sch(c); + c = getch(); + } + sch('\0'); + if (state>1) + error("Control syntax"); + return(c); +} + +insym(sp, namep) +struct symtab **sp; +char *namep; +{ + register struct symtab *np; + + *sp = np = lookup(namep, 1); + np->value = np->name; +} + +error(s, x) +{ + printf("%d: ", lineno); + printf(s, x); + putchar('\n'); + exfail++; + cflag++; +} + +sch(c) +{ + register char *rlp; + + rlp = lp; + if (rlp==line+194) + error("Line overflow"); + *rlp++ = c; + if (rlp>line+195) + rlp = line+195; + lp = rlp; +} + +savch(c) +{ + *stringbuf++ = c; + if (stringbuf-sbf < SBSIZE) + return; + error("Too much defining"); + dexit(); +} + +getch() +{ + register int c; + +loop: + if ((c=getc1())=='/' && !instring) { + if ((c=getc1())!='*') + { + ungetc(c); + return('/'); + } + for(;;) { + c = getc1(); + cloop: + switch (c) { + + case '\0': + return('\0'); + + case '*': + if ((c=getc1())=='/') + goto loop; + goto cloop; + + case '\n': + if (ibuf==ibuf1) { + putc('\n', obuf); + lineno++; + } + continue; + } + } + } + return(c); +} +char pushbuff[300]; +char *pushp pushbuff; +ungetc(c) + { + *++pushp = c; + } + +getc1() +{ + register c; + + if (*pushp !=0) + return(*pushp--); + depth=0; + if ((c = getc(ibuf)) < 0 && ibuf==ibuf2) { + close(ibuf2[0]); + ibuf = ibuf1; + putc('\n', obuf); + lineno++; + c = getc1(); + } + if (c<0) + return(0); + return(c); +} + +lookup(namep, enterf) +char *namep; +{ + register char *np, *snp; + register struct symtab *sp; + int i, c, around; + np = namep; + around = i = 0; + while (c = *np++) + i =+ c; + i =% symsiz; + sp = &symtab[i]; + while (sp->name[0]) { + snp = sp; + np = namep; + while (*snp++ == *np) + if (*np++ == '\0' || np==namep+8) { + if (!enterf) + subst(namep, sp); + return(sp); + } + if (++sp >= &symtab[symsiz]) + if (around++) + { + error("too many defines"); + dexit(); + } + else + sp = symtab; + } + if (enterf>0) { + snp = namep; + for (np = &sp->name[0]; np < &sp->name[8];) + if (*np++ = *snp) + snp++; + } + return(sp); +} +char revbuff[200]; +char *bp; +backsch(c) + { + if (bp-revbuff > 200) + error("Excessive define looping", bp--); + *bp++ = c; + } + +subst(np, sp) +char *np; +struct symtab *sp; +{ + register char *vp; + + lp = np; + bp = revbuff; + if (depth++>100) + { + error("define recursion loop\n"); + return; + } + if ((vp = sp->value) == 0) + return; + /* arrange that define unix unix still + has no effect, avoiding rescanning */ + if (streq(sp->name,sp->value)) + { + while (*vp) + sch(*vp++); + return; + } + backsch(' '); + if (*vp == '(') + expdef(vp); + else + while (*vp) + backsch(*vp++); + backsch(' '); + while (bp>revbuff) + ungetc(*--bp); +} + +getsuf(as) +char as[]; +{ + register int c; + register char *s; + register int t; + + s = as; + c = 0; + while(t = *s++) + if (t=='/') + c = 0; + else + c++; + s =- 3; + if (c<=14 && c>2 && *s++=='.') + return(*s); + return(0); +} + +setsuf(as, ch) +char as[]; +{ + register char *s, *s1; + + s = s1 = copy(as); + while(*s) + if (*s++ == '/') + s1 = s; + s[-1] = ch; + return(s1); +} + +callsys(f, v) +char f[], *v[]; { + int t, status; + + if ((t=fork())==0) { + execv(f, v); + printf("Can't find %s\n", f); + exit(1); + } else + if (t == -1) { + printf("Try again\n"); + return(1); + } + while(t!=wait(&status)); + if ((t=(status&0377)) != 0 && t!=14) { + if (t!=2) /* interrupt */ + printf("Fatal error in %s\n", f); + dexit(); + } + return((status>>8) & 0377); +} + +copy(as) +char as[]; +{ + register char *otsp, *s; + + otsp = tsp; + s = as; + while(*tsp++ = *s++); + return(otsp); +} + +nodup(l, os) +char **l, *os; +{ + register char *t, *s; + register int c; + + s = os; + if (getsuf(s) != 'o') + return(1); + while(t = *l++) { + while(c = *s++) + if (c != *t++) + break; + if (*t=='\0' && c=='\0') + return(0); + s = os; + } + return(1); +} + +cunlink(f) +char *f; +{ + if (f==0) + return(0); + return(unlink(f)); +} +expdef(proto) + char *proto; +{ +char buffer[100], *parg[20], *pval[20], name[20], *cspace, *wp; +char protcop[100], *pr; +int narg, k, i, c; +pr = protcop; +while (*pr++ = *proto++); +proto= protcop; +for (narg=0; (parg[narg] = token(&proto)) != 0; narg++) + ; +/* now scan input */ +cspace = buffer; +while ((c=getch()) == ' '); +if (c != '(') + { + error("defined function requires arguments"); + return; + } +ungetc(c); +for(k=0; pval[k] = coptok(&cspace); k++); +if (k!=narg) + { + error("define argument mismatch"); + return; + } +while (c= *proto++) + { + if (!letter(c)) + backsch(c); + else + { + wp = name; + *wp++ = c; + while (letnum(*proto)) + *wp++ = *proto++; + *wp = 0; + for (k=0; k 0) + { + if (stc == '"' || stc == '\'') + { + stop = stc; + if (stop == '\'') + *(*cpp)++ = '\''; + while ( (stc = getch()) != stop) + { + if (stc == '\n') + { + error ("non-terminated string"); + break; + } + if (stc == '\\') + if ((stc= getch()) != stop && stc != '\\') + *(*cpp)++ = '\\'; + *(*cpp)++ = stc; + } + if (stop == '\'') + *(*cpp)++ = '\''; + } + else if (stc == '\\') + { + stc = getch(); + if (stc != '"' && stc != '\\') + *(*cpp)++ = '\\'; + *(*cpp)++ = stc; + } + else + { + *(*cpp)++ = stc; + if (stc == '(') + paren++; + if (stc == ')') + paren--; + } + } +*(*cpp)++ = 0; +ungetc(stc); +return(val); +} +letter(c) +{ +if ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c == '_')) + return (1); +else + return(0); +} +letnum(c) +{ +if (letter(c) || (c >= '0' && c <= '9')) + return(1); +else + return(0); +} +streq(s,t) char *s, *t; +{ +int c; +while ( (c= *s++) == *t++) + if (c==0) return(1); +return(0); +} diff --git a/source/s1/cdb1.c b/source/s1/cdb1.c new file mode 100644 index 0000000..54053fb --- /dev/null +++ b/source/s1/cdb1.c @@ -0,0 +1,965 @@ +# +/* + + C debugger + +*/ + +#include "/usr/sys/param.h" +#include "/usr/sys/user.h" + +#define DSP 0 +#define ISP 1 +#define NBKP 10 +#define SYMSIZ 12*400 +#define BADJST 01 + +int fcore; +int errno; +int fsym; +int symoff; +char *lp; +int errflg; +int symlen; +int symct; +int symcor; +int symbuf[SYMSIZ]; +int *symptr; +struct { + int loc; + int ins; + int count; + int flag; +} bkptl[NBKP]; +int lastbp; +char symbol[8]; +int symflg; +int symval; +char tsym[8]; +char fsymbol[10]; +char ssymbol[8]; +int ssymflg; +int ssymval; +int signo; +char line[128]; +int regbuf[512]; +char **uregs ®buf[512]; +char *rtsize; +int loccsv; +int locsr5; +#define RUSER 1 +#define RIUSER 2 +#define WUSER 4 +#define RUREGS 3 +#define WUREGS 6 +#define SETTRC 0 +#define CONTIN 7 +#define EXIT 8 + +#define ps -1 +#define pc -2 +#define sp -6 +#define r5 -9 +#define r4 -10 +#define r3 -11 +#define r2 -12 +#define r1 -5 +#define r0 -3 +struct reglist { + char *rname; + int roffs; +} reglist[] { + "ps", ps, + "pc", pc, + "sp", sp, + "r5", r5, + "r4", r4, + "r3", r3, + "r2", r2, + "r1", r1, + "r0", r0, +}; + +struct sfregs { + int junk[2]; + int fpsr; + float sfr[6]; +}; + +struct lfregs { + int junk[2]; + int fpsr; + double lfr[6]; +}; + +int frnames[] { 0, 3, 4, 5, 1, 2 }; +int dot; +int tdot; +int dotinc 2; +int lastcom '/'; +int lastype 'o'; +int modifier; +char *symfil "a.out"; +char *corfil "core"; +int callist[50]; +int entpt[50]; +int callev; +int pid; +int adrflg; +int idsep; +char *signals[] { + "", + "Hangup", + "Interrupt", + "Quit", + "Illegal instruction", + "Trace/BTP", + "IOT", + "EMT", + "Floating exception", + "Killed", + "Bus error", + "Memory fault", + "Bad system call", + "", + "", + "", +}; + +main(argc, argv) +char **argv; +{ + int onintr(); + + if (argc>1) + symfil = argv[1]; + if (argc>2) + corfil = argv[2]; + fcore = open(corfil, 0); + if ((fsym = open(symfil, 0)) < 0) { + printf("%s not found\n", symfil); + return; + } + read(fsym, regbuf, 020); + if (regbuf[0]==0411) /* I/D separated */ + idsep++; + else if (regbuf[0]!=0410 && regbuf[0]!=0407) { /* magic */ + printf("Bad format: %s\n", symfil); + return; + } + symoff = regbuf[1] + regbuf[2]; + symlen = regbuf[4]; + if (regbuf[7] != 1) + symoff =<< 1; + symoff =+ 020; + seek(fsym, symoff, 0); + symcor = read(fsym, symbuf, sizeof symbuf); + if (symcor>0) + symoff =+ symcor; + symcor =>> 1; + read(fcore, regbuf, 1024); + signo = regbuf[0].u_arg[0]&017; + regbuf->u_tsize =<< 6; + regbuf->u_dsize =<< 6; + regbuf->u_ssize =<< 6; + rtsize = (regbuf->u_tsize+017777) & ~017777; + if (symlook("csv\0\0\0\0")) + loccsv = ssymval; + if (symlook("savr5\0\0\0")) + locsr5 = ssymval; + setstack(); + signal(SIGINS, onintr); + setexit(); + signal(SIGINT, onintr); +loop: + if (errflg) { + printf("?\n"); + errflg = 0; + } + lp = line; + while ((*lp = getchar()) != '\n') + if (*lp++ == '\0') { + if (pid) + ptrace(EXIT, pid, 0, 0); + return; + } + lp = line; + command(); + goto loop; +} + +command() +{ + register n; + + adrflg = expr(); + if (errflg) + return; + n = getcnt(); + if (lastcom=='$') + lastcom = '/'; + if (*lp == '\n') { + if (!adrflg) + dot =+ dotinc; + } else + lastcom = *lp++; + modifier = 0; + if (*lp != '\n') + modifier = *lp++; + if (lastcom=='%' && modifier=='r') { + runcom(); + return; + } + if (*lp != '\n') { + errflg++; + return; + } + if (adrflg) + dot = tdot; + while(n) { + scommand(n); + if (errflg) + return; + if (--n) + dot =+ dotinc; + } +} + +scommand(n) +{ + register w, c; + double fw; + struct { int i[4]; }; + int onintr(); + + switch(lastcom) { + + case '/': + w = cget(dot, DSP); + if (modifier) + lastype = modifier; + switch(lastype) { + + case 'o': + printf("%.1o\n", w); + dotinc = 2; + return; + + case 'i': + printf("%d\n", w); + dotinc = 2; + return; + + case 'f': + fw = 0; + fw.i[0] = w; + fw.i[1] = cget(dot+2, DSP); + printf("%e\n", fw); + dotinc = 4; + return; + + case 'd': + fw.i[0] = w; + fw.i[1] = cget(dot+2, DSP); + fw.i[2] = cget(dot+4, DSP); + fw.i[3] = cget(dot+6, DSP); + printf("%e\n", fw); + dotinc = 8; + return; + } + errflg++; + return; + + case '\\': + printf("%.1o\n", cget(dot, DSP)&0377); + dotinc = 1; + return; + + case '=': + printf("%.1o\n", dot); + return; + + case '\'': + printc(cget(dot, DSP) & 0377); + if (n<=1) + putchar('\n'); + dotinc = 1; + return; + + case '"': + w = cget(dot, DSP); + while(c = cget(w++, DSP)&0377) + printc(c); + putchar('\n'); + return; + + case '&': + psymoff(cget(dot, DSP), 0100000); + printf("\n"); + return; + + case '$': + printf("%s\n", signals[signo]); + printtrace(); + return; + + case '?': + printins(0); + printf("\n"); + return; + + case '%': + runcom(); + signal(SIGINT, onintr); + return; + + } + errflg++; +} + +getcnt() +{ + register t1, t2; + + if (*lp != ',') + return(1); + lp++; + t1 = tdot; + if (expr() == 0) { + tdot = t1; + return(1); + } + t2 = tdot; + tdot = t1; + return(t2); +} + +cget(n, space) +{ + register w; + + w = get(n, space); + if (errflg) + reset(); + return(w); +} + +printc(c) +{ + if (c<' ' || c>'~') + printf("\\%o", c); + else + printf("%c", c); +} + +expr() +{ + int i, t1, t2, donef, lastop, b; + + tdot = 0; + adrflg = 0; + lastop = '+'; + ssymval = 0; + donef = 0; +loop: + fsymbol[0] = 0; + if (symchar(0)) { + adrflg++; + symcollect('_'); + if (*lp++==':' && symchar(0)) { + for (i=0; i<8; i++) + fsymbol[i] = tsym[i]; + fsymbol[0] = '~'; + symcollect(0); + } else + lp--; + if (symlook(tsym) == 0) { + errflg++; + reset(); + } + goto loop; + } + if (*lp>='0' && *lp<='9') { + adrflg++; + ssymval = 0; + if (*lp == '0') + b = 8; + else + b = 10; + while (*lp>='0' && *lp<='9') { + ssymval =* b; + ssymval =+ *lp++ -'0'; + } + goto loop; + } + switch (*lp) { + + default: + donef++; + + case '+': + case '-': + switch(lastop) { + + case '+': + tdot =+ ssymval; + goto op; + + case '-': + tdot =- ssymval; + + op: + if (donef) + return(adrflg); + else + lastop = *lp++; + } + goto loop; + + case ' ': + case '\t': + lp++; + goto loop; + + case '[': + lp++; + t1 = ssymval; + t2 = tdot; + if (expr() == 0) + tdot = 0; + ssymval = cget(t1 + (tdot<<1), DSP); + tdot = t2; + if (*lp == ']') + lp++; + goto loop; + } +} + +symcollect(c) +{ + register char *p; + + p = tsym; + if (c) + *p++ = c; + while (symchar(1)) { + if (p < &tsym[8]) + *p++ = *lp; + lp++; + } + while (p < &tsym[8]) + *p++ = 0; +} + +symchar(dig) +{ + if (*lp>='a'&&*lp<='z' || *lp=='_') + return(1); + if (dig && *lp>='0' && *lp<='9') + return(1); + return(0); +} + +error() +{ + errflg++; + reset(); +} + +printtrace() +{ + int tpc, tr5, narg, argp, i; + + if (modifier=='r') { + printregs(); + return; + } + if (modifier=='f' || modifier=='d') { + printfregs(); + return; + } + tpc = uregs[pc]; + tr5 = uregs[r5]; + if (locsr5) + if (narg = get(locsr5, DSP)) { + tr5 = narg; + } + callev = 0; + while (errflg == 0) { + narg = findroutine(tpc, tr5); + printf("%2d: %.8s(", callev, ssymbol); + if (--narg >= 0) + printf("%.1o", get(tr5+4, DSP)); + argp = tr5+4; + while(--narg >= 0) + printf(",%.1o", get(argp =+ 2, DSP)); + printf(")\n"); + tpc = get(tr5+2, DSP); + if (callev < 50) { + entpt[callev] = ssymval; + callist[callev++] = tr5; + } + if ((tr5 = get(tr5, DSP)) == 0) + break; + } +} + +setstack() +{ + register int tpc, tr5, i; + + tpc = uregs[pc]; + tr5 = uregs[r5]; + if (locsr5) + if (i = get(locsr5, DSP)) { + tr5 = i; + } + callev = 0; + while (errflg == 0) { + findroutine(tpc, tr5); + tpc = get(tr5+2, DSP); + if (callev >= 50) + break; + entpt[callev] = ssymval; + callist[callev++] = tr5; + if ((tr5 = get(tr5, DSP)) == 0) + break; + } + errflg = 0; +} + +printfregs() +{ + register i; + double f; + + printf("fpsr %.1o\n", regbuf[0].fpsr); + for (i=0; i<6; i++) { + if (regbuf[0].fpsr&0200) /* long mode */ + f = regbuf[0].lfr[frnames[i]]; + else + f = regbuf[0].sfr[frnames[i]]; + printf("fr%d %e\n", i, f); + } +} + +printregs() +{ + register struct reglist *p; + register char *v, *d; + + for (p=reglist; p < ®list[9]; p++) { + printf("%s %.1o", p->rname, v=uregs[p->roffs]); + d = vallook(v); + if (d < 010000) { + printf(" %.8s", ssymbol); + if (d) + printf("+%.1o", d); + } + printf("\n"); + } +} + +findroutine(rpc, rr5) +{ + register callpt, inst, narg; + + callpt = get(rr5+2, DSP); + if ((inst=get(callpt-4, ISP)) == 04737) /* jsr pc,*$... */ + narg = 1; + else if ((inst&~077)==04700) /* jsr pc,... */ + narg = 0; + else { + errflg++; + return(0); + } + inst = vallook((inst==04767?callpt:0) + get(callpt-2, ISP)); + if (inst) { + ssymbol[0] = '?'; + ssymbol[1] = 0; + ssymval = 0; + } + inst = get(callpt, ISP); + if (inst == 05726) /* tst (sp)+ */ + return(narg+1); + if (inst == 022626) /* cmp (sp)+,(sp)+ */ + return(narg+2); + if (inst == 062706) /* add $n,sp */ + return(narg+get(callpt+2, ISP)/2); + return(narg); +} + +runcom() +{ + int stat; + register w, i; + + switch(modifier) { + + + /* delete breakpoint */ + case 'd': + if (adrflg==0) + error(); + for (w=0; w= NBKP) { + printf("%s\n", signals[signo]); + return; + } + lastbp = w; + ptrace(WUSER, pid, w, bkptl[i].ins); + ptrace(WUREGS, pid, 2*(512+pc), w); + ptrace(WUREGS, pid, 2*(512+ps), uregs[ps]|020); + printf("Breakpoint: "); + psymoff(w, 0777); + printf("\n"); + return; + } + error(); +} + +doexec() +{ + extern _exectrap; + char *argl[32]; + register char *p, **ap; + register c; + + _exectrap++; + ap = argl; + *ap++ = symfil; + p = lp; + do { + while (*p==' ') + p++; + if (*p=='\n' || *p=='\0') + break; + *ap++ = p; + while (*p!=' ' && *p!='\n') + p++; + c = *p; + *p++ = '\0'; + } while (c != '\n'); + *ap++ = 0; + execv(symfil, argl); +} + +setbp(runflag) +{ + register w, i1, l; + int i2; + + for (w=0; w>8; + collinfo(); + if (signo!=SIGTRC) { + printf("%s\n", signals[signo]); + reset(); + } +} + +collinfo() +{ + register i; + + for (i=0; i<9; i++) + uregs[reglist[i].roffs] = + ptrace(RUREGS, pid, 2*(512+reglist[i].roffs), 0); + setstack(); +} + +symlook(symstr) +char *symstr; +{ + register i; + register symv; + + symset(); + if (fsymbol[0]==0) { + while(symget()) { + if (eqstr(symbol, symstr)) { + savsym(); + return(1); + } + } + return(0); + } + while (symget()) { + /* wait for function symbol */ + if (symbol[0]!='~' || !eqstr(symbol, fsymbol)) + continue; + symv = symval; + while (symget()&& symbol[0]!='~' &&symflg!=037) + if (eqstr(symbol, symstr)) + return(localsym(symv)); + return(0); + } +} + +localsym(s) +{ + register i, xr5; + + /* label, static */ + if (symflg>=2 && symflg<=4) { + ssymval = symval; + return(1); + } + /* auto, arg */ + if (symflg==1) { + for (i=0; i>8)&0377 | (w1<<8); + } + errflg = errno; + return(w); + } + w = 0; + if (idsep==0&&addru_tsize || idsep&&space==ISP) { + seek(fsym, addr+020, 0); + if (read(fsym, &w, 2) != 2) + errflg++; + return(w); + } + if (addr < rtsize+regbuf->u_dsize) { + if (idsep==0) + addr =- rtsize; + } else if (-addr < regbuf->u_ssize) + addr =+ regbuf->u_dsize + regbuf->u_ssize; + else + errflg++; + seek(fcore, addr+1024, 0); + if (read(fcore, &w, 2) < 2) + errflg++; + return(w); +} + +symset() +{ + symct = symlen; + symptr = symbuf; + seek(fsym, symoff, 0); +} + +symget() +{ + register int *p, *q; + if ((symct =- 12) < 0) + return(0); + if (symptr < &symbuf[symcor]) { + p = symptr; + for (q=symbol; q <= &symval;) + *q++ = *p++; + symptr = p; + return(1); + } + return(read(fsym, symbol, 12) == 12); +} + +savsym(skip) +{ + register int ch; + register char *p, *q; + + p = symbol; + q = ssymbol; + while (p lim) { + printf("%.1o", v); + return; + } + printf("%.8s", ssymbol); + if (w) + printf("+%d", w); +} + +#define ISP 1 +#define DOUBLE 0 +#define SINGLE 1 +#define SINGLW 2 +#define MULDIV 4 +#define BRANCH 5 +#define NOADDR 6 +#define FLTREV 7 +#define FLTNOR 8 +#define SPECL1 9 +#define SPECL2 10 +#define SPECL3 11 +#define SPECL4 12 +#define SPECL5 13 +#define SPECL6 14 +#define SPECL7 15 +#define SPECL8 18 +#define SPECL9 19 + +struct optab { + int mask; + int val; + int itype; + char *iname; +} optab[] { + 0107777, 0010000, DOUBLE, "mov", + 0107777, 0020000, DOUBLE, "cmp", + 0107777, 0030000, DOUBLE, "bit", + 0107777, 0040000, DOUBLE, "bic", + 0107777, 0050000, DOUBLE, "bis", + 0007777, 0060000, DOUBLE, "add", + 0007777, 0160000, DOUBLE, "su", + 0100077, 0005000, SINGLE, "clr", + 0100077, 0005100, SINGLE, "com", + 0100077, 0005200, SINGLE, "inc", + 0100077, 0005300, SINGLE, "dec", + 0100077, 0005400, SINGLE, "neg", + 0100077, 0005500, SINGLE, "adc", + 0100077, 0005600, SINGLE, "sbc", + 0100077, 0005700, SINGLE, "tst", + 0100077, 0006000, SINGLE, "ror", + 0100077, 0006100, SINGLE, "rol", + 0100077, 0006200, SINGLE, "asr", + 0100077, 0006300, SINGLE, "asl", + 0000077, 0000100, SINGLE, "jmp", + 0000077, 0000300, SINGLE, "swab", + 0000077, 0170100, SINGLW, "ldfps", + 0000077, 0170200, SINGLW, "stfps", + 0000077, 0170300, SINGLW, "stst", + 0000077, 0170400, SINGLW, "clrf", + 0000077, 0170500, SINGLW, "tstf", + 0000077, 0170600, SINGLW, "absf", + 0000077, 0170700, SINGLW, "negf", + 0000077, 0006700, SINGLW, "sxt", + 0000077, 0006600, SINGLW, "mtpi", + 0000077, 0106600, SINGLW, "mtpd", + 0000077, 0006500, SINGLW, "mfpi", + 0000077, 0106500, SINGLW, "mfpd", + 0000777, 0070000, MULDIV, "mul", + 0000777, 0071000, MULDIV, "div", + 0000777, 0072000, MULDIV, "ash", + 0000777, 0073000, MULDIV, "ashc", + 0000377, 0000400, BRANCH, "br", + 0000377, 0001000, BRANCH, "bne", + 0000377, 0001400, BRANCH, "beq", + 0000377, 0002000, BRANCH, "bge", + 0000377, 0002400, BRANCH, "blt", + 0000377, 0003000, BRANCH, "bgt", + 0000377, 0003400, BRANCH, "ble", + 0000377, 0100000, BRANCH, "bpl", + 0000377, 0100400, BRANCH, "bmi", + 0000377, 0101000, BRANCH, "bhi", + 0000377, 0101400, BRANCH, "blos", + 0000377, 0102000, BRANCH, "bvc", + 0000377, 0102400, BRANCH, "bvs", + 0000377, 0103000, BRANCH, "bhis", + 0000377, 0103400, BRANCH, "blo", + 0000000, 0000000, NOADDR, "halt", + 0000000, 0000001, NOADDR, "wait", + 0000000, 0000002, NOADDR, "rti", + 0000000, 0000004, NOADDR, "iot", + 0000000, 0000005, NOADDR, "reset", + 0000377, 0171000, FLTREV, "mulf", + 0000377, 0171400, FLTREV, "modf", + 0000377, 0172000, FLTREV, "addf", + 0000377, 0172400, FLTREV, "movf", + 0000377, 0173000, FLTREV, "subf", + 0000377, 0173400, FLTREV, "cmpf", + 0000377, 0174000, FLTNOR, "movf", + 0000377, 0174400, FLTREV, "divf", + 0000377, 0175000, FLTNOR, "movei", + 0000377, 0175400, FLTNOR, "movfi", + 0000377, 0176000, FLTNOR, "movfo", + 0000377, 0176400, FLTREV, "movie", + 0000377, 0177000, FLTREV, "movif", + 0000377, 0177400, FLTREV, "movof", + 0000000, 0170000, NOADDR, "cfcc", + 0000000, 0170001, NOADDR, "setf", + 0000000, 0170002, NOADDR, "seti", + 0000000, 0170011, NOADDR, "setd", + 0000000, 0170012, NOADDR, "setl", + 0000777, 0004000, SPECL1, "jsr", + 0000777, 0074000, SPECL1, "xor", + 0000007, 0000200, SPECL2, "rts", + 0000017, 0000240, SPECL3, "cflg", + 0000017, 0000260, SPECL3, "sflg", + 0000377, 0104000, SPECL4, "emt", + 0000377, 0104400, SPECL5, "sys", + 0000077, 0006400, SPECL7, "mark", + 0000777, 0077000, SPECL8, "sob", + 0000007, 0000230, SPECL9, "spl", + 0177777, 0000000, SPECL6, "oct", +}; + +struct systab { + int argc; + char *sname; +} systab[] { + 1, "indir", + 0, "exit", + 0, "fork", + 2, "read", + 2, "write", + 2, "open", + 0, "close", + 0, "wait", + 2, "creat", + 2, "link", + 1, "unlink", + 2, "exec", + 1, "chdir", + 0, "time", + 3, "mknod", + 2, "chmod", + 2, "chown", + 1, "break", + 2, "stat", + 2, "seek", + 0, "getpid", + 3, "mount", + 1, "umount", + 0, "setuid", + 0, "getuid", + 0, "stime", + 3, "ptrace", + 0, "27", + 1, "fstat", + 0, "29", + 1, "smdate", + 1, "stty", + 1, "gtty", + 0, "33", + 0, "nice", + 0, "sleep", + 0, "sync", + 1, "kill", + 0, "switch", + 0, "39", + 0, "40", + 0, "dup", + 0, "pipe", + 1, "times", + 4, "profil", + 0, "45", + 0, "setgid", + 0, "getgid", + 2, "signal", + 0, "49", + 0, "50", + 0, "51", + 0, "52", + 0, "53", + 0, "54", + 0, "55", + 0, "56", + 0, "57", + 0, "58", + 0, "59", + 0, "60", + 0, "61", + 0, "62", + 0, "63", +}; + +char *regname[] { "r0", "r1", "r2", "r3", "r4", "r5", "sp", "pc"}; + +printins(f) +{ + register ins, w; + register struct optab *p; + + dotinc = 2; + ins = cget(dot, ISP); + if (vallook(dot)==0) + printf("%.8s:", ssymbol); + printf("\t"); + for (p=optab;; p++) + if ((ins & ~p->mask) == p->val) + break; + printf("%s", p->iname); + switch (p->itype) { + + /* rts */ + case SPECL2: + ins =& 07; + + case SINGLE: + if (ins < 0) + printf("b"); + + case SINGLW: + printf("\t"); + paddr(ins); + return; + + case FLTREV: + ins =& 0377; + + case MULDIV: + ins = ((ins>>6)&07) | ((ins<<6)&07700); + goto doub; + + case FLTNOR: + ins =& 0377; + + /* jsr, xor */ + case SPECL1: + ins =& 0777; + goto doub; + + case DOUBLE: + if (ins<0) + printf("b"); + doub: + printf("\t"); + paddr(ins>>6); + printf(","); + paddr(ins); + return; + + case NOADDR: + return; + + /* sob */ + case SPECL8: + printf("\t"); + paddr((ins>>6)&07); + printf(","); + ins = - (ins&077); + goto bran; + + case BRANCH: + printf("\t"); + bran: + ins =& 0377; + if (ins&0200) + ins =| 0177400; + ins = dot + (ins<<1) + 2; + psymoff(ins, 010000); + return; + + /* emt */ + case SPECL4: + ins =& 0377; + /* mark */ + case SPECL7: + ins =& 077; + /* spl */ + case SPECL9: + ins =& 07; + printf("\t%d", ins); + return; + + /* sys */ + case SPECL5: + printf("\t%s", systab[ins =& 077].sname); + if (ins==0 && f==0) { /* indir */ + w = dot; + dot = cget(dot+2, ISP); + printf(" {"); + printins(1); + printf("}"); + dotinc = 4; + dot = w; + return; + } + w = systab[ins].argc; + while (w--) { + printf("; "); + psymoff(cget(dot+dotinc, ISP), 010000); + dotinc =+ 2; + } + return; + + default: + printf("\t%.1o", ins); + } +} + +paddr(aa) +{ + register a, r; + + a = aa; + r = a&07; + a =& 070; + if (r==7 && a&020) { + if (a&010) + printf("*"); + if (a&040) + psymoff(cget(dot+dotinc, ISP)+dot+dotinc+2, 010000); + else { + printf("$"); + psymoff(cget(dot+dotinc, ISP), 010000); + } + dotinc =+ 2; + return; + } + r = regname[r]; + switch (a) { + /* r */ + case 000: + printf("%s", r); + return; + + /* (r) */ + case 010: + printf("(%s)", r); + return; + + /* *(r)+ */ + case 030: + printf("*"); + + /* (r)+ */ + case 020: + printf("(%s)+", r); + return; + + /* *-(r) */ + case 050: + printf("*"); + + /* -(r) */ + case 040: + printf("-(%s)", r); + return; + + /* *x(r) */ + case 070: + printf("*"); + + /* x(r) */ + case 060: + psymoff(cget(dot+dotinc, ISP), 010000); + dotinc =+ 2; + printf("(%s)", r); + return; + } +} diff --git a/source/s1/chgrp.s b/source/s1/chgrp.s new file mode 100644 index 0000000..eaab5a9 --- /dev/null +++ b/source/s1/chgrp.s @@ -0,0 +1,106 @@ +/ chgrp -- change group + + + .globl fopen, getc, mesg + + mov sp,r5 + mov (r5),r4 + cmp r4,$3 + bge 1f + jsr r5,mesg; ; .even +1: + add $4,r5 + mov (r5),r3 + cmpb (r3),$'0 + blt 1f + cmpb (r3),$'9 + bgt 1f + jsr r5,cvnum; geta + br do +1: + mov $uids,r0 + jsr r5,fopen; ubuf + bec 1f + jsr r5,mesg; ; .even + sys exit +1: + mov r3,r2 +2: + jsr r5,getc; ubuf + bcc 3f +who: + jsr r5,mesg; ; .even + sys exit +3: + cmp r0,$': + beq 3f + cmpb (r2)+,r0 + beq 2b +2: + jsr r5,getc; ubuf + bcs who + cmp r0,$'\n + bne 2b + br 1b +3: + tstb (r2) + bne 2b +3: + jsr r5,getc; ubuf + cmpb r0,$': + bne 3b + jsr r5,cvnum; getc +do: + sub $2,r4 + swab r1 + mov r1,0f+2 + tst (r5)+ +1: + mov (r5),0f + mov (r5)+,9f + sys stat; 9:..; statb + movb statb+7,0f+2 + sys chown; 0:..; 0 + bec 2f + mov 0b,r0 + mov r0,0f + clr 0f+2 +3: + tstb (r0)+ + beq 3f + inc 0f+2 + br 3b +3: + mov $1,r0 + sys write; 0:..; .. + jsr r5,mesg; ; .even +2: + dec r4 + bgt 1b + sys exit + +cvnum: + clr r1 +1: + jsr r5,*(r5); ubuf + bcs 1f + sub $'0,r0 + cmp r0,$9. + bhi 1f + mpy $10.,r1 + add r0,r1 + br 1b +1: + tst (r5)+ + rts r5 + +geta: + movb (r3)+,r0 + tst (r5)+ + rts r5 + +uids: + + .bss +statb: .=.+36. +ubuf: .=.+518. diff --git a/source/s1/chmod.c b/source/s1/chmod.c new file mode 100644 index 0000000..b604783 --- /dev/null +++ b/source/s1/chmod.c @@ -0,0 +1,27 @@ +main(argc, argv) +char **argv; +{ + register i, m; + register char *c; + int count; + + if(argc < 3) { + printf("arg count\n"); + exit(1); + } + c = argv[1]; + m = 0; + for(m=0; *c; c++) { + if(*c < '0' || *c > '7') { + printf("bad mode\n"); + exit(1); + } + m = (m<<3) | *c - '0'; + } + for(i=2; i; .even +1: + add $4,r5 + mov (r5),r3 + cmpb (r3),$'0 + blt 1f + cmpb (r3),$'9 + bgt 1f + jsr r5,cvnum; geta + br do +1: + mov $uids,r0 + jsr r5,fopen; ubuf + bec 1f + jsr r5,mesg; ; .even + sys exit +1: + mov r3,r2 +2: + jsr r5,getc; ubuf + bcc 3f +who: + jsr r5,mesg; ; .even + sys exit +3: + cmp r0,$': + beq 3f + cmpb (r2)+,r0 + beq 2b +2: + jsr r5,getc; ubuf + bcs who + cmp r0,$'\n + bne 2b + br 1b +3: + tstb (r2) + bne 2b +3: + jsr r5,getc; ubuf + cmpb r0,$': + bne 3b + jsr r5,cvnum; getc +do: + sub $2,r4 + mov r1,0f+2 + tst (r5)+ +1: + mov (r5),0f + mov (r5)+,9f + sys stat; 9:..; statb + movb statb+8,0f+3 + sys chown; 0:..; 0 + bec 2f + mov 0b,r0 + mov r0,0f + clr 0f+2 +3: + tstb (r0)+ + beq 3f + inc 0f+2 + br 3b +3: + mov $1,r0 + sys write; 0:..; .. + jsr r5,mesg; ; .even +2: + dec r4 + bgt 1b + sys exit + +cvnum: + clr r1 +1: + jsr r5,*(r5); ubuf + bcs 1f + sub $'0,r0 + cmp r0,$9. + bhi 1f + mpy $10.,r1 + add r0,r1 + br 1b +1: + tst (r5)+ + rts r5 + +geta: + movb (r3)+,r0 + tst (r5)+ + rts r5 + +uids: + + .bss +statb: .=.+36. +ubuf: .=.+518. diff --git a/source/s1/clri.s b/source/s1/clri.s new file mode 100644 index 0000000..04686a5 --- /dev/null +++ b/source/s1/clri.s @@ -0,0 +1,63 @@ +/ clri -- clear inode + + cmp (sp)+,$2 + blt error + beq 1f + mov 4(sp),fs1 + mov 4(sp),fs2 +1: + tst (sp)+ + mov (sp)+,r0 + clr r5 +1: + movb (r0)+,r1 + beq 1f + mpy $10.,r5 + sub $'0,r1 + cmp r1,$10. + bhis error + add r1,r5 + br 1b +1: + add $31.,r5 + mov r5,r0 + als $-4,r0 + mov r0,0f + sys open; fs1: filsys; 0 + bes error + mov r0,-(sp) + sys seek; 0:..; 3 + mov (sp),r0 + sys read; buf; 512. + mov (sp)+,r0 + sys close + mov r5,r0 + als $5,r0 + bic $!777,r0 + add $buf,r0 + mov $16.,r5 +1: + clr (r0)+ + sob r5,1b + sys open; fs2: filsys; 1 + bes error + mov r0,-(sp) + mov 0b,0f + sys seek; 0:..; 3 + mov (sp)+,r0 + sys write; buf; 512. + bes error + sys exit + +error: + mov $1,r0 + sys write; 1f; 2f-1f + sys exit +1: + +2: + +filsys: +.even + .bss +buf: .=.+512. diff --git a/source/s1/cmp.c b/source/s1/cmp.c new file mode 100644 index 0000000..742a5cb --- /dev/null +++ b/source/s1/cmp.c @@ -0,0 +1,90 @@ +int ibuf1[259]; +int ibuf2[259]; +int eflg; +int lflg 1; +int line[2] {0, 1}; +int chr[2] { -1, -1}; + +main(argc, argv) +char **argv; +{ + register c1, c2; + char *arg; + + if(argc < 3) + goto narg; + arg = argv[1]; + if(arg[0] == '-' && arg[1] == 's') { + lflg--; + argv++; + argc--; + } + arg = argv[1]; + if(arg[0] == '-' && arg[1] == 'l') { + lflg++; + argv++; + argc--; + } + if(argc < 3) + goto narg; + arg = argv[1]; + if( arg[0]=='-' && arg[1]==0 ) + ibuf1[0] = dup(0); + else if(fopen(arg, ibuf1) < 0) + goto barg; + arg = argv[2]; + if(fopen(arg, ibuf2) < 0) + goto barg; + +loop: + if (++chr[1]==0) + chr[0]++; + c1 = getc(ibuf1); + c2 = getc(ibuf2); + if(c1 == c2) { + if (c1 == '\n') + if (++line[1]==0) + line[0]++; + if(c1 == -1) { + if(eflg) + exit(1); + exit(0); + } + goto loop; + } + if(lflg == 0) + exit(1); + if(c1 == -1) { + arg = argv[1]; + goto earg; + } + if(c2 == -1) + goto earg; + if(lflg == 1) { + printf("%s %s differ: char %s, line ", argv[1], arg, + locv(chr[0], chr[1])); + printf("%s\n", locv(line[0], line[1])); + exit(1); + } + eflg = 1; + printf("%5s %3o %3o\n", locv(chr[0], chr[1]), c1, c2); + goto loop; + +narg: + printf("arg count\n"); + exit(2); + +barg: + printf("cannot open %s\n", arg); + exit(2); + +earg: + printf("EOF on %s\n", arg); + exit(1); +} + +putchar(c) +{ + + write(1, &c, 1); +} diff --git a/source/s1/col.c b/source/s1/col.c new file mode 100644 index 0000000..c3bf7a6 --- /dev/null +++ b/source/s1/col.c @@ -0,0 +1,132 @@ +# define PL 102 +# define ESC 033 +# define SI 017 +# define SO 016 +# define LINELN 800 +char *page[PL]; +char lbuff [LINELN], *line; +main () +{ +int c, i, j, ll, cp, mustwr; + extern int fin, fout; + fin = dup(0); + fout = dup(1); + +for (ll=0; ll0) + switch (c = getchar()) + { + case '\n': + store (ll%PL); + if (++ll >= mustwr) + if (page[ll%PL] != 0) + { + printf ("%s\n",page[ll%PL]); + mustwr++; + free (page[ll%PL]); + page[ll%PL]=0; + } + fetch (ll%PL); + cp = 0; + continue; + case '\0': continue; + case ESC: + c = getchar(); + if (c == '7') + { + store(ll%PL); + ll--; + fetch (ll%PL); + } + else + { + outc (ESC, &line); + outc (c, &line ); + } + continue; + case '\r': + line = lbuff; + continue; + case '\t': + outc (' ', &line); + cp = line-lbuff; + while (cp++%8) + outc(' ', &line); + continue; + default: + outc(c, &line); + } +for (i=0; i0 || *(*lp) == '\b' || *(*lp) == ESC || **lp == SI || **lp == SO) + { + switch (*(*lp)) + { + case '\b': + j++; + (*lp)++; + break; + case '\0': + *(*lp)++ = ' '; + j--; + break; + case ESC: /* 'escape' */ + (*lp) =+ 2; + break; + case SI: + case SO: + (*lp)++; + break; + default: + (*lp)++; + j--; + break; + } + } +if (c != ' ' || *(*lp) == '\0') + *(*lp) = c; +(*lp)++; +} +store (ll) +{ +if (page[ll] != 0) + free (page[ll]); +page[ll] = alloc ( leng (lbuff) + 2); +copy (page[ll],lbuff); +} +fetch(ll) +{ +int i; +for (i=0; i < LINELN; i++) + lbuff[i] = '\0'; +copy (line=lbuff, page[ll]); +} +copy (s,t) + char *s, *t; +{ +if (t == 0) + return (*s=0); +while (*s++ = *t++); +} +leng (s) + char *s; +{ +int l; +for (l=0; s[l]; l++); +return (l); +} diff --git a/source/s1/comm.c b/source/s1/comm.c new file mode 100644 index 0000000..4b356e0 --- /dev/null +++ b/source/s1/comm.c @@ -0,0 +1,168 @@ +#define LB 250 +int one; +int two; +int three; + +char *ldr[3]; + +char ib1[518]; +char ib2[518]; +main(argc,argv) + char *argv[]; +{ + extern fout; + int l; + char lb1[LB],lb2[80]; + + ldr[0] = ""; + ldr[1] = "\t"; + ldr[2] = "\t\t"; + if(argc > 1) { + if(*argv[1] == '-' && argv[1][1] != 0) { + l = 1; + while(*++argv[1]) { + switch(*argv[1]) { + case'1': + if(!one) { + one = 1; + ldr[1][0] = + ldr[2][l--] = '\0'; + } + break; + case '2': + if(!two) { + two = 1; + ldr[2][l--] = '\0'; + } + break; + case '3': + three = 1; + break; + default: + printf("Illegal flag: %c\n",*argv[1]); + exit(); + } + } + argv++; + argc--; + } + } + + if(argc < 3) { + printf("Argc = %d\n",argc); + exit(); + } + + openfil(argv[1],ib1); + openfil(argv[2],ib2); + fout = dup(1); + + + if(rd(ib1,lb1) < 0) { + if(rd(ib2,lb2) < 0) exit(); + copy(ib2,lb2,2); + } + if(rd(ib2,lb2) < 0) copy(ib1,lb1,1); + + while(1) { + + switch(compare(lb1,lb2)) { + + case 0: + wr(lb1,3); + if(rd(ib1,lb1) < 0) { + if(rd(ib2,lb2) < 0) fexit(); + copy(ib2,lb2,2); + } + if(rd(ib2,lb2) < 0) copy(ib1,lb1,1); + continue; + + case 1: + wr(lb1,1); + if(rd(ib1,lb1) < 0) copy(ib2,lb2,2); + continue; + + case 2: + wr(lb2,2); + if(rd(ib2,lb2) < 0) copy(ib1,lb1,1); + continue; + } + } +} + +rd(file,buf) + char *buf; +{ + + register int i; + i = 0; + while((*buf = getc(file)) >=0) { + if(*buf == '\n' || i > LB-2) { + *buf = '\0'; + return(0); + } + i++; + buf++; + } + return(-1); +} + +wr(str,n) + char *str; +{ + + switch(n) { + + case 1: + if(one) return; + break; + + case 2: + if(two) return; + break; + + case 3: + if(three) return; + } + printf("%s%s\n",ldr[n-1],str); +} + +copy(ibuf,lbuf,n) +{ + do { + wr(lbuf,n); + } while(rd(ibuf,lbuf) >= 0); + + flush(); + exit(); +} + +compare(a,b) + char *a,*b; +{ + register char *ra,*rb; + + ra = --a; + rb = --b; + while(*++ra == *++rb) + if(*ra == '\0') return(0); + if(*ra < *rb) return(1); + return(2); +} +fexit() +{ + flush(); + exit(); +} + +openfil(s,b) +char *s; +int *b; +{ + if(s[0]=='-' && s[1]==0) + b[0] = 0; + else if(fopen(s, b) == -1) { + printf("Can't open %s\n", s); + exit(1); + } +} diff --git a/source/s1/cp.c b/source/s1/cp.c new file mode 100644 index 0000000..4da67c7 --- /dev/null +++ b/source/s1/cp.c @@ -0,0 +1,57 @@ +/* + * cp oldfile newfile + */ + +main(argc,argv) +char **argv; +{ + static int buf[256]; + int fold, fnew, n; + register char *p1, *p2, *bp; + int mode; + + if(argc != 3) { + write(1, "Usage: cp oldfile newfile\n", 26); + exit(1); + } + if((fold = open(argv[1], 0)) < 0) { + write(1, "Cannot open old file.\n", 22); + exit(1); + } + fstat(fold, buf); + mode = buf[2]; + /* is target a directory? */ + if (stat(argv[2], buf+50)>=0 && (buf[52]&060000)==040000) { + p1 = argv[1]; + p2 = argv[2]; + bp = buf+100; + while(*bp++ = *p2++); + bp[-1] = '/'; + p2 = bp; + while(*bp = *p1++) + if(*bp++ == '/') + bp = p2; + argv[2] = buf+100; + } + if (stat(argv[2], buf+50) >= 0) { + if (buf[0]==buf[50] && buf[1]==buf[51]) { + write(1, "Copying file to itself.\n", 24); + exit(1); + } + } + if ((fnew = creat(argv[2], mode)) < 0) { + write(1, "Can't create new file.\n", 23); + exit(1); + } + while(n = read(fold, buf, 512)) { + if(n < 0) { + write(1, "Read error\n", 11); + exit(1); + } else + if(write(fnew, buf, n) != n){ + write(1, "Write error.\n", 13); + exit(1); + } + } + exit(0); +} diff --git a/source/s1/cpall.c b/source/s1/cpall.c new file mode 100644 index 0000000..2349e8d --- /dev/null +++ b/source/s1/cpall.c @@ -0,0 +1,27 @@ +char buf[100]; + +main(argc, argv) +char **argv; +{ + register i; + register char *c1, *c2; + + if(argc < 3) { + write(2, "arg count\n", 10); + exit(); + } + argc--; + c1 = buf; + c2 = argv[argc]; + while(*c1++ = *c2++); + c1[-1] = '/'; + *c1++ = '.'; + *c1 = '\0'; + for(i=1; i v || cp[1] < v) + flag++; + return(cp+2); + } + if(cp[-1] != v) + flag++; + return(cp); +} + +slp() +{ + register i; + int t[2]; + + time(t); + i = itime[1] - t[1]; + if(i > 0) + sleep(i); +} + +ex(s) +char *s; +{ + register i; + + if(fork()) { + wait(); + return; + } + for(i=0; s[i]; i++); + close(0); + creat(crontmp, 0600); + write(0, s, i); + close(0); + open(crontmp, 0); + unlink(crontmp); + if(fork()) + exit(); + execl("/bin/sh", "sh", "-t", 0); + exit(); +} + +init() +{ + int ib[259], t[10]; + register i, c; + register char *cp; + char *ocp; + int n; + extern char end[]; + + if(fopen(crontab, ib) < 0) { + write(1, "cannot open table\n", 18); + exit(); + } + cp = end; + if(aend == 0) + aend = cp; + +loop: + ocp = cp; + if(cp+100 > aend) { + aend =+ 512; + brk(aend); + } + for(i=0;; i++) { + do + c = getc(ib); + while(c == ' ' || c == '\t'); + if(c <= 0 || c == '\n') + goto ignore; + if(i == 5) + break; + if(c == '*') { + *cp++ = ANY; + continue; + } + n = 0; + while(c >= '0' && c <= '9') { + n = n*10 + c-'0'; + c = getc(ib); + } + if(n < 0 || n > 100) + goto ignore; + if(c == ',') + goto list; + if(c == '-') + goto range; + if(c != '\t' && c != ' ') + goto ignore; + *cp++ = n; + continue; + + list: + *cp++ = LIST; + *cp++ = n; + list1: + n = 0; + c = getc(ib); + while(c >= '0' && c <= '9') { + n = n*10 + c-'0'; + c = getc(ib); + } + if(n < 0 || n > 100) + goto ignore; + *cp++ = n; + if(c == ',') + goto list1; + if(c != '\t' && c != ' ') + goto ignore; + *cp++ = LIST; + continue; + + range: + *cp++ = RANGE; + *cp++ = n; + n = 0; + c = getc(ib); + while(c >= '0' && c <= '9') { + n = n*10 + c-'0'; + c = getc(ib); + } + if(n < 0 || n > 100) + goto ignore; + if(c != '\t' && c != ' ') + goto ignore; + *cp++ = n; + } + while(c != '\n') { + if(c <= 0) + goto ignore; + if(c == '%') + c = '\n'; + *cp++ = c; + c = getc(ib); + } + *cp++ = '\n'; + *cp++ = 0; + goto loop; + +ignore: + cp = ocp; + while(c != '\n') { + if(c <= 0) { + close(ib[0]); + *cp++ = EOF; + *cp++ = EOF; + aend = cp; + brk(aend); + return; + } + c = getc(ib); + } + goto loop; +} diff --git a/source/s1/crypt.c b/source/s1/crypt.c new file mode 100644 index 0000000..ce59fe9 --- /dev/null +++ b/source/s1/crypt.c @@ -0,0 +1,207 @@ +/* +This routine is an exact implementation of Boris Hagelin's +cryptographic machine. See U. S. Patent #2,089,603. +*/ + +int cagetable[] { 0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 8, 8, 9, 10, 12, 16, + 16, 17, 18, 20, 24, 32, 32, 33, 34, 36, 40, 48}; +int warr1[52]; +int warr2[50]; +int warr3[46]; +int warr4[42]; +int warr5[38]; +int warr6[34]; +int *wheel1 warr1; +int *wheel2 warr2; +int *wheel3 warr3; +int *wheel4 warr4; +int *wheel5 warr5; +int *wheel6 warr6; +char key[130]; +int xxx; + + +/* +subroutine to manufacture a wheel +*/ + +setup(list,n) int list[]; + {int *lp; + lp = list; + while(--n){ + *lp = lp+2; + lp[1] = getbit(); + if(xxx) putchar(lp[1]+'0'); + lp = lp + 2; + } + *lp = list; + lp[1] = getbit(); + if(xxx){ + putchar(lp[1]+'0'); + putchar('\n'); + } + } + + + +/* +subroutine to return the next bit from the main routines +argument +*/ + +getbit(){ + static i,j; + int b; + b = (key[j] >> i) & 1; + if (i++ > 5) { + j++; + i = 0; + } + return (b); + } + + + + +main(ncooky,cookyp) + int ncooky; + char *cookyp[]; + { + char *ip, *jp; + int temp; + int random; + int i,j; + int precious; + int crypt; + int cage[27]; + xxx = 0; + + + +/* +copy input key and pad with clever junk +*/ + + jp = key; + *jp++ = 004; + *jp++ = 034; + if(ncooky > 1){ + while (*jp++ = *cookyp[1]++); + jp--; + } + ip = key; + while (jp < key+128) { + *jp = jp[-1] ^ *ip++; + jp++; + } + + +/* +manufacture six wheels of various length +*/ + + setup(wheel1,26); + setup(wheel2,25); + setup(wheel3,23); + setup(wheel4,21); + setup(wheel5,19); + setup(wheel6,17); + +/* +set up the cage bars from the key area +*/ + + jp = key; + i = 27; + while (i--){ + cage[i] = cagetable[*jp++ % 28]; + if(xxx && (cage[i] != 0)){ + putchar( cage[i]/8 + '0'); + putchar( cage[i]%8 + '0'); + putchar(' '); + } + } + if(xxx) putchar('\n'); + + +/* +the internal settings are now complete +it's time to turn the crank, running the cage +bars against the wheel lugs. +*/ + + +while ((precious = getchar()) >=0){ + temp = 040*wheel1[1] + 020*wheel2[1] + 010*wheel3[1] + + 004*wheel4[1] + 002*wheel5[1] + 001*wheel6[1]; + wheel1 = *wheel1; + wheel2 = *wheel2; + wheel3 = *wheel3; + wheel4 = *wheel4; + wheel5 = *wheel5; + wheel6 = *wheel6; + + random = 0; + i = 27; + while (i--){ + random = random + ((temp & cage[i]) != 0); + } + random =% 26; + +/* +now we have a random number to use to encrypt the input +it is done in such a way that the process is its own +inverse. +*/ + + + if ( precious=='\n' || precious==' ') + crypt = precious; + else{ + crypt = ('a' + 'z' - precious + random)%0400; + if (crypt >= 'a' && crypt <= 'z' && precious > 'z') + crypt =+ 26; + if (crypt > 'z' && precious >= 'a' & precious <= 'z') + crypt =- 26; + if (crypt == '\n' || crypt == ' ') + crypt = precious; + } + putchar(crypt); + } +flush(); +return; +} + +char ibuf[512]; +char obuf[512]; +char *ibufp; +int icnt; +int ocnt; +getchar() +{ + + if(icnt == 0) { + icnt = read(0, ibuf, 512); + if(icnt <= 0) + return(-1); + ibufp = ibuf; + } + icnt --; + return(*ibufp++ & 0377); +} + +putchar(c) +{ + + obuf[ocnt++] = c; + if(ocnt >= 512) + flush(); +} + +flush() +{ + + if(ocnt > 0) + write(1, obuf, ocnt); + ocnt = 0; +} diff --git a/source/s1/date.c b/source/s1/date.c new file mode 100644 index 0000000..782c620 --- /dev/null +++ b/source/s1/date.c @@ -0,0 +1,150 @@ +int timbuf[2]; +char *cbp; + +char *tzname[2]; +int dmsize[]; +char cbuf[]; +char *cbp; + +struct { + char name[8]; + char tty; + char fill1; + int wtime[2]; + int fill2; +} wtmp[2]; + +main(argc, argv) +int argc, **argv; +{ + register char *tzn; + extern int timezone, *localtime(); + int wf, tfailed; + + tfailed = 0; + if(argc > 1) { + cbp = argv[1]; + if(gtime()) { + write(1, "bad conversion\n", 15); + exit(); + } + if (*cbp != 's') { + /* convert to Greenwich time, on assumption of Standard time. */ + dpadd(timbuf, timezone); + /* Now fix up to local daylight time. */ + if (localtime(timbuf)[8]) + dpadd(timbuf, -1*60*60); + } + time(wtmp[0].wtime); + wtmp[0].tty = '|'; + if(stime(timbuf) < 0) { + tfailed++; + write(1, "no permission\n", 14); + } else if ((wf = open("/usr/adm/wtmp", 1)) >= 0) { + time(wtmp[1].wtime); + wtmp[1].tty = '}'; + seek(wf, 0, 2); + write(wf, wtmp, 32); + } + } + if (tfailed==0) + time(timbuf); + cbp = cbuf; + ctime(timbuf); + write(1, cbuf, 20); + tzn = tzname[localtime(timbuf)[8]]; + if (tzn) + write(1, tzn, 3); + write(1, cbuf+19, 6); +} + +gtime() +{ + register int i; + register int y, t; + int d, h, m; + extern int *localtime(); + int nt[2]; + + t = gpair(); + if(t<1 || t>12) + goto bad; + d = gpair(); + if(d<1 || d>31) + goto bad; + h = gpair(); + if(h == 24) { + h = 0; + d++; + } + m = gpair(); + if(m<0 || m>59) + goto bad; + y = gpair(); + if (y<0) { + time(nt); + y = localtime(nt)[5]; + } + if (*cbp == 'p') + h =+ 12; + if (h<0 || h>23) + goto bad; + timbuf[0] = 0; + timbuf[1] = 0; + y =+ 1900; + for(i=1970; i= 3) + gdadd(1); + while(--t) + gdadd(dmsize[t-1]); + gdadd(d-1); + gmdadd(24, h); + gmdadd(60, m); + gmdadd(60, 0); + return(0); + +bad: + return(1); +} + +gdadd(n) +{ + register char *t; + + t = timbuf[1]+n; + if(t < timbuf[1]) + timbuf[0]++; + timbuf[1] = t; +} + +gmdadd(m, n) +{ + register int t1; + + timbuf[0] =* m; + t1 = timbuf[1]; + while(--m) + gdadd(t1); + gdadd(n); +} + +gpair() +{ + register int c, d; + register char *cp; + + cp = cbp; + if(*cp == 0) + return(-1); + c = (*cp++ - '0') * 10; + if (c<0 || c>100) + return(-1); + if(*cp == 0) + return(-1); + if ((d = *cp++ - '0') < 0 || d > 9) + return(-1); + cbp = cp; + return (c+d); +} diff --git a/source/s1/db1.s b/source/s1/db1.s new file mode 100644 index 0000000..d410f07 --- /dev/null +++ b/source/s1/db1.s @@ -0,0 +1,726 @@ +/ db1 -- debugger + +fpp = 0 +eae = 0 +ldfps = 170100^tst + + +db: + mov sp,r5 + mov (r5)+,r4 + tst (r5)+ + cmp r4,$2 + blt 1f + mov (r5),dbfile + mov (r5),odbfil + mov (r5)+,namfil + cmp r4,$2 + beq 1f + mov (r5)+,namfil +1: + sys open; dbfile: core; 0 + bec 9f + jmp fnfnd +9: + mov r0,dbfin + clr dbfout + sys open; odbfil:core; 1 + bes 1f + mov r0,dbfout +1: + sys open; namfil: a.out; 0 + bes 1f + mov r0,r1 + mov r0,symfin + sys read; nambuf; 20 + cmp nambuf,nobjmagic + beq 2f + cmp nambuf,objmagic + bne 1f +2: + mov nambuf+2,r0 / text + add nambuf+4,r0 / data + cmp nambuf+16,$1 / relocation? + beq 6f + asl r0 / sym origin +6: + add $20,r0 + mov r0,0f + mov r1,r0 + sys seek; 0:..; 0 + mov nambuf+10,r0 / symbol size + cmp r0,$maxsym + blos 3f + mov $maxsym,r0 +3: + add r0,0f + sys break; 0: nambuf + mov r0,0f + mov r1,r0 + sys read; nambuf; 0:.. + add $nambuf,r0 + mov r0,namsiz +1: + jsr r5,get; zero / test new object + cmp r0,nobjmagic + beq 2f + cmp r0,objmagic + bne 1f +2: + mov $20,getoff +1: + mov sp,savsp + sys signal; 2; 1 + ror r0 + bcs 1f + sys signal; 2; errexit +1: + cmp r4,$2 / arg count + beq 9f / not core image + cmp r4,$4 / no-core image flag + beq 9f + mov $1024.,getoff + mov dbfin,r0 + sys seek; 0; 0 + mov dbfin,r0 + sys read; regbuf; 1024. + mov txtsiz,r0 + ash $6,r0 + mov r0,txtsiz + add $17777,r0 + bic $17777,r0 + mov r0,rtxtsiz + mov datsiz,r0 + ash $6,r0 + mov r0,datsiz + mov stksiz,r0 + ash $6,r0 + mov r0,stksiz + mov *locfpsr,r0 + bic $!200,r0 + mov r0,fpsr + br loop +9: +loop: + clr error + jsr pc,readlin + jsr pc,readexp + tst error + bne errexit + mov $1,count + cmpb r0,$', + bne 2f + movb (r4)+,r0 + mov addres,-(sp) + mov adrflg,-(sp) + jsr pc,readexp + mov addres,count + mov (sp)+,adrflg + mov (sp)+,addres + tst error + bne errexit +2: + movb (r4),r0 + jsr pc,command + tst error + beq loop +errexit: + sys signal; 2; errexit + mov savsp,sp + jsr r5,mesg; ; .even + br loop + +fnfnd: + jsr r5,mesg; ; .even +ex: + sys exit + +readlin: + mov $inbuf,r4 +1: + mov ttyfin,r0 + sys read; ch; 1 + tst r0 + beq ex + cmpb ch,$'\n + beq 1f + movb ch,(r4)+ + br 1b +1: + clrb (r4) + mov $inbuf,r4 + rts pc + +switch: + mov (r5)+,r1 +2: + cmp r0,(r1)+ + bne 1f + tst (sp)+ + jmp *(r1) +1: + tst (r1)+ + bne 2b + rts r5 + +readexp: + mov $'+,lastop + clr addres + clr starmod + clr taddr + clr adrflg +nextxp: + movb (r4)+,r0 + cmp r0,$'0 + blt 1f + cmp r0,$'9 + ble numin + cmp r0,$'a + blt 1f + cmp r0,$'z + bgt 1f + jmp letin +1: + cmp r0,$'a-40 + blt 1f + cmp r0,$'z-40 + ble letin +1: + jsr r5,switch; expsw + tstb -(r4) + tst starmod + beq 1f + mov dot,taddr + br operand +1: + rts pc + +expsw: + '+; opex + '-; opex + ' ; nextxp + '.; letin + '_; letin + '^; circumf + '*; star + -1; 0 + +star: + mov pc,starmod + br nextxp + +operand: + inc adrflg + tst starmod + beq 1f + clr starmod + bis bytemod,error + jsr r5,get; taddr + tst error + bne 1f + mov r0,taddr +1: + cmp lastop,$'+ + beq 1f + sub taddr,addres + br 2f +1: + add taddr,addres +2: + mov $'+,lastop + br nextxp + +circumf: + mov dot,taddr + dec taddr + tst bytemod + bne operand + dec taddr + br operand + +numin: + clr r1 + clr r3 +1: + sub $'0,r0 + asl r1 + asl r1 + asl r1 + mpy $10.,r3 + bis r0,r1 + add r0,r3 + movb (r4)+,r0 + cmp r0,$'0 + blo 1f + cmp r0,$'9 + blos 1b +1: + cmp r0,$'. + bne 1f + mov r3,r1 + inc r4 +1: + mov r1,taddr + dec r4 + br operand + +letin: + dec r4 + mov $nambuf,namstrt +letin1: + mov $symbol,r1 + clr (r1)+ + clr (r1)+ + clr (r1)+ + clr (r1) + mov $symbol,r1 + mov $8.,-(sp) + br 2f +1: + tstb (r4)+ + cmpb (r4),$'. + beq 2f + cmpb (r4),$'0 + blo 3f + cmpb (r4),$'9 + blos 2f + cmpb (r4),$'A + blo 3f + cmpb (r4),$'Z + blos 2f + cmpb (r4),$'_ + beq 2f + cmpb (r4),$'a + blo 3f + cmpb (r4),$'z + bhi 3f +2: + dec (sp) + blt 1b + movb (r4),(r1)+ + br 1b +3: + tst (sp)+ + jsr pc,lookupn + tst error + bne 1f + cmpb (r4),$'; + beq 2f +1: + jmp operand +2: + tstb (r4)+ + mov r1,namstrt + br letin1 + +opex: + mov r0,lastop + jmp nextxp + + +command: + jsr r5,switch; comsw + inc error + rts pc + +comsw: + '/; slash + '\\; bslash + '?; quest + '\0; newln + '^; circumf + '=; equal + ':; colon + '!; excla + ''; squote + '"; dquote + '$; dolr + '&; amper + '%; ex + '`; grave + -1; 0 + +dolr: + mov sigp,r1 + bic $!17,r1 + asl r1 + mov traptab(r1),r1 + jsr pc,string + jsr pc,pnl + mov $doltab,r5 +1: + mov (r5)+,r1 + beq 1f + jsr pc,*(r5)+ + br 1b + .if fpp +1: + mov (r5)+,r1 + beq 1f + ldfps fpsr + jsr pc,*(r5)+ + br 1b +1: + mov (r5)+,r1 + jsr pc,*(r5)+ + .endif +1: + rts pc + +traptab: + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + 1f; .data; 1:; .text + +locps: regbuf+1776 +locpc: regbuf+1774 +locr0: regbuf+1772 +locr1: regbuf+1766 +locr2: regbuf+1750 +locr3: regbuf+1752 +locr4: regbuf+1754 +locsp: regbuf+1764 +locr5: regbuf+1756 +locfpsr: regbuf+4 +locfr0: regbuf+6 +locfr4: regbuf+16 +locfr5: regbuf+26 +locfr1: regbuf+36 +locfr2: regbuf+46 +locfr3: regbuf+56 + +doltab: + 1f; prgreg; locsp; .data; 1:; .text + 1f; proct; locps; .data; 1:; .text + 1f; prgreg; locpc; .data; 1:; .text + 1f; prgreg; locr0; .data; 1:; .text + 1f; prgreg; locr1; .data; 1:; .text + 1f; prgreg; locr2; .data; 1:; .text + 1f; prgreg; locr3; .data; 1:; .text + 1f; prgreg; locr4; .data; 1:; .text + 1f; prgreg; locr5; .data; 1:; .text + 0 + .if fpp + 1f; prfreg; locfr0; .data; 1:; .text + 1f; prfreg; locfr1; .data; 1:; .text + 1f; prfreg; locfr2; .data; 1:; .text + 1f; prfreg; locfr3; .data; 1:; .text + 1f; prfreg; locfr4; .data; 1:; .text + 1f; prfreg; locfr5; .data; 1:; .text + 0 + 1f; proct; locfpsr; .data; 1:; .text + .endif +.data +.even +.text + + .if fpp +prfreg: + mov *(r5)+,r4 + movf (r4),fr0 + cfcc + beq 1f + jsr pc,string + jsr pc,printf + jsr pc,pnl +1: + rts pc + .endif + +prgreg: + jsr pc,string + mov *(r5)+,r4 + mov (r4),r0 + jsr pc,printo + mov (r4),r0 + jsr pc,lookupv + tst r2 + beq 1f + jsr r5,mesg; < \0>; .even + mov (r4),r0 + jsr pc,pname +1: + jsr pc,pnl + rts pc + +proct: + jsr pc,string + mov *(r5)+,r4 + mov (r4),r0 + jsr pc,printo + jsr pc,pnl + rts pc + +string: + movb (r1)+,r0 + beq 1f + jsr pc,putc + br string +1: + rts pc + +putc: + mov r0,och + mov $1,r0 + sys write; och; 1 + rts pc + +equal: + jsr r5,coleq; printo + rts pc +amper: + clr bytemod + mov $2,incdot + jsr r5,cycle; asymp + rts pc + +asymp: + jsr pc,pname + jsr pc,pnl + rts pc + +bslash: + inc bytemod + mov $1,incdot + br 1f + +slash: + clr bytemod + mov $2,incdot +1: + jsr r5,cycle; octp + rts pc + +grave: + clr bytemod + mov $2,incdot + jsr r5,cycle; decp + rts pc + +quest: + clr bytemod + jsr r5,cycle; psym + rts pc + +decp: + jsr pc,printd + jsr r5,mesg; <.\n\0>; .even + rts pc + +octp: + jsr pc,printo + jsr pc,pnl + rts pc + +newln: + tst adrflg + bne 1f + add incdot,dot +1: + mov nlcom,r0 + jmp command + +excla: + tst adrflg + bne 1f +2: + inc error + rts pc +1: + bit $1,dot + beq 1f + tst bytemod + beq 2b +1: + jsr r5,put; dot; addres + rts pc + +squote: + inc bytemod + mov $1,incdot + br 2f +dquote: + clr bytemod + mov $2,incdot +2: + jsr r5,cycle; ascp + rts pc + +ascp: + mov r0,-(sp) + jsr pc,ascp1 + mov (sp)+,r0 + tst bytemod + bne 1f + swab r0 + jsr pc,ascp1 +1: + cmp count,$1 + bgt 1f + jsr pc,pnl +1: + rts pc + +ascp1: + bic $!377,r0 + cmp r0,$'\n + beq 2f + cmp r0,$011 + beq 2f + cmp r0,$40 + blo 1f + cmp r0,$177 + bhis 1f +2: + jsr pc,putc + rts pc +1: + mov r0,r1 + jsr r5,mesg; <\\\0> + clr r0 + alsc $10.,r0 + add $'0,r0 + jsr pc,putc + clr r0 + alsc $3,r0 + add $'0,r0 + jsr pc,putc + clr r0 + alsc $3,r0 + add $'0,r0 + jsr pc,putc + rts pc + +colon: + jsr r5,coleq; pname + rts pc + +coleq: + jsr pc,setadr + mov addres,r0 + jsr pc,*(r5)+ + jsr pc,pnl + rts r5 + +cycle: + mov r0,nlcom + jsr pc,setadr + mov addres,dot + tst bytemod + bne 1f + bic $1,dot +1: + jsr r5,get; dot + tst error + bne 1f + tst bytemod + beq 2f + bic $!377,r0 +2: + jsr pc,*(r5) + tst error + bne 1f + dec count + ble 1f + add incdot,dot + br 1b +1: + tst (r5)+ + rts r5 + +setadr: + tst adrflg + bne 1f + mov dot,addres +1: + rts pc + + .if fpp +printf: + ldfps $200 / round+double + mov r4,-(sp) + mov r3,-(sp) + movif $10.,r3 + movif $1,r2 + clr r4 + tstf r0 + cfcc + beq 2f + bge 1f + negf r0 + mov $'-,r0 + jsr pc,putc +1: + cmpf r3,r0 + cfcc + bgt 1f + inc r4 + divf r3,r0 + br 1b +1: + cmpf r2,r0 + cfcc + ble 2f + dec r4 + mulf r3,r0 + br 1b +2: + modf r2,r0 + movfi r1,r0 + add $'0,r0 + jsr pc,putc + mov $'.,r0 + jsr pc,putc + mov $8.,r3 +1: + modf r3,r0 + movfi r1,r0 + add $'0,r0 + jsr pc,putc + dec r3 + bgt 1b + mov $'E,r0 + jsr pc,putc + mov r4,r0 + mov (sp)+,r3 + mov (sp)+,r4 + br printd + .endif + +printd: + mov r1,-(sp) + mov r0,r1 + bpl 1f + neg r1 + mov $'-,r0 + jsr pc,putc +1: + jsr pc,1f + mov (sp)+,r1 + rts pc +1: + clr r0 + dvd $10.,r0 + mov r1,-(sp) + mov r0,r1 + beq 1f + jsr pc,1b +1: + mov (sp)+,r0 + add $'0,r0 + jsr pc,putc + rts pc + diff --git a/source/s1/db2.s b/source/s1/db2.s new file mode 100644 index 0000000..d612a59 --- /dev/null +++ b/source/s1/db2.s @@ -0,0 +1,375 @@ +/ db2 -- debugger + +lookupn: + cmp symbol,$'. + bne 1f + mov dot,taddr + rts pc +1: + tst error + beq 1f + rts pc +1: + mov r2,-(sp) + mov namstrt,r1 + mov namsiz,r2 + jsr pc,1f + mov (sp)+,r2 + rts pc +1: + mov $symbol,r0 + cmp (r0)+,(r1)+ + bne 2f + cmp (r0)+,(r1)+ + bne 3f + cmp (r0)+,(r1)+ + bne 4f + cmp (r0)+,(r1)+ + bne 5f + tst (r1)+ + mov (r1)+,taddr + rts pc +2: + tst (r1)+ +3: + tst (r1)+ +4: + tst (r1)+ +5: + cmp (r1)+,(r1)+ + cmp r1,r2 + blo 1b + inc error + clr taddr + rts pc + +lookupv: + mov r5,-(sp) + mov $nambuf,r5 + clr r2 + mov $177777,r3 +1: + cmp r5,namsiz + bhis 4f + mov 12(r5),r1 + sub r0,r1 + neg r1 + blt 3f + cmp r1,r3 + bhi 3f + cmp r1,$4000 + bhis 3f + cmp r2,r5 + bhi 3f + mov r1,r3 + mov r5,r2 +3: + add $14,r5 + br 1b +4: + mov (sp)+,r5 + rts pc + +get: + mov *(r5)+,r0 + jsr r5,remap + tst error + bne 2f + mov r0,0f + mov curfin,r0 + sys seek; 0:0; 0 + bec 1f +2: + inc error + rts r5 +1: + mov curfin,r0 + sys read; temp; 2 + bes 2b + tst r0 + beq 2b + mov temp,r0 + rts r5 + +remap: + mov dbfin,curfin + cmp getoff,$1024. + bne 1f + cmp r0,txtsiz + bhis 2f + add $20,r0 + mov symfin,curfin + rts r5 +2: + cmp r0,rtxtsiz + blo 3f + sub rtxtsiz,r0 + cmp r0,datsiz + bhis 2f + add $1024.,r0 + rts r5 +2: + add rtxtsiz,r0 + neg r0 + cmp r0,stksiz + bhi 3f + neg r0 + add datsiz,r0 + add stksiz,r0 + add $1024.,r0 + rts r5 +1: + add getoff,r0 + rts r5 +3: + inc error + rts r5 + +printo: + mov $obuf+6,r1 + clr r2 +1: + inc r2 + movb r0,-(r1) + bicb $!7,(r1) + bisb $'0,(r1) + clc + ror r0 + asr r0 + asr r0 + bne 1b + mov r2,0f+2 + mov r1,0f + mov $1,r0 + sys write; 0:obuf; 6 + rts pc + +mesg: + movb (r5)+,r0 + beq 1f + jsr pc,putc + br mesg +1: + inc r5 + bic $1,r5 + rts r5 + +pnl: + jsr r5,mesg; <\n\0> + rts pc + +psp: + jsr r5,mesg; < \0> + rts pc + +pstar: + jsr r5,mesg; <*\0> + rts pc + +plp: + jsr r5,mesg; <(\0> + rts pc + +prp: + jsr r5,mesg; <)\0> + rts pc + +pb: + jsr r5,mesg; + rts pc + +pcom: + jsr r5,mesg; <,\0> + rts pc + +put: + mov *(r5)+,r0 + jsr r5,remap + tst error + bne 2f + cmp curfin,dbfin + bne 2f + mov r0,0f + mov dbfout,r0 + bne 1f +2: + tst (r5)+ +3: + inc error + rts r5 +1: + tst error + bne 3b + sys seek; 0:0; 0 + bes 2b + mov (r5)+,0f + mov dbfout,r0 + tst bytemod + beq 1f + mov $1,0f+2 + br 2f +1: + mov $2,0f+2 +2: + sys write; 0:0; 2 + bes 3b + rts r5 + +decodadr: + mov r0,r3 + mov r3,-(sp) + bic $!10,(sp) + bic $!7,r0 + cmp r0,$7 + beq pcadr +7: + mov r3,r0 + asr r0 + asr r0 + asr r0 + bic $!6,r0 + jmp *1f(r0) + +1: + simp + incr + decr + indx + +simp: + tst (sp) + beq 1f + jsr pc,plp +1: + jsr pc,preg + tst (sp)+ + beq 9f + jsr pc,prp + br 9f + +incr: + tst (sp)+ + beq 1f + jsr pc,pstar +1: + jsr pc,plp + jsr pc,preg + jsr r5,mesg; <)+\0>; .even + br 9f + +decr: + tst (sp)+ + beq 1f + jsr pc,pstar +1: + jsr r5,mesg; <-(\0>; .even + jsr pc,preg + jsr pc,prp + br 9f + +indx: + tst (sp)+ + beq 1f + jsr pc,pstar +1: + jsr pc,get1 + jsr pc,pname + jsr pc,plp + jsr pc,preg + jsr pc,prp + br 5f + +pcadr: + mov r3,r0 + bit $20,r3 + beq 7b + tst (sp)+ + beq 1f + jsr pc,pstar +1: + bit $40,r3 + bne 6f + jsr r5,mesg; <$\0> + jsr pc,get1 + jsr pc,pname + br 5f +6: + jsr pc,get1 + add $2,r0 + add r1,r0 + mov $3,r1 + jsr pc,pname + br 5f +9: + tst (r5)+ + clr r0 + rts r5 +5: + mov $2,r0 + rts r5 + +preg: + mov r3,r0 + bic $!7,r0 + asl r0 + mov regtab(r0),obuf + mov $1,r0 + sys write; obuf; 2 + rts pc + +regtab: + "r0 + "r1 + "r2 + "r3 + "r4 + "r5 + "sp + "pc + +pname: + mov r5,-(sp) + mov r3,-(sp) + mov r1,-(sp) + jsr pc,lookupv + tst r2 + beq 5f + cmp (sp),$1 + bne 1f + tst r3 + bne 5f +1: + mov r2,r1 + mov $8,-(sp) + mov r0,r5 +1: + movb (r1)+,r0 + beq 1f + jsr pc,putc + dec (sp) + bne 1b +1: + tst (sp)+ + cmp 12(r2),r5 + beq 1f + blt 2f + jsr r5,mesg; <-\0> + br 3f +2: + jsr r5,mesg; <+\0> +3: + mov r3,r0 +5: + jsr pc,printo +1: + tst (sp)+ + mov (sp)+,r3 + mov (sp)+,r5 + rts pc + +get1: + mov *(r5)+,r1 + add $2,r1 + mov r1,temp + jsr r5,get; temp + rts pc diff --git a/source/s1/db3.s b/source/s1/db3.s new file mode 100644 index 0000000..98e859e --- /dev/null +++ b/source/s1/db3.s @@ -0,0 +1,330 @@ +/ db3 -- debugger + +psym: + mov $2,incdot + jsr pc,prints + jsr pc,pnl + rts pc + +prints: + mov r0,-(sp) + mov $optab,r1 +1: + mov (sp),r0 + bic (r1)+,r0 + cmp (r1)+,r0 + bne 2f + mov (r1)+,-(sp) + jsr pc,string + jmp *(sp)+ +2: + add $8.,r1 + br 1b + +optab: + 107777; 010000; double; + 107777; 020000; double; + 107777; 030000; double; + 107777; 040000; double; + 107777; 050000; double; + 007777; 060000; double; + 007777; 160000; double; + + 100077; 005000; single; + 100077; 005100; single; + 100077; 005200; single; + 100077; 005300; single; + 100077; 005400; single; + 100077; 005500; single; + 100077; 005600; single; + 100077; 005700; single; + 100077; 006000; single; + 100077; 006100; single; + 100077; 006200; single; + 100077; 006300; single; + 000077; 000100; single; + 000077; 000300; single; + 000077; 170100; singlw; + 000077; 170200; singlw; + 000077; 170300; singlw; + 000077; 170400; singlw; + 000077; 170500; singlw; + 000077; 170600; singlw; + 000077; 170700; singlw; + 000077; 006700; singlw; + 000077; 006600; singlw; + 000077; 106600; singlw; + 000077; 006500; singlw; + 000077; 106500; singlw; + 000777; 070000; muldiv; + 000777; 071000; muldiv; + 000777; 072000; muldiv; + 000777; 073000; muldiv; + + 000377; 000400; branch; + 000377; 001000; branch; + 000377; 001400; branch; + 000377; 002000; branch; + 000377; 002400; branch; + 000377; 003000; branch; + 000377; 003400; branch; + 000377; 100000; branch; + 000377; 100400; branch; + 000377; 101000; branch; + 000377; 101400; branch; + 000377; 102000; branch; + 000377; 102400; branch; + 000377; 103000; branch; + 000377; 103400; branch; + + 000000; 000000; noaddr; + 000000; 000001; noaddr; + 000000; 000002; noaddr; + 000000; 000004; noaddr; + 000000; 000005; noaddr; + + 000377; 171000; fltrev; + 000377; 171400; fltrev; + 000377; 172000; fltrev; + 000377; 172400; fltrev; + 000377; 173000; fltrev; + 000377; 173400; fltrev; + 000377; 174000; fltnor; + 000377; 174400; fltrev; + 000377; 175000; fltnor; + 000377; 175400; fltnor; + 000377; 176000; fltnor; + 000377; 176400; fltrev; + 000377; 177000; fltrev; + 000377; 177400; fltrev; + 000000; 170000; noaddr; + 000000; 170001; noaddr; + 000000; 170002; noaddr; + 000000; 170011; noaddr; + 000000; 170012; noaddr; + + 000777; 004000; specl1; + 000777; 074000; specl1; + 000007; 000200; specl2; + 000017; 000240; specl3; + 000017; 000260; specl3; + 000377; 104000; specl4; + 000377; 104400; specl5; + 000077; 006400; specl7; + 000777; 077000; specl8; + 000007; 000230; specl9; + 177777; 000000; specl6; + +fltrev: + bic $!377,(sp) +muldiv: + jsr pc,psp + mov (sp)+,r0 + asl r0 + asl r0 + swab r0 + aslb r0 + aslb r0 + aslb r0 + aslb r0 + asr r0 + asr r0 + asr r0 + asr r0 + bic $!7707,r0 + mov r0,-(sp) + br fltnor1 + +fltnor: + bic $!377,(sp) + br 1f + +double: + tst (sp) + bge 1f + jsr pc,pb +1: + jsr pc,psp + mov (sp),r0 +fltnor1: + als $-6,r0 + jsr r5,decodadr; dot + add r0,incdot + add dot,r0 + mov r0,temp + jsr pc,pcom + mov (sp)+,r0 + jsr r5,decodadr; temp + add r0,incdot + rts pc + +single: + tst (sp) + bge singlw + jsr pc,pb +singlw: + jsr pc,psp + mov (sp)+,r0 + jsr r5,decodadr; dot + add r0,incdot + rts pc + +specl8: / sob + jsr pc,psp + mov (sp),r3 + als $-6,r3 + jsr pc,preg + jsr pc,pcom + mov (sp)+,r0 + bic $!77,r0 + neg r0 + br 1f + +branch: + jsr pc,psp + mov (sp)+,r0 + bic $!377,r0 + bit $200,r0 + beq 1f + bis $177400,r0 +1: + inc r0 + asl r0 + add dot,r0 + jsr pc,pname + rts pc + +noaddr: + tst (sp)+ + rts pc + +specl1: / jsr + jsr pc,psp + mov (sp),r3 + als $-6,r3 + jsr pc,preg + jsr pc,pcom + mov (sp)+,r0 + jsr r5,decodadr; dot + add r0,incdot + rts pc + +specl2: / rts + jsr pc,psp + mov (sp)+,r3 + jsr pc,preg + rts pc + +specl3: / opr + jsr pc,psp + mov (sp)+,r2 + mov $3f,r1 +1: + bit $17,r2 + beq 1f + bit $10,r2 + beq 2f + movb (r1),r0 + jsr pc,putc +2: + inc r1 + asl r2 + br 1b +1: + rts pc +3: + + +specl7: / mark + bic $!77,(sp) + br specl4 + +specl9: / spl + bic $!7,(sp) + br specl4 + +specl4: / emt + jsr pc,psp + mov (sp)+,r0 + bic $!377,r0 +8: + jsr pc,printo + rts pc + +specl5: / sys + jsr pc,psp + mov (sp)+,r2 + bic $!377,r2 + mov r2,r0 + asl r2 + asl r2 + cmp r2,$esystab-systab + bhis 8b + mov systab(r2),r1 + jsr pc,string + mov systab+2(r2),-(sp) + mov dot,temp1 +1: + dec (sp) + bge 2f + tst (sp)+ + rts pc +2: + jsr r5,mesg; <;\0> + add $2,temp1 + add $2,incdot + jsr r5,get; temp1 + jsr pc,pname + br 1b + +systab: + 1f; 0; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 2; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 1; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 0; .data; 1:; .text + 1f; 0; .data; 1:; .text +esystab: +.data +.even +.text + +specl6: / unknown + jsr pc,psp + mov (sp)+,r0 + jsr pc,printo + rts pc diff --git a/source/s1/db4.s b/source/s1/db4.s new file mode 100644 index 0000000..012e528 --- /dev/null +++ b/source/s1/db4.s @@ -0,0 +1,54 @@ +/ db4 -- debugger + +maxsym = 24000. +core: + +a.out: + +.even +zero: 0 +.bss +regbuf: + .=.+1024. +sigp = regbuf+310 +txtsiz = regbuf+322 +datsiz = regbuf+324 +stksiz = regbuf+326 +rtxtsiz: .=.+2 +.data +objmagic: 407 +nobjmagic: 410 +namsiz: nambuf +incdot: 2 +nlcom: '/ + + .bss + +starmod:.=.+2 +symbol: .=.+10. +getoff: .=.+2 +namstrt: .=.+2 +bytemod: .=.+2 +savsp: .=.+2 +error: .=.+2 +ttyfin: .=.+2 +dbfin: .=.+2 +symfin: .=.+2 +curfin: .=.+2 +dbfout: .=.+2 +ch: .=.+2 +lastop: .=.+2 +addres: .=.+2 +taddr: .=.+2 +adrflg: .=.+2 +fpsr: .=.+2 +och: .=.+2 +dot: .=.+2 +count: .=.+2 +syscnt: .=.+2 +temp: .=.+2 +temp1: .=.+2 +obuf: .=.+8. +inbuf: .=.+128. +nambuf: .=.+20 + diff --git a/source/s1/dc1.s b/source/s1/dc1.s new file mode 100644 index 0000000..683ac30 --- /dev/null +++ b/source/s1/dc1.s @@ -0,0 +1,2542 @@ +.globl log2 +.globl getchar +.globl lookchar +.globl fsfile +.globl seekchar +.globl backspace +.globl putchar +.globl alterchar +.globl move +.globl rewind +.globl create +.globl zero +.globl allocate +.globl release +.globl collect +.globl w, r, a, l +/ + cmp (sp)+,$2 + blo 1f + tst (sp)+ + mov (sp)+,0f + cmpb *0f,$'- + beq 8f + sys 0; 9f +.data +9: + sys open; 0:.=.+2; 0 +.text + bec 2f + mov $1,r0 + sys write; 4f; 5f-4f + sys exit + +/ +4: +5: .even +/ +2: + mov r0,source +1: + sys signal; 2; 1 + ror r0 + bcs 1f + sys signal; 2; case177 +1: +8: + clr delflag + mov $pdl,r5 +/ + mov $10.,r0 + jsr pc,log2 + mov r0,log10 + mov $1,r0 + jsr pc,allocate + mov r1,scalptr + clr r0 + jsr pc,putchar + clr r0 + jsr pc,allocate + mov r1,basptr + mov $10.,r0 + jsr pc,putchar + mov $1,r0 + jsr pc,allocate + mov r1,inbas + mov $10.,r0 + jsr pc,putchar + mov $1,r0 + jsr pc,allocate + mov $10.,r0 + jsr pc,putchar + mov r1,tenptr + clr r0 + jsr pc,allocate + mov r1,chptr + clr r0 + jsr pc,allocate + mov r1,strptr + mov $1,r0 + jsr pc,allocate + mov $2,r0 + jsr pc,putchar + mov r1,sqtemp + clr r0 + jsr pc,allocate + mov r1,divxyz +loop: + tst delflag + bne in177 + mov sp,errstack + jsr pc,readc + mov $casetab,r1 +1: tst (r1)+ + beq 2f + cmp r0,(r1)+ + bne 1b + jmp *-4(r1) +2: jmp eh +/ +/ +/ case for new line (which is special for apl box) +/ +case012: + br loop +/ +/ +/ case q for quit +/ +case161: + cmp readptr,$readstack+2 + blos 1f + mov *readptr,r1 + beq 2f + jsr pc,release +2: + sub $2,readptr + mov *readptr,r1 + beq 2f + jsr pc,release +2: + sub $2,readptr + jmp loop +1: + sys exit +/ +/ +/ case Q for controlled quit +/ +case121: + jsr pc,pop + jes eh + jsr pc,length + cmp r0,$2 + jhi eh1 + jsr pc,rewind + jsr pc,getchar + jmi eh1 + jsr pc,release +1: + cmp readptr,$readstack + jlos eh + mov *readptr,r1 + beq 2f + jsr pc,release +2: + sub $2,readptr + sob r0,1b + jbr loop +/ +/ +/ case of delete character +/ +case177: + sys signal; 2; case177 + mov $1,delflag + mov r0,-(sp) + mov 2(sp),r0 + cmp -6(r0),$sys+read + bne 1f + sub $6,2(sp) + clr delflag +1: + mov (sp)+,r0 + 2 /rti +/ +in177: + mov $' ,ch + mov $1,r0 + sys write; 1f; 1 + clr delflag + jmp eh +/ +.bss +delflag: .=.+2 +.text +1: <\n> + .even +/ +/ +/ case digit +/ +case060: + movb r0,savec + jsr pc,readin + jsr pc,push + br loop +/ +/ +/ case _ for negative numbers +/ +case137: + jsr pc,readin + jsr pc,fsfile + jsr pc,backspace + mov r0,savk + dec w(r1) + jsr pc,chsign + mov savk,r0 + jsr pc,putchar + jsr pc,push + jbr loop +/ +/ +/ case screamer +/ +case041: + jsr pc,in041 + jbr loop +/ +in041: + jsr pc,readc + cmp r0,$'< + jeq in74a + cmp r0,$'= + jeq in75a + cmp r0,$'> + jeq in76a +/ + mov $field,r1 + movb r0,(r1)+ +1: + jsr pc,readc + movb r0,(r1)+ + cmpb r0,$'\n + bne 1b + clrb (r1)+ +/ + sys fork + br 9f + sys wait + mov $1,r0 + sys write; screamer; 2 + rts pc +9: sys exec; 6f; 8f + sys exit +.data +8: 6f; 7f; field; 0 +6: +7: <-c\0> +screamer: + .even +.bss +field: .=.+70. +.text +/ +/ +/ case d for duplicate +/ +case144: + cmp r5,$pdl + jeq eh + clr r0 + jsr pc,allocate + mov -2(r5),r0 + jsr pc,move + jsr pc,push + jmp loop +/ +/ +/ case z for stack size +/ +case172: + clr r0 + jsr pc,allocate + mov r5,r3 + sub $pdl,r3 + asr r3 +2: + beq 2f + clr r2 + dvd $100.,r2 + mov r3,r0 + jsr pc,putchar + mov r2,r3 + br 2b +2: + clr r0 + jsr pc,putchar + jsr pc,push + jmp loop +/ +/ +/ case c for flush +/ +case143: +2: jsr pc,pop + jes loop + jsr pc,release + br 2b +/ +/ case s for save +/ +case163: + tst sfree + bne 1f + jsr pc,sinit +1: + jsr pc,readc + cmp r5,$pdl + bne 2f + movb $'s,ch + jmp eh +2: + clr r2 + cmpb r0,$128. / check for array + blo 1f + inc r2 +1: + asl r0 + mov stable(r0),r1 + beq 2f + mov r1,r0 + mov 2(r0),r1 + tst r2 + beq 4f + mov r1,-(sp) / have array - release elements + jsr pc,rewind +1: + mov (sp),r1 +3: + jsr pc,getword + bes 1f + tst r0 + beq 3b + mov r0,r1 + jsr pc,release + br 1b +1: + mov (sp)+,r1 +4: + jsr pc,release + jsr pc,pop + mov r1,2(r0) + jbr loop +2: + mov sfree,stable(r0) + mov stable(r0),r0 + mov (r0),sfree + beq symout + clr (r0) + jsr pc,pop + mov r1,2(r0) + jmp loop +/ +symout: + mov $1,r0 + sys write; 7f; 8f-7f + jmp reset +/ +7: +8: .even +/ +/ +sinit: + mov $sfree+4,r0 +1: + mov r0,-4(r0) + clr -2(r0) + add $4,r0 + cmp r0,$sfend + blos 1b + clr sfend-4 + rts pc +/ +/ +.bss +sfree: .=.+512. +sfend: +.text +/ +/ +/ case S for save +/ +case123: + tst sfree + bne 1f + jsr pc,sinit +1: + jsr pc,readc + cmp r5,$pdl + bne 2f + movb $'S,ch + jbr eh +2: + clr r3 + cmp r0,$128. / check for array + blo 1f + inc r3 +1: + asl r0 + mov stable(r0),r1 + beq 2f + mov sfree,r2 + mov (r2),sfree + beq symout + mov stable(r0),(r2) + mov r2,stable(r0) + jsr pc,pop + tst r3 + beq 1f + jsr pc,length / to make auto arrays work + cmp r0,$1 + bhi 1f + jsr pc,zero +1: + mov r1,2(r2) + jbr loop +2: + mov sfree,stable(r0) + mov stable(r0),r2 + mov (r2),sfree + beq symout + clr (r2) + jsr pc,pop + tst r3 + beq 1f + jsr pc,length + cmp r0,$1 + bhi 1f + jsr pc,zero +1: + mov r1,2(r2) + jbr loop +/ +/ +/ case l for load +/ +case154: + jsr pc,in154 + jmp loop +/ +in154: + jsr pc,readc + clr r2 + cmp r0,$128. / check for array + blo 1f + inc r2 +1: + asl r0 + mov stable(r0),r1 + beq 1f + mov 2(r1),r1 + mov r1,-(sp) + jsr pc,length + jsr pc,allocate + tst r2 + beq 2f + mov r1,-(sp) / have array - copy elements + mov 2(sp),r1 + jsr pc,rewind +3: + mov 2(sp),r1 + jsr pc,getword + bes 3f + tst r0 + beq 4f + mov r0,-(sp) + mov r0,r1 + jsr pc,length + jsr pc,allocate + mov (sp)+,r0 + jsr pc,move + mov r1,r0 + mov (sp),r1 + jsr pc,putword + br 3b +4: + clr r0 + mov (sp),r1 + jsr pc,putword + br 3b +3: + mov (sp)+,r1 + jsr pc,push + tst (sp)+ + rts pc +2: + mov (sp)+,r0 + jsr pc,move + jsr pc,push + rts pc +1: + clr r0 + jsr pc,allocate + jsr pc,putword + jsr pc,push + rts pc +/ +/ case : for save array +/ +case072: + tst sfree + bne 1f + jsr pc,sinit +1: + jsr pc,pop + jes eh + jsr pc,scalint + jsr pc,fsfile + jsr pc,backspace + tst r0 + jmi eh1 / neg. index + jsr pc,length + cmp r0,$2 + jhi eh1 / index too high + jsr pc,fsfile + clr r3 + cmp r0,$1 + blo 1f + beq 2f + jsr pc,backspace + mov r0,r3 + mul $100.,r3 +2: + jsr pc,backspace + add r0,r3 + cmp r3,$2048. + jhis eh1 / index too high + asl r3 +1: + jsr pc,release + jsr pc,readc + cmp r5,$pdl + bne 2f + movb $':,ch + jmp eh +2: + asl r0 + mov stable(r0),r1 + beq 2f + mov r1,-(sp) + mov 2(r1),r1 + mov l(r1),r0 + sub a(r1),r0 + sub $2,r0 + cmp r3,r0 + blos 1f + mov r1,-(sp) / need more space + mov r3,r0 + add $2,r0 + jsr pc,allocate + jsr pc,zero + mov (sp)+,r0 + jsr pc,move + mov r1,-(sp) + mov r0,r1 + jsr pc,release + mov (sp)+,r1 +1: + mov r1,-(sp) + mov r3,r0 + jsr pc,seekchar + jsr pc,getword + bes 1f + sub $2,r(r1) + tst r0 + beq 1f + mov r0,r1 + jsr pc,release +1: + jsr pc,pop + jes eh + mov r1,r0 + mov (sp)+,r1 + jsr pc,alterchar + swab r0 + jsr pc,alterchar + mov (sp)+,r0 + mov r1,2(r0) + jmp loop +2: + mov sfree,stable(r0) + mov stable(r0),r0 + mov (r0),sfree + jeq symout + clr (r0) + mov r0,-(sp) + mov r3,r0 + add $2,r0 + jsr pc,allocate + jsr pc,zero + sub $2,r0 + jsr pc,seekchar + mov r1,-(sp) + br 1b +/ +/ case ; for load array +/ +case073: + tst sfree + bne 1f + jsr pc,sinit +1: + jsr pc,pop + jes eh + jsr pc,scalint + jsr pc,fsfile + jsr pc,backspace + tst r0 + jmi eh1 / neg. index + jsr pc,length + cmp r0,$2 + jhi eh1 + jsr pc,fsfile + clr r3 + cmp r0,$1 + blo 1f + beq 2f + jsr pc,backspace + mov r0,r3 + mul $100.,r3 +2: + jsr pc,backspace + add r0,r3 + cmp r3,$2048. + jhis eh1 / index too high + asl r3 +1: + jsr pc,release + jsr pc,readc + asl r0 + mov stable(r0),r1 + beq 1f + mov 2(r1),r1 + jsr pc,length + sub $2,r0 + cmp r3,r0 + bhi 1f / element not here + mov r3,r0 + jsr pc,seekchar + jsr pc,getword + tst r0 + beq 1f + mov r0,r1 + mov r1,-(sp) + jsr pc,length + jsr pc,allocate + mov (sp)+,r0 + jsr pc,move + jsr pc,push + jmp loop +1: + clr r0 + jsr pc,allocate + jsr pc,putword + jsr pc,push + jmp loop +/ +/ +/ case L for load +/ +case114: + jsr pc,readc + clr r2 + cmp r0,$128. / check for array + blo 1f + inc r2 +1: + asl r0 + mov stable(r0),r1 + beq 4f + mov (r1),stable(r0) + mov sfree,(r1) + mov r1,sfree + mov 2(r1),r1 + tst r2 + beq 2f + mov r1,-(sp) / have array - assume a throw away + jsr pc,rewind +1: + mov (sp),r1 +3: + jsr pc,getword + bes 1f + tst r0 + beq 3b + mov r0,r1 + jsr pc,release + br 1b +1: + mov (sp)+,r1 +2: + jsr pc,push + jbr loop +4: + movb $'L,ch + jbr eh +/ +/ +/ case - for subtract +/ +case055: + jsr pc,in055 + jmp loop +/ +in055: + jsr pc,pop + jes eh + jsr pc,fsfile + jsr pc,backspace + mov r0,savk + dec w(r1) + jsr pc,chsign + mov savk,r0 + jsr pc,putchar + jsr pc,push + br in053 +/ +/ +/ case + for add +/ +case053: + jsr pc,in053 + jmp loop +/ +in053: + jsr pc,eqk + mov $add3,r0 + jsr pc,binop + jsr pc,pop + mov savk,r0 + jsr pc,putchar + jsr pc,push + rts pc +/ +/ +/ case * for multiply +/ +case052: + jsr pc,pop + jes eh + mov r1,-(sp) + jsr pc,pop + jec 1f + mov (sp)+,r1 + jsr pc,push + jbr eh +1: + jsr pc,fsfile + jsr pc,backspace + mov r0,savk2 + dec w(r1) + mov r1,r2 + mov (sp)+,r1 + jsr pc,fsfile + jsr pc,backspace + mov r0,savk1 + dec w(r1) + mov r1,r3 + mov $mul3,r0 + jsr pc,binop + jsr pc,pop + cmp savk1,savk2 + blo 1f + mov savk1,r2 + br 2f +1: + mov savk2,r2 +2: + cmp r2,k + bhis 1f + mov k,r2 +1: + add savk2,savk1 + cmp r2,savk1 + bhis 1f + mov r2,-(sp) + neg r2 + add savk1,r2 + jsr pc,removc + mov (sp)+,r0 +2: + jsr pc,putchar + jsr pc,push + jmp loop +1: + mov savk1,r0 + br 2b +/ +/ r1 = string +/ r2 = count +/ result returned in r1 (old r1 released) +/ +removc: + mov r1,-(sp) + jsr pc,rewind +1: + cmp r2,$1 + blos 1f + jsr pc,getchar + sub $2,r2 + br 1b +1: + mov $2,r0 + jsr pc,allocate + mov r1,-(sp) +1: + mov 2(sp),r1 + jsr pc,getchar + bes 1f + mov (sp),r1 + jsr pc,putchar + mov r1,(sp) + br 1b +1: + cmp r2,$1 + bne 1f + mov (sp),r3 + mov tenptr,r2 + jsr pc,div3 + mov r1,(sp) + mov r3,r1 + jsr pc,release + mov r4,r1 + jsr pc,release +1: + mov 2(sp),r1 + jsr pc,release + mov (sp)+,r1 + tst (sp)+ + rts pc +/ +/ case / for divide +/ +case057: + jsr pc,dscale + mov $div3,r0 + jsr pc,binop + mov r4,r1 + jsr pc,release + jsr pc,pop + mov savk,r0 + jsr pc,putchar + jsr pc,push + jmp loop +/ +/ +dscale: + jsr pc,pop + jes eh + mov r1,-(sp) + jsr pc,pop + bec 1f + mov (sp)+,r1 + jsr pc,push + jmp eh +1: + mov r1,-(sp) + jsr pc,fsfile + jsr pc,backspace + mov r0,savk1 + dec w(r1) + jsr pc,rewind + mov 2(sp),r1 + jsr pc,fsfile + jsr pc,backspace + mov r0,savk2 + dec w(r1) + mov k,r2 + sub savk1,r2 + add savk2,r2 + mov k,savk + mov (sp)+,r1 + tst r2 + bmi 1f + jsr pc,add0 + br 2f +1: + neg r2 + jsr pc,removc +2: + mov r1,r3 + mov (sp)+,r2 + rts pc +/ +/ +/ case % for remaindering +/ +case045: + jsr pc,dscale + mov $div3,r0 + jsr pc,binop + jsr pc,pop + jsr pc,release + mov r4,r1 + mov savk1,r0 + add k,r0 + jsr pc,putchar + jsr pc,push + jmp loop +/ +/ +binop: + jsr pc,(r0) + jsr pc,push + mov r2,r1 + jsr pc,release + mov r3,r1 + jsr pc,release + rts pc +/ +eqk: + jsr pc,pop + jes eh + mov r1,-(sp) + jsr pc,pop + bec 1f + mov (sp)+,r1 + jsr pc,push + jbr eh +1: + mov r1,-(sp) + mov 2(sp),r1 + jsr pc,fsfile + jsr pc,backspace + mov r0,savk1 + dec w(r1) + mov (sp),r1 + jsr pc,fsfile + jsr pc,backspace + mov r0,savk2 + dec w(r1) + cmp r0,savk1 + beq 1f + blo 2f + mov savk2,savk + mov r0,r2 + sub savk1,r2 + mov 2(sp),r1 + jsr pc,add0 + mov r1,2(sp) + br 4f +2: + mov savk1,r2 + sub savk2,r2 + mov (sp),r1 + jsr pc,add0 + mov r1,(sp) +1: + mov savk1,savk +4: + mov 2(sp),r3 + mov (sp)+,r2 + tst (sp)+ + rts pc +.bss +savk1: .=.+2 +savk2: .=.+2 +savk: .=.+2 +.text +/ +/ +/ r2 = count +/ r1 = ptr +/ returns ptr in r1 +add0: + mov r1,-(sp) + jsr pc,length + jsr pc,allocate + clr r0 +1: + cmp r2,$1 + blos 1f + jsr pc,putchar + sub $2,r2 + br 1b +1: + mov r1,-(sp) + mov 2(sp),r1 + jsr pc,rewind +1: + jsr pc,getchar + bes 1f + mov (sp),r1 + jsr pc,putchar + mov r1,(sp) + mov 2(sp),r1 + br 1b +1: + cmp r2,$1 + bne 1f + mov (sp),r3 + mov tenptr,r2 + jsr pc,mul3 + mov r1,(sp) + mov r3,r1 + jsr pc,release +1: + mov 2(sp),r1 + jsr pc,release + mov (sp)+,r1 + tst (sp)+ + rts pc +/ case i for input base +/ +case151: + jsr pc,in151 + jmp loop +/ +in151: + jsr pc,pop + jes eh + jsr pc,scalint + mov r1,-(sp) + mov inbas,r1 + mov (sp)+,inbas + jsr pc,release + rts pc +case111: + mov inbas,r1 + jsr pc,length + inc r0 + jsr pc,allocate + mov inbas,r0 + jsr pc,move + clr r0 + jsr pc,putchar /scale + jsr pc,push + jmp loop +/ +.bss +inbas: .=.+2 +.data +/ +/ +/ case o for output base +/ +case157: + jsr pc,in157 + jmp loop +/ +in157: + jsr pc,pop + jes eh + jsr pc,scalint + mov r1,-(sp) + jsr pc,length + jsr pc,allocate + mov (sp),r0 + jsr pc,move + jsr pc,fsfile + jsr pc,length +1: + cmp r0,$1 + beq 1f + jsr pc,backspace + bpl 2f + jsr pc,chsign + jsr pc,length + br 1b +2: + clr sav + mov r0,-(sp) +2: + jsr pc,backspace + bes 2f + mov (sp),r2 + clr r3 + mul $100.,r2 + add r0,r3 + mov r3,(sp) + tst sav + beq 3f + mov r2,r0 + clr r3 + mov sav,r2 + mul $100.,r2 + mov r3,sav + add r0,sav + br 2b +3: + mov r2,sav + br 2b +2: + mov (sp)+,r0 + tst sav + beq 2f + mov sav,r0 + jsr pc,log2 + add $16.,r0 + mov r0,logo + br 3f +1: + jsr pc,backspace +2: + tst r0 + bpl 1f + mov $15.,logo + br 3f +1: + jsr pc,log2 + mov r0,logo +3: + jsr pc,release + mov basptr,r1 + jsr pc,release + mov (sp),basptr +/ +/ set field widths for output +/ and set output digit handling routines +/ + mov (sp),r1 + mov $bigout,outdit + jsr pc,length + cmp r0,$1. + bne 2f + jsr pc,fsfile + jsr pc,backspace + cmp r0,$16. + bhi 2f + mov $hexout,outdit +2: + jsr pc,length + jsr pc,allocate + mov (sp),r0 + jsr pc,move + clr (sp) + jsr pc,fsfile + jsr pc,backspace + bpl 2f + add $1.,(sp) + jsr pc,chsign +2: + mov r1,r2 + mov $1,r0 + jsr pc,allocate + mov $-1,r0 + jsr pc,putchar + mov r1,r3 + jsr pc,add3 + jsr pc,length + asl r0 + add r0,(sp) + jsr pc,fsfile + jsr pc,backspace + cmp r0,$9. + blos 2f + add $1,(sp) +2: + jsr pc,release + mov r2,r1 + jsr pc,release + mov r3,r1 + jsr pc,release + mov (sp)+,fw + mov fw,fw1 + dec fw1 + cmp outdit,$hexout + bne 2f + mov $1,fw + clr fw1 +2: + mov $70.,ll + cmp fw,$70. + blo 9f; rts pc; 9: + mov $70.,r1 + clr r0 + dvd fw,r0 + mov r0,r1 + mpy fw,r1 + mov r1,ll + rts pc +case117: + mov basptr,r1 + jsr pc,length + inc r0 + jsr pc,allocate + mov basptr,r0 + jsr pc,move + clr r0 + jsr pc,putchar /scale + jsr pc,push + jmp loop +/ +.data +fw: 1 /field width for digits +fw1: 0 +ll: 70. /line length +.text +/ +/ +/ case k for skale factor +/ +case153: + jsr pc,pop + jes eh + jsr pc,scalint + mov w(r1),r0 + sub a(r1),r0 + cmp r0,$1 + jhi eh1 + jsr pc,rewind + jsr pc,getchar + jmi eh1 + mov r0,k + mov r1,-(sp) + mov scalptr,r1 + jsr pc,release + mov (sp)+,scalptr + jmp loop +/ +case113: + mov scalptr,r1 + jsr pc,length + inc r0 + jsr pc,allocate + mov scalptr,r0 + jsr pc,move + clr r0 + jsr pc,putchar + jsr pc,push + jmp loop +scalint: + jsr pc,fsfile + jsr pc,backspace + dec w(r1) + mov r0,r2 + jsr pc,removc + rts pc +/ +/ case ^ for exponentiation +/ +case136: + jsr pc,pop + jes eh + jsr pc,scalint + jsr pc,fsfile + jsr pc,backspace + tst r0 + bge 1f + inc negexp + jsr pc,chsign +1: + jsr pc,length + cmp r0,$3 + jhis eh1 + mov r1,r3 + jsr pc,pop + jes eh + jsr pc,fsfile + jsr pc,backspace + mov r0,savk + dec w(r1) + mov r1,r2 + jsr pc,exp3 + mov r1,-(sp) + mov r2,r1 + jsr pc,release + mov r3,r1 + jsr pc,rewind + jsr pc,getchar + mov r0,-(sp) + jsr pc,getchar + bes 2f + mov r0,r1 + mul $100.,r1 + add (sp)+,r1 + br 3f +2: + mov (sp)+,r1 +3: + mul savk,r1 + mov r1,r2 + mov r3,r1 + jsr pc,release + tst negexp + bne 4f + cmp k,savk + blo 1f + mov k,r3 + br 2f +1: + mov savk,r3 +2: + cmp r3,r2 + bhis 4f + sub r3,r2 + mov (sp)+,r1 + mov r3,-(sp) + jsr pc,removc + mov (sp)+,r0 + jsr pc,putchar + jsr pc,push + br 3f +4: + mov (sp)+,r1 + mov r2,r0 + jsr pc,putchar + jsr pc,push +3: + tst negexp + jeq loop + clr negexp + jsr pc,pop + mov r1,-(sp) + mov $2,r0 + jsr pc,allocate + mov $1,r0 + jsr pc,putchar + clr r0 + jsr pc,putchar + jsr pc,push + mov (sp)+,r1 + jsr pc,push + jmp case057 +/ +.bss +sav: .=.+2 +negexp: .=.+2 +.text +/ +/ case v for square root +/ +case166: + jsr pc,pop + jes eh +/ + jsr pc,fsfile + jsr pc,backspace + mov r0,savk + dec w(r1) + mov w(r1),r2 + sub a(r1),r2 + tst r2 + beq sqz + jsr pc,backspace + tst r0 + jmi eh1 + mov k,r2 + asl r2 + sub savk,r2 + beq 1f + blo 2f + jsr pc,add0 + br 1f +2: + neg r2 + jsr pc,removc +1: + jsr pc,sqrt + mov k,r0 + jsr pc,putchar + jsr pc,push + jmp loop +/ +/ +sqz: + mov savk,r0 + jsr pc,putchar + jsr pc,push + jmp loop +.bss +sqtemp: .=.+2 +.text +/ +/ +/ case [ for subroutine definition +/ +case133: + clr -(sp) + clr r0 + jsr pc,allocate + jsr pc,push +1: jsr pc,readc + cmp r0,$'] + bne 3f + tst (sp) + beq 1f + dec (sp) + br 2f +3: + cmp r0,$'[ + bne 2f + inc (sp) +2: + jsr pc,putchar + br 1b +/ +1: tst (sp)+ + jmp loop +/ +/ +/ case x for execute top of stack +/ +case170: + jsr pc,in170 + jmp loop +/ +in170: + jsr pc,pop + jes eh + mov r1,-(sp) + tst *readptr + beq 1f + mov *readptr,r1 + cmp r(r1),w(r1) + bne 1f + jsr pc,release + br 2f +1: + add $2,readptr + cmp readptr,$readtop + bhis 1f +2: mov (sp)+,r1 + mov r1,*readptr + beq 2f + jsr pc,rewind + rts pc +2: + jsr pc,readc + cmp r0,$'\n + beq 3f + mov r0,savec +3: + rts pc +1: +nderr: + mov $1,r0 + sys write; 1f; 2f-1f + jmp reset +1: +2: .even +/ +.data +readptr: readstack +.bss +readstack: .=.+100. +readtop: +.text +/ +/ case ? for apl box function +/ +case077: + add $2,readptr + cmp readptr,$readtop + bhis nderr + clr *readptr +in077: + mov source,-(sp) + clr source + jsr pc,readc + cmp r0,$'! + bne 1f + jsr pc,in041 + mov (sp)+,source + br in077 +1: + mov r0,savec + clr r0 + jsr pc,allocate +2: + jsr pc,readc + jsr pc,putchar +1: + jsr pc,readc + jsr pc,putchar + cmp r0,$'\\ + beq 2b + cmp r0,$'\n + bne 1b + mov (sp)+,source + mov r1,*readptr + jmp loop +/ +/ +/ case < for conditional execution +/ +case074: + jsr pc,in074 + ble neg074 + jmp aff074 +/ +/ +/ case !< for conditional execution +/ +in74a: + jsr pc,in074 + bgt inneg + jmp inaff +/ +in074: + jsr pc,in055 /go subtract + jsr pc,pop + jsr pc,length + tst r0 + beq 1f + jsr pc,fsfile + jsr pc,backspace + jsr pc,backspace + tst r0 +1: + rts pc +/ +aff074: + jsr pc,release + jsr pc,in154 /load from register + jmp case170 +/ +neg074: + jsr pc,release + jsr pc,readc + jmp loop +/ +/ +/ case = for conditional execution +/ +case075: + jsr pc,in074 + beq aff074 + jmp neg074 +/ +/ +/ case != for conditional execution +/ +in75a: + jsr pc,in074 + bne inaff + jmp inneg +/ +/ +/ case > for conditional execution +/ +case076: + jsr pc,in074 + bge neg074 + jmp aff074 +/ +/ +/ case !> for conditional execution +/ +in76a: + jsr pc,in074 + blt inneg + jmp inaff +/ +inaff: + jsr pc,release + jsr pc,in154 + jsr pc,in170 + rts pc +/ +inneg: + jsr pc,release + jsr pc,readc + rts pc +/ +err: + mov $1,r0 + sys write; 1f; 2f-1f + jmp reset +1: ; 2: .even +/ +eh1: + jsr pc,release +eh: + movb ch,1f+2 + mov $1,r0 + sys write; 1f; 2f-1f + mov $readstack,readptr + mov errstack,sp + jmp loop +.data +1: <( ) ?\n> +2: .even +.text +/ +/ +/ routine to read and convert a number from the +/ input stream. Numbers beginnig with 0 are +/ converted as octal. Routine converts +/ up to next nonnumeric. +/ +/ +readin: + clr dp + clr dpt + clr r0 + jsr pc,allocate + mov r1,-(sp) + mov strptr,r1 + jsr pc,create + jsr pc,readc +1: + cmpb ch,$'0 + blt 3f + cmpb ch,$'9 + bgt 3f + mov ch,r0 + sub $'0,r0 +4: + tst dp + beq 8f + cmp dpt,$99. + beq 5f + inc dpt +8: + mov chptr,r1 + jsr pc,create + tst r0 + beq 2f + jsr pc,putchar +2: mov r1,chptr + mov (sp),r3 + mov inbas,r2 + jsr pc,mul3 + mov r1,(sp) + mov r3,r1 + jsr pc,release + mov (sp),r3 + mov chptr,r2 + jsr pc,add3 + mov r1,(sp) + mov r3,r1 + jsr pc,release +5: + jsr pc,readc + mov r0,ch + br 1b +3: + cmpb ch,$'A + blt 1f + cmpb ch,$'F + bgt 1f + mov ch,r0 + sub $67,r0 + br 4b +1: + cmpb ch,$134 /backslash + bne 1f + jsr pc,readc + br 5b +1: + cmpb ch,$'. + bne 1f + tst dp + bne 1f + inc dp + clr dpt + br 5b +1: + mov r0,savec +/ +/ scale up or down +2: + tst dp + bne 1f + mov (sp)+,r1 + clr r0 + jsr pc,putchar + rts pc +1: + mov (sp),r1 + jsr pc,scale + mov dpt,r0 + jsr pc,putchar + tst (sp)+ + rts pc +/ +.bss +dp: .=.+2 +dpt: .=.+2 +.text +/ +scale: + mov dpt,r2 + jsr pc,add0 + mov r1,-(sp) + mov $1,r0 + jsr pc,allocate + mov dpt,r0 + jsr pc,putchar + mov r1,r3 + mov inbas,r2 + jsr pc,exp3 + mov r1,-(sp) + mov r3,r1 + jsr pc,release + mov (sp)+,r2 + mov (sp)+,r3 + jsr pc,div3 + mov r1,-(sp) + mov r2,r1 + jsr pc,release + mov r3,r1 + jsr pc,release + mov r4,r1 + jsr pc,release + mov (sp)+,r1 + rts pc +/ +/ routine to read another character from the input +/ stream. If the caller does not want the character, +/ it is to be placed in the cell savec. +/ The routine exits to the system on end of file. +/ Character is returned in r0. +/ +/ jsr pc,readc +/ movb r0,... +/ +/ +readc: + tst savec + beq 1f + movb savec,r0 + bic $177400,r0 + clr savec + rts pc +1: + tst *readptr + bne 1f +2: mov source,r0 + sys read; ch; 1 + bes eof + tst r0 + beq eof + movb ch,r0 + bic $177400,r0 + rts pc +1: + mov r1,-(sp) + mov *readptr,r1 + jsr pc,getchar + bes eof1 + bic $177400,r0 + mov r0,ch + mov (sp)+,r1 + rts pc +/ +eof: + tst source + beq 1f + clr source + br 2b +1: + sys exit +/ +eof1: + mov *readptr,r1 + beq 2f + jsr pc,release +2: + sub $2,readptr + mov (sp)+,r1 + jmp readc +/ +/ +/ case p for print +/ +case160: + cmp r5,$pdl + jeq eh + jsr pc,in160 + jmp loop +/ +/ +in160: +/ mov $1,r0 +/ sys write; sphdr; 4 + br 1f +/ +sphdr: < > + .even +/ +1: cmp r5,$pdl + bne 1f + mov $1,r0 + sys write; qm; 1 + mov $1,r0 + sys write; nl; 1 + rts pc +/ +/ do the conversion +/ +1: + mov -2(r5),r1 + jsr pc,printf + rts pc +/ +/ +/ case f for print the stack +/ +case146: + mov r5,-(sp) +1: + cmp r5,$pdl + beq 2f +1: + jsr pc,in160 + jsr pc,pop + cmp r5,$pdl + bne 1b +2: + mov $stable-2,r2 +1: + tst (r2)+ + cmp r2,$stable+254. + bhi 1f +/ + mov (r2),r3 + beq 1b + movb $'0,7f+3 + mov r2,r0 + sub $stable,r0 + asr r0 + movb r0,7f+1 +3: + mov $1,r0 + sys write; 7f; 8f-7f +.data +7: <" (0)"> +8: .even +.text + mov 2(r3),r1 + jsr pc,printf + tst (r3) + beq 1b + incb 7b+3 + mov (r3),r3 + br 3b +1: + mov (sp)+,r5 + jbr loop +/ +/ +/ routine to convert to decimal and print the +/ top element of the stack. +/ +/ jsr pc,printf +/ +/ +printf: + mov r4,-(sp) + mov r3,-(sp) + mov r2,-(sp) + mov r1,-(sp) + mov r0,-(sp) + clr -(sp) + jsr pc,rewind +2: + jsr pc,getchar + bes 2f + cmp r0,$143 + blos 2b + cmp r0,$-1 + beq 2b + bis $1,(sp) + br 2b +2: + tst (sp)+ + beq 2f + jsr pc,length + mov r0,0f + mov a(r1),3f + mov $1,r0 + sys 0; 9f +.data +9: + sys write; 3:.=.+2; 0:.=.+2 +.text + jbr prout +2: + jsr pc,fsfile + jsr pc,backspace + bec 1f + mov $1,r0 + sys write; asczero; 1 + jbr prout +1: + jsr pc,length + mov r1,-(sp) + jsr pc,allocate + mov (sp),r0 + mov r1,(sp) + jsr pc,move + mov ll,count +/ inc count + jsr pc,fsfile + jsr pc,backspace + mov r0,savk + dec w(r1) + jsr pc,backspace + cmpb r0,$-1 + bne 2f + mov basptr,r1 + jsr pc,fsfile + jsr pc,backspace + cmp r0,$-1 + beq 2f + mov (sp),r1 + jsr pc,chsign + mov $'-,ch + jsr pc,wrchar + br 1f +2: +/ mov $' ,ch +/ jsr pc,wrchar +1: + mov strptr,r1 + jsr pc,create + mov basptr,r1 + jsr pc,length + cmp r0,$1 + jlo dingout + bne 1f + jsr pc,rewind + jsr pc,getchar + cmp r0,$1. + jeq unout + cmp r0,$-1 + jeq dingout + cmp r0,$10. + jeq tenout +1: + mov log10,r1 + mul savk,r1 + clr r0 + div logo,r0 + mov r0,dout + clr ct +1: + mov (sp),r3 + mov savk,r2 + jsr pc,getdec + mov r1,decimal + clr dflg + mov (sp),r1 + mov savk,r2 + jsr pc,removc + mov r1,(sp) +1: + mov (sp),r3 + mov basptr,r2 + jsr pc,div3 + mov r1,r2 + mov (sp),r1 + jsr pc,release + mov r2,(sp) + mov r4,r1 + jsr pc,*outdit + mov (sp),r1 + jsr pc,length + bne 1b +/ + mov strptr,r1 + jsr pc,fsfile +1: + jsr pc,backspace + bes 1f + mov r0,ch + jsr pc,wrchar + br 1b +1: + mov (sp)+,r1 + jsr pc,release + tst savk + bne 1f + mov decimal,r1 + jsr pc,release + br prout +1: + mov dot,ch + jsr pc,wrchar + mov strptr,r1 + jsr pc,create + mov decimal,-(sp) + inc dflg +1: + mov (sp),r3 + mov basptr,r2 + jsr pc,mul3 + mov r1,(sp) + mov r3,r1 + jsr pc,release + mov (sp),r3 + mov savk,r2 + jsr pc,getdec + mov r1,(sp) + mov r3,r1 + mov savk,r2 + jsr pc,removc + jsr pc,*outdit + mov strptr,r1 + inc ct + cmp ct,dout + blo 1b + mov (sp)+,r1 + jsr pc,release + mov strptr,r1 + jsr pc,rewind +1: + jsr pc,getchar + bes 1f + mov r0,ch + jsr pc,wrchar + br 1b +1: +/ +/ cleanup, print new line and return +/ +prout: mov $1,r0 + sys write; nl; 1 + mov (sp)+,r0 + mov (sp)+,r1 + mov (sp)+,r2 + mov (sp)+,r3 + mov (sp)+,r4 + rts pc +/ +/ +/ +/ r2 = count +/ r3 = pointer (not released) +/ +.bss +dflg: .=.+2 +dout: .=.+2 +logo: .=.+2 +log10: .=.+2 +decimal: .=.+2 +.text +getdec: + mov r3,-(sp) + mov r3,r1 + jsr pc,rewind + jsr pc,length + jsr pc,allocate + mov r1,-(sp) +1: + cmp r2,$1 + blt 1f + mov 2(sp),r1 + jsr pc,getchar + mov (sp),r1 + jsr pc,putchar + mov r1,(sp) + sub $2,r2 + br 1b +1: + tst r2 + beq 1f + mov tenptr,r2 + mov (sp),r3 + jsr pc,mul3 + mov r1,(sp) + mov r3,r1 + jsr pc,length + jsr pc,release + mov r0,r3 + jsr pc,allocate + mov r1,-(sp) + mov 2(sp),r1 + jsr pc,rewind +2: + tst r3 + beq 2f + jsr pc,getchar + mov (sp),r1 + jsr pc,putchar + mov r1,(sp) + dec r3 + mov 2(sp),r1 + br 2b +2: + clr r0 + mov (sp),r1 + jsr pc,putchar + mov 2(sp),r1 + jsr pc,release + mov (sp),r3 + mov tenptr,r2 + jsr pc,div3 + mov r1,(sp) + mov r3,r1 + jsr pc,release + mov r4,r1 + jsr pc,release + mov (sp)+,r1 + tst (sp)+ + mov (sp)+,r3 + rts pc +1: + mov (sp)+,r1 + mov (sp)+,r3 + rts pc +tenout: + mov savk,ct + mov $2,r0 + jsr pc,allocate + mov r1,-(sp) + mov 2(sp),r1 + jsr pc,fsfile + jsr pc,backspace + mov r0,r3 + clr r2 + dvd $10.,r2 + beq 1f +3: + add $60,r2 + mov r2,r0 + mov (sp),r1 + jsr pc,putchar + mov r1,(sp) +1: + mov (sp),r1 + add $60,r3 + mov r3,r0 + jsr pc,putchar + mov 2(sp),r1 +1: + jsr pc,backspace + bec 2f + mov (sp),r1 + jsr pc,length + cmp r0,ct + beq 4f + blo 5f + sub ct,r0 + mov r0,ct +1: + jsr pc,getchar + mov r0,ch + jsr pc,wrchar + dec ct + bne 1b + jsr pc,getchar + bes 6f + jsr pc,backspace +4: + movb dot,ch + jsr pc,wrchar +1: + jsr pc,getchar + bes 1f + mov r0,ch + jsr pc,wrchar + br 1b +5: + sub r0,ct + movb dot,ch + jsr pc,wrchar + mov $60,ch +5: + jsr pc,wrchar + dec ct + bne 5b + br 1b +1: +6: + mov (sp)+,r1 + jsr pc,release + mov (sp)+,r1 + jsr pc,release + jbr prout +2: + mov r0,r3 + clr r2 + dvd $10.,r2 + br 3b +dot: <.> + .even +ct: .=.+2 +/ +/ +dingout: + clr -(sp) + br 1f +unout: + mov $1,-(sp) +1: + mov 2(sp),r1 + mov savk,r2 + jsr pc,removc + mov r1,2(sp) + mov strptr,r1 + jsr pc,create + mov $-1,r0 + jsr pc,putchar + mov r1,r3 +1: + mov 2(sp),r1 + jsr pc,length + beq 1f + mov r1,r2 + jsr pc,add3 + mov r1,2(sp) + mov r2,r1 + jsr pc,release + mov $1,r0 + tst (sp) + beq 2f + mov $'1,ch + jsr pc,wrchar + br 1b +2: + tst delflag + jne in177 + sys write; ding; 3 + br 1b +1: + tst (sp)+ + mov (sp)+,r1 + jsr pc,release + jmp prout +/ +ding: < > / +sp5: <\\\n > +minus: <-> +one: <1> + .even +.bss +count: .=.+2 +.text +/ +bigout: + mov r1,-(sp) /big digit + tst dflg + beq 1f + clr r0 + jsr pc,allocate + mov r1,tptr +1: + mov strptr,r1 + jsr pc,length + add fw,r0 + dec r0 + mov r0,-(sp) /end of field + clr -(sp) /negative + mov 4(sp),r1 + jsr pc,length + bne 2f + mov $'0,r0 + tst dflg + beq 3f + mov tptr,r1 + jsr pc,putchar + mov r1,tptr + br 1f +3: + mov strptr,r1 + jsr pc,putchar + br 1f +2: + mov 4(sp),r1 /digit + jsr pc,fsfile + jsr pc,backspace + bpl 2f + mov $1,(sp) /negative + jsr pc,chsign +2: + mov 4(sp),r3 /digit + mov r3,r1 + jsr pc,length + beq 1f + mov tenptr,r2 + jsr pc,div3 + mov r1,4(sp) /digit + mov r3,r1 + jsr pc,release + mov r4,r1 + jsr pc,rewind + jsr pc,getchar + jsr pc,release + add $'0,r0 + tst dflg + beq 3f + mov tptr,r1 + jsr pc,putchar + mov r1,tptr + br 2b +3: + mov strptr,r1 + jsr pc,putchar + br 2b +1: + tst dflg + beq 4f + mov tptr,r1 + jsr pc,length + cmp r0,fw1 + bhis 2f + mov fw1,r1 + sub r0,r1 + mov r1,-(sp) + mov strptr,r1 +3: + mov $'0,r0 + jsr pc,putchar + dec (sp) + bne 3b + tst (sp)+ +2: + mov tptr,r1 + jsr pc,fsfile +2: + mov tptr,r1 + jsr pc,backspace + bes 2f + mov strptr,r1 + jsr pc,putchar + br 2b +2: + mov tptr,r1 + jsr pc,release + br 1f +4: + mov strptr,r1 + jsr pc,length + cmp r0,2(sp) /end of field + bhis 1f + mov $'0,r0 + jsr pc,putchar + br 1b +1: + tst (sp) /negative + beq 1f + mov $'-,r0 + mov strptr,r1 + dec w(r1) + jsr pc,putchar +1: + mov strptr,r1 + mov $' ,r0 + jsr pc,putchar + tst (sp)+ + tst (sp)+ + mov (sp)+,r1 + jsr pc,release + rts pc +/ +.bss +tptr: .=.+2 +tenptr: .=.+2 +.text +/ +/ +/ +hexout: + mov r1,-(sp) + jsr pc,rewind + jsr pc,getchar + cmp r0,$16. + blo 1f + jmp err +1: + add $60,r0 + cmp r0,$'9 + blos 2f + add $'A-'9-1,r0 +2: + mov strptr,r1 + jsr pc,putchar + mov (sp)+,r1 + jsr pc,release + rts pc +/ +/ +wrchar: + tst delflag + jne in177 + mov $1,r0 + tst count + bne 7f + sys write; sp5; 2 + mov ll,count + mov $1,r0 +7: + dec count + sys write; ch; 1 + rts pc +/ +/ +/ case P for print an ascii string +/ +/ +case120: + jsr pc,pop + jes eh + jsr pc,length + mov r0,0f + mov a(r1),3f + mov $1,r0 + sys 0; 9f + jsr pc,release + jmp loop +.data +9: sys write; 3:.=.+2; 0:.=.+2 +.text +/ +/ +/ here for unimplemented stuff +/ +junk: + movb r0,1f + mov $1,r0 + sys write; 1f; 2f-1f + jmp loop +.data +1: <0 not in switch.\n> +2: .even +.text +/ +/ +/ +/ routine to place one word onto the pushdown list +/ Error exit to system on overflow. +/ +/ +push: + mov r1,(r5)+ + cmp r5,$pdltop + bhis pdlout + rts pc +/ +pdlout: + mov $1,r0 + sys write; 1f; 2f-1f + jmp reset +1: +2: .even +/ +/ +/ routine to remove one word from the pushdown list +/ carry bit set on empty stack +/ +/ +/ jsr pc,pop +/ +pop: + cmp r5,$pdl + bhi 1f + clr r1 + sec + rts pc +1: mov -(r5),r1 + clc + rts pc +/ +/ +/ +/ +.data +outdit: hexout +.bss +source: .=.+2 +savec: .=.+2 +ch: .=.+2 +.text +nl: <\n> +asczero: <0> +qm: + .even +/ +.bss +chptr: .=.+2 +strptr: .=.+2 +basptr: .=.+2 +scalptr: .=.+2 +errstack:.=.+2 +/ +stable: .=.+512. +.text +casetab: + case012; 012 /nl + loop; 040 /sp + case041; 041 /! + case045; 045 /% + case052; 052 /* + case053; 053 /+ + case055; 055 /- + case060; 056 /. + case057; 057 // + case060; 060 /0 + case060; 061 /1 + case060; 062 /2 + case060; 063 /3 + case060; 064 /4 + case060; 065 /5 + case060; 066 /6 + case060; 067 /7 + case060; 070 /8 + case060; 071 /9 + case072; 072 /: + case073; 073 /; + case074; 074 /< + case075; 075 /= + case076; 076 /> + case077; 077 /? + case060; 101 /A + case060; 102 /B + case060; 103 /C + case060; 104 /D + case060; 105 /E + case060; 106 /F + case111; 111 /I + case113; 113 /K + case114; 114 /L + case117; 117 /O + case120; 120 /P + case121; 121 /Q + case123; 123 /S + case166; 126 /V + case170; 130 /X + case172; 132 /Z + case133; 133 /[ + case136; 136 /^ + case137; 137 /_ + case143; 143 /c + case144; 144 /d + case146; 146 /f + case151; 151 /i + case153; 153 /k + case154; 154 /l + case157; 157 /o + case160; 160 /p + case161; 161 /q + case163; 163 /s + case166; 166 /v + case170; 170 /x + case172; 172 /z + 0;0 +/ +.bss +pdl: .=.+100. +pdltop: +.text + +reset: + clr r0 + sys seek; 0; 2 +1: + clr r0 + sys read; rathole; 1 + bes 1f + tst r0 + beq 1f + cmpb rathole,$'q + bne 1b +1: + sys exit +.bss +rathole: .=.+2 +.text diff --git a/source/s1/dc2.s b/source/s1/dc2.s new file mode 100644 index 0000000..cfba1b9 --- /dev/null +++ b/source/s1/dc2.s @@ -0,0 +1,457 @@ +/ +/ +/ routine to add the two centennial numbers +/ pointed to by r2 and r3. +/ a pointer to the result is returned in r1 +/ r2 and r3 are preserved +/ +/ mov ptr1,r2 +/ mov ptr2,r3 +/ jsr pc,add3 +/ mov r1,... +/ +add3: mov r0,-(sp) + mov r4,-(sp) + mov r5,-(sp) + mov r3,-(sp) + mov r2,-(sp) +/ +/ allocate a new string whose length is +/ the max of the two addends. +/ + mov w(r2),r0 + sub a(r2),r0 + mov w(r3),r4 + sub a(r3),r4 + cmp r0,r4 + bgt 1f + mov r4,r0 +1: mov r0,r4 + jsr pc,allocate + mov r1,-(sp) +/ +/ get everything ready +/ + mov 2(sp),r1 + jsr pc,rewind + mov 4(sp),r1 + jsr pc,rewind + clr carry +/ +/ now add them +/ +2: dec r4 + blt 3f + mov 2(sp),r1 /r2 + jsr pc,getchar + mov r0,r5 + mov 4(sp),r1 /r3 + jsr pc,getchar + add r5,r0 + add carry,r0 + clr carry + cmp r0,$100. + blt 1f + sub $100.,r0 + mov $1,carry +1: + tstb r0 + bpl 1f + add $100.,r0 + mov $-1,carry +1: mov (sp),r1 /r1 + jsr pc,putchar + br 2b +/ +/ perhaps there is an extra digit +/ +3: mov carry,r0 + beq 2f + mov (sp),r1 /r1 + jsr pc,putchar +/ +/ strip leading zeros +/ +2: + jsr pc,fsfile +2: jsr pc,backspace + bes 2f + beq 2b + inc r(r1) +2: mov r(r1),w(r1) +/ +/ strip leading 99's +/ + jsr pc,fsfile + jsr pc,backspace + cmpb r0,$-1 + bne 1f +2: + jsr pc,backspace + bes 2f + cmpb r0,$99. + beq 2b + jsr pc,getchar +2: + mov $-1,r0 + jsr pc,alterchar + mov r(r1),w(r1) +/ +/ restore and return +/ +1: + mov (sp)+,r1 + mov (sp)+,r2 + mov (sp)+,r3 + mov (sp)+,r5 + mov (sp)+,r4 + mov (sp)+,r0 + rts pc +/ +.bss +carry: .=.+2 +.text +/ +/ +/ routine to change the sign of the centennial number +/ pointed to by r1. +/ negative numbers are stored in 100's complement form with +/ -1 as the high order digit; the second digit is not 99. +/ +/ mov ...,r1 +/ jsr pc,chsign +/ +chsign: + mov r1,-(sp) + mov r0,-(sp) + jsr pc,rewind + clr chcarry +/ +1: + jsr pc,lookchar + bes 1f + negb r0 + sub chcarry,r0 + mov $1,chcarry + add $100.,r0 + cmpb $100.,r0 + bgt 2f + sub $100.,r0 + clr chcarry +2: + jsr pc,alterchar + br 1b +/ +1: + clr r0 + sub chcarry,r0 + beq 2f + jsr pc,putchar + jsr pc,fsfile + jsr pc,backspace + jsr pc,backspace + cmp r0,$99. + bne 1f + mov r(r1),w(r1) + mov $-1,r0 + jsr pc,putchar + br 1f +/ +2: + jsr pc,fsfile + jsr pc,backspace + bne 1f + mov r(r1),w(r1) +/ +1: + mov (sp)+,r0 + mov (sp)+,r1 + rts pc +/ +.bss +chcarry: .=.+2 +.text +/ +/ +/ +/ +/ routine to multiply the two centennial numbers +/ pointed to by r2 and r3. +/ a pointer to the result is returned in r1 +/ r2 and r3 are preserved +/ +/ mov ptr1,r2 +/ mov ptr2,r3 +/ jsr pc,mul3 +/ mov r1,... +/ +/ save registers and make space for temps +/ +mul3: + mov r5,-(sp) + mov r3,-(sp) /arg2 + mov r2,-(sp) /arg1 + mov r0,-(sp) + tst -(sp) /result + tst -(sp) /arg1 + tst -(sp) /arg2 + tst -(sp) /carry +/ +/ compute sign of result and make args positive +/ + clr outsign + mov r2,r1 + jsr pc,fsfile + jsr pc,backspace + bmi 2f + mov r2,4(sp) /arg1 + br 1f +2: + jsr pc,length + jsr pc,allocate + mov r1,4(sp) + mov r2,r0 + jsr pc,move + jsr pc,chsign + com outsign +1: + mov r3,r1 + jsr pc,fsfile + jsr pc,backspace + bmi 2f + mov r3,2(sp) /arg2 + br 1f +2: + mov r3,r1 + jsr pc,length + jsr pc,allocate + mov r1,2(sp) + mov r3,r0 + jsr pc,move + jsr pc,chsign + com outsign +1: +/ +/ compute the length of the result and +/ allocate space for it +/ + mov w(r2),r0 + sub a(r2),r0 + add w(r3),r0 + sub a(r3),r0 + jsr pc,allocate + jsr pc,zero + mov r1,6(sp) /result + clr offset + mov 2(sp),r1 /arg2 + jsr pc,rewind +/ +/ work on next digit of arg2, starting over on arg1 +/ +1: mov 4(sp),r1 /arg1 + jsr pc,rewind + mov 2(sp),r1 /arg2 + jsr pc,getchar + bes 3f + mov r0,r2 + mov 6(sp),r1 /result + jsr pc,rewind + add offset,r(r1) + clr 0(sp) /carry +/ +/ work on next digit of arg3 +/ form the product of the two digits, +/ add to what is already there and add in old carry +/ to generate new dit and new carry. +/ +2: mov 4(sp),r1 /arg1 + jsr pc,getchar + bes 2f + mov r0,r3 + mpy r2,r3 + add (sp),r3 /carry + mov 6(sp),r1 /result + jsr pc,lookchar + add r0,r3 + mov r3,r1 + clr r0 + dvd $100.,r0 + mov r0,(sp) /carry + mov r1,r0 + mov 6(sp),r1 /result + jsr pc,alterchar + br 2b +/ +2: + inc offset + tst (sp) /carry + beq 1b + mov 6(sp),r1 /result + jsr pc,lookchar + add (sp),r0 /carry + jsr pc,alterchar + br 1b +/ +3: +/ +/ change sign of result if necessary +/ + tst outsign + bpl 1f + mov 6(sp),r1 /result + jsr pc,chsign +/ +/ release dregs if necessary +/ +1: + cmp 2(sp),14(sp) + beq 1f + mov 2(sp),r1 + jsr pc,release +1: + cmp 4(sp),12(sp) + beq 1f + mov 4(sp),r1 + jsr pc,release +1: +/ +/ restore registers and return +/ + tst (sp)+ + tst (sp)+ + tst (sp)+ + mov (sp)+,r1 + mov (sp)+,r0 + mov (sp)+,r2 + mov (sp)+,r3 + mov (sp)+,r5 + rts pc +/ +.bss +outsign: .=.+2 +offset: .=.+2 +k: .=.+2 +kptr: .=.+2 +.text +/ +sqrt: + mov r4,-(sp) + mov r3,-(sp) + mov r2,-(sp) + mov r0,-(sp) +/ +/ check for zero or negative +/ + mov w(r1),r2 + sub a(r1),r2 +/ +/ look at the top one or two digits +/ + mov r1,r3 + jsr pc,fsfile + jsr pc,backspace + mov r0,r4 + bit $1,r2 + bne 2f + mov r4,r1 + mul $100.,r1 + mov r1,r4 + mov r3,r1 + jsr pc,backspace + add r0,r4 +2: +/ +/ allocate space for result +/ + inc r2 + asr r2 + mov r2,r0 + jsr pc,allocate + jsr pc,zero + mov r2,r0 + jsr pc,seekchar + mov r1,r2 +/ +/ get high order digit of arg and square root it +/ + mov $1,r0 +2: sub r0,r4 + blt 2f + add $2,r0 + br 2b +2: inc r0 + asr r0 + mov r0,r4 + mov r2,r1 + jsr pc,fsfile + jsr pc,backspace + cmp r4,$100. + blt 1f + sub $100.,r4 + mov r4,r0 + jsr pc,alterchar + mov $1,r0 + jsr pc,putchar + br 2f +1: + mov r4,r0 + jsr pc,alterchar +2: + mov r1,-(sp) + mov r3,-(sp) +/ +/ get successive approx. from Newton +/ +1: mov (sp),r3 /arg + mov 2(sp),r2 /approx + jsr pc,div3 + mov r1,r3 + jsr pc,add3 + mov r1,-(sp) + mov r3,r1 + jsr pc,release + mov r4,r1 + jsr pc,release + mov (sp)+,r1 + mov sqtemp,r2 + mov r1,r3 + jsr pc,div3 + mov r1,-(sp) + mov r3,r1 + jsr pc,release + mov r4,r1 + jsr pc,release + mov (sp)+,r3 + mov 2(sp),r1 + jsr pc,length + jsr pc,allocate + mov 2(sp),r0 + jsr pc,move + jsr pc,chsign + mov r1,r2 + jsr pc,add3 + jsr pc,fsfile + jsr pc,backspace + jsr pc,release + mov r2,r1 + jsr pc,release + tst r0 + bpl 2f +/ +/ loop if new < old + mov 2(sp),r1 + jsr pc,release + mov r3,2(sp) + br 1b +/ +2: + mov r3,r1 + jsr pc,release + mov (sp)+,r1 + jsr pc,release + mov (sp)+,r1 + mov (sp)+,r0 + mov (sp)+,r2 + mov (sp)+,r3 + mov (sp)+,r4 + rts pc diff --git a/source/s1/dc3.s b/source/s1/dc3.s new file mode 100644 index 0000000..e7f3610 --- /dev/null +++ b/source/s1/dc3.s @@ -0,0 +1,460 @@ +/ +/ +/ routine to divide the two centennial numbers pointed +/ to by r2 (the divisor) and r3 (the dividend). +/ A pointer to the result is returned in r1. All other +/ registers are preserved. If the divisor is zero, zero +/ is returned and the carry bit is set. +/ Remainder is returned in r4 and has the sign +/ of the dividend. +/ +/ +/ mov divisor,r2 +/ mov dividend,r3 +/ jsr pc,div3 +/ mov r1,result +/ mov r4,remainder +/ +/ +div3: + mov r5,-(sp) + mov r3,-(sp) /dividend + mov r2,-(sp) /divisor + mov r0,-(sp) + tst -(sp) /result +/ +/ allocate space for result; allocate temps if necessary +/ + clr r0 + jsr pc,allocate + mov r1,0(sp) /result +/ +/ +/ check for divisor zero +/ + mov 4(sp),r2 /divisor + mov w(r2),r0 + sub a(r2),r0 + bne 1f + jmp eh +1: +/ +/ compute sign of result and make arguments positive +/ + clr divsign + mov r2,r1 + jsr pc,length + jsr pc,allocate + mov r1,divisor + mov r2,r0 + jsr pc,move + jsr pc,fsfile + jsr pc,backspace + bpl 1f +2: + jsr pc,chsign + mov r1,divisor + com divsign +1: + clr remsign + mov r3,r1 + jsr pc,length + jsr pc,allocate + mov r1,dividend + mov r3,r0 + jsr pc,move + jsr pc,fsfile + jsr pc,backspace + bpl 1f +2: + jsr pc,chsign + mov r1,dividend + com divsign + com remsign +1: +/ +/ +/ find out how many digits in the quotient result +/ +1: + mov dividend,r2 + mov divisor,r3 + mov w(r2),r0 + sub a(r2),r0 + add a(r3),r0 + sub w(r3),r0 + jlo bugout + mov r0,divoffset + mov 0(sp),r1 /result + inc r0 + jsr pc,seekchar + clr r0 + mov dividend,r1 + jsr pc,putchar +/ +/ load r5 with binary divisor for finding +/ trial quotient digits. If leading digit of +/ divisor is <10, it is scaled +/ + clr magic + mov divisor,r1 + jsr pc,fsfile + jsr pc,backspace + mov r0,r5 + cmp r5,$10. + bge 2f + inc magic +2: + mpy $100.,r5 + jsr pc,backspace + add r0,r5 + tst magic + beq 2f + mov r5,r4 + mpy $100.,r4 + jsr pc,backspace + add r0,r5 + adc r4 + asl r5 + rol r4 + dvd $25.,r4 + mov r4,r5 +2: +/ +/ compute trial quotient digit +/ +1: + mov dividend,r1 + jsr pc,fsfile + jsr pc,backspace + bec 9f; 4; 9: + mov r0,r3 + mpy $100.,r3 + mov r3,r2 + jsr pc,backspace + add r0,r2 + mpy $100.,r2 + jsr pc,backspace + add r0,r3 + adc r2 + tst divoffset + bne 2f + add $1,r3 + adc r2 +2: +/ + tst magic + beq 3f + ashc $3,r2 +3: + mov r5,r0 + tst divoffset + beq 2f + inc r0 +2: + dvd r0,r2 + mov r2,trial +/ +/ +/ multiply divisor by trial digit +/ + mov divisor,r1 + jsr pc,rewind + jsr pc,length + inc r0 + mov divxyz,r1 + jsr pc,rewind + clr -(sp) +2: + mov divisor,r1 + jsr pc,getchar + bes 2f + mov r0,r3 + mpy trial,r3 + add (sp),r3 /carry + clr r2 + dvd $100.,r2 + mov r2,(sp) /carry + mov r3,r0 + mov divxyz,r1 + jsr pc,alterchar + br 2b +2: + mov divxyz,r1 + mov (sp)+,r0 + jsr pc,alterchar +3: +/ +/ and subtract from dividend +/ + jsr pc,rewind + mov divoffset,r0 + mov dividend,r1 + jsr pc,seekchar + clr -(sp) +/ +2: mov dividend,r1 + jsr pc,lookchar + bes 2f + mov r0,r2 +/ + mov divxyz,r1 + jsr pc,getchar + sub r0,r2 + sub (sp),r2 + clr (sp) + mov r2,r0 + bpl 3f + add $100.,r0 + mov $1.,(sp) +3: mov dividend,r1 + jsr pc,alterchar + br 2b +/ +/ put away the quotient digit +/ +2: + mov (sp)+,divcarry + mov 0(sp),r1 /result + jsr pc,backspace + mov trial,r0 + jsr pc,alterchar + jsr pc,backspace +/ +/ and go for another digit +/ + dec divoffset + bmi 1f + mov dividend,r1 + dec w(r1) + cmp w(r1),a(r1) + bhis 9f; 4; 9: + jmp 1b +/ +/ fix up the result +/ +1: + tst divcarry + beq 1f + mov trial,r0 + dec r0 + jsr pc,alterchar + mov dividend,r1 + mov $-1,r0 + jsr pc,alterchar + mov divisor,r2 + mov dividend,r3 + jsr pc,add3 + mov r1,-(sp) + mov r3,r1 + jsr pc,release + mov (sp)+,dividend +1: + mov 0(sp),r1 /result + jsr pc,rewind + clr divcarry +1: + jsr pc,lookchar + bes 1f + bic $!377,r0 + add divcarry,r0 + clr divcarry + cmp r0,$100. + blt 2f + sub $100.,r0 + inc divcarry +2: jsr pc,alterchar + br 1b +/ +1: + tst divcarry + beq 1f + mov $1.,r0 + jsr pc,alterchar +1: + jsr pc,fsfile +1: + jsr pc,backspace + bes 1f + bne 1f + mov r(r1),w(r1) + br 1b +1: +/ +/ change sign of result if necessary +/ + tst divsign + bpl 1f + jsr pc,chsign +1: + mov dividend,r1 + jsr pc,fsfile +1: + jsr pc,backspace + bes 1f + bne 1f + mov r(r1),w(r1) + br 1b +1: +bugout: + tst remsign + bpl 1f + mov dividend,r1 + jsr pc,chsign +/ +/ clean up junk, restore registers, and return +/ +1: + mov divisor,r1 + jsr pc,release + mov (sp)+,r1 + mov (sp)+,r0 + mov (sp)+,r2 + mov (sp)+,r3 + mov dividend,r4 + mov (sp)+,r5 + clc + rts pc +/ +/ +/ +/ +.bss +divisor: .=.+2 +dividend: .=.+2 +divxyz: .=.+2 +divoffset:.=.+2 +divcarry: .=.+2 +divsign: .=.+2 +trial: .=.+2 +remsign: .=.+2 +magic: .=.+2 +.text +/ +/ +/ +/ routine to exponentiate the two centennial numbers +/ pointed to by r2 (the base) and r3 (the exponent). +/ A pointer to the result is returned in r1. +/ +/ mov base,r2 +/ mov exp,r3 +/ jsr pc,exp3 +/ mov r1,... +/ +/ +/ save registers +/ +exp3: + mov r3,-(sp) /exponent + mov r2,-(sp) /base + mov r0,-(sp) +/ +/ +1: + mov $1,r0 + jsr pc,allocate + mov r1,-(sp) /accumulated result + mov $1,r0 + jsr pc,putchar +/ + mov r2,r1 + jsr pc,length + jsr pc,allocate + mov r1,-(sp) /powers of the base + mov r2,r0 + jsr pc,move +/ + mov r3,r1 + jsr pc,length + jsr pc,allocate + mov r1,-(sp) /exponent + mov r3,r0 + jsr pc,move + jsr pc,fsfile + clr exptemp + jsr pc,backspace + bpl 1f + inc exptemp + jsr pc,chsign +/ +1: + mov 0(sp),r1 + jsr pc,length + beq 1f + mov sqtemp,r2 + mov 0(sp),r3 + jsr pc,div3 + mov r1,0(sp) + mov r3,r1 + jsr pc,release + mov r4,r1 + jsr pc,length + jsr pc,release + tst r0 + beq 2f +/ +/ +/ + mov 2(sp),r2 + mov 4(sp),r3 + jsr pc,mul3 + mov r1,4(sp) + mov r3,r1 + jsr pc,release +2: + mov 2(sp),r3 + mov r3,r1 + jsr pc,length + jsr pc,allocate + mov r1,r2 + mov r3,r0 + jsr pc,move + jsr pc,mul3 + mov r1,2(sp) + mov r3,r1 + jsr pc,release + mov r2,r1 + jsr pc,release + br 1b +1: + tst exptemp + beq 1f + mov 10(sp),r1 + jsr pc,length + bne 2f + jmp eh +2: + cmp r0,$1 + blos 2f + mov 4(sp),r1 + jsr pc,create + br 1f +2: + jsr pc,rewind + jsr pc,getchar + cmp r0,$1 + bgt 2f + mov 4(sp),r1 + jsr pc,create + jsr pc,putchar + br 1f +2: + mov 4(sp),r1 + jsr pc,create +1: + mov (sp)+,r1 + jsr pc,release + mov (sp)+,r1 + jsr pc,release + mov (sp)+,r1 +/ + mov (sp)+,r0 + mov (sp)+,r2 + mov (sp)+,r3 + rts pc +/ +.bss +exptemp: .=.+2 +.text +/ diff --git a/source/s1/dc4.s b/source/s1/dc4.s new file mode 100644 index 0000000..cdc6bda --- /dev/null +++ b/source/s1/dc4.s @@ -0,0 +1,408 @@ +.globl getchar +.globl stats +.globl lookchar +.globl fsfile +.globl seekchar +.globl backspace +.globl putchar +.globl alterchar +.globl move +.globl rewind +.globl create +.globl zero +.globl allocate +.globl release +.globl collect +.globl getword, putword +.globl length, position +.globl w, r, a, l +/ +testing = 0 +/ +/ +/ routine to return the length of a string +/ +/ mov ...,r1 +/ jsr pc,length +/ mov r0,... +/ +length: + mov w(r1),r0 + sub a(r1),r0 + rts pc +/ +/ +/ routine to return the read pointer position +/ +/ mov ...,r1 +/ jsr pc,position +/ mov r0,... +/ +position: + mov r(r1),r0 + sub a(r1),r0 + rts pc +/ +/ +/ +/ +/ routine to get a word from the string +/ mov ...,r1 +/ jsr pc,getword +/ mov r0,... +/ +getword: + jsr pc,getchar + bes noch + movb r0,nchar + jsr pc,getchar + bec 2f + dec r(r1) + br noch +2: movb r0,nchar+1 + mov nchar,r0 + tst r0 /tst clears c-bit + rts pc +/ +/ +/ routine to put a word onto the string +/ mov ...,r1 +/ mov ...,r0 +/ jsr pc,putword +/ +putword: + jsr pc,putchar + swab r0 + jsr pc,putchar + swab r0 + rts pc +/ +.bss +nchar: .=.+2 +.text +/ +/ +/ +/ routine to read next character from string +/ pointed to by r1; character returned in r0 +/ c-bit set if character not available (end of file) +/ r1 is preserved +/ +/ mov ...,r1 +/ jsr pc,getchar +/ movb r0,... +/ +getchar: + jsr pc,lookchar + bec 2f + rts pc +2: inc r(r1) + tst r0 /tst clears c-bit + rts pc +/ +noch: clr r0 + sec + rts pc +/ +/ routine to look at next character from string +/ pointed to by r1; character returned in r0 +/ c-bit set if character not available (end of file) +/ r1 is preserved +/ +/ mov ...,r1 +/ jsr pc,lookchar +/ movb r0,... +/ +lookchar: + .if testing + jsr pc,plausible + inc stats+6. + .endif + cmp w(r1),r(r1) + blos noch + movb *r(r1),r0 + clc + rts pc +/ +plausible: + cmp r1,$headers + bhis 9f; 4; 9: + cmp r1,$headend + blo 9f; 4; 9: + rts pc +/ +/ +/ +/ routine to move the read pointer of a string to a +/ specified point. If the string is not long enough, +/ the string is extended +/ +/ mov position,r0 +/ mov ...,r1 +/ jsr pc,seekchar +/ +seekchar: + mov r1,-(sp) + mov r0,-(sp) + .if testing + jsr pc,plausible + inc stats+10. + .endif +1: + mov (sp),r0 + add a(r1),r0 + cmp r0,l(r1) + bhi 3f + mov r0,r(r1) + cmp r0,w(r1) + blo 1f + mov r0,w(r1) + br 1f +3: + mov (sp),r0 + jsr pc,allocate + mov 2(sp),r0 + jsr pc,move + jsr pc,swap + jsr pc,release + mov 2(sp),r1 + br 1b +1: + mov (sp)+,r0 + mov (sp)+,r1 + rts pc +/ +/ +/ routine to move read pointer of string to end of string +/ +/ mov ...,r1 +/ jsr pc,fsfile +/ +fsfile: + .if testing + jsr pc,plausible + inc stats+10. + .endif + mov w(r1),r(r1) + rts pc +/ +/ +/ routine to read a string backwards +/ the read pointer is decremented before reading +/ +/ mov ...,r1 +/ jsr pc,backspace +/ mov r0,... +/ +backspace: + .if testing + jsr pc,plausible + inc stats+6. + .endif + cmp a(r1),r(r1) + bhis noch + dec r(r1) + movb *r(r1),r0 + clc + rts pc +/ +/ +/ +/ +/ routine to put a character into the string +/ pointed to by r1; character in r0 +/ r0 and r1 are preserved. +/ +/ movb ch,r0 +/ mov ...,r1 +/ jsr pc,putchar +/ +putchar: + mov r1,-(sp) + mov r0,-(sp) + .if testing + jsr pc,plausible + inc stats+8. + .endif +1: cmp w(r1),l(r1) + blt 3f + mov w(r1),r0 + inc r0 + sub a(r1),r0 /W-A+1 + jsr pc,allocate + mov 2(sp),r0 /r1 + jsr pc,move + jsr pc,swap + jsr pc,release + mov 2(sp),r1 /r1 + cmp w(r1),l(r1) + blt 3f + jmp err +/ +3: movb (sp),*w(r1) + inc w(r1) + mov (sp)+,r0 + tst (sp)+ + rts pc +/ +/ +swap: + mov w(r1),-(sp) + mov w(r0),w(r1) + mov (sp),w(r0) + mov r(r1),(sp) + mov r(r0),r(r1) + mov (sp),r(r0) + mov a(r1),(sp) + mov a(r0),a(r1) + mov (sp),a(r0) + mov l(r1),(sp) + mov l(r0),l(r1) + mov (sp)+,l(r0) + rts pc +/ +/ +/ routine to alter a character in the string +/ pointed to by r1; character in r0 +/ r0 and r1 are preserved. +/ +/ movb ch,r0 +/ mov ...,r1 +/ jsr pc,alterchar +/ +alterchar: + mov r1,-(sp) + mov r0,-(sp) + .if testing + jsr pc,preposterous + inc stats+8. + .endif +1: cmp r(r1),l(r1) + blt 3f + mov l(r1),r0 + inc r0 + sub a(r1),r0 /W-A+1 + jsr pc,allocate + mov 2(sp),r0 /r1 + jsr pc,move + jsr pc,swap + jsr pc,release + mov 2(sp),r1 /r1 + cmp r(r1),l(r1) + blt 3f + jmp err +/ +3: movb (sp),*r(r1) + inc r(r1) + cmp r(r1),w(r1) + ble 1f + mov r(r1),w(r1) +1: + mov (sp)+,r0 + tst (sp)+ + rts pc +/ +/ +/ routine to move the contents of one string +/ to another. +/ +/ mov source,r0 +/ mov dest,r1 +/ jsr pc,move +/ +/ on return, r1 points to the new string and should +/ be saved. r0 is preserved. +/ +move: + mov r3,-(sp) + mov r2,-(sp) + mov r1,-(sp) + mov r0,-(sp) + mov w(r0),r2 + sub a(r0),r2 /W-A + mov l(r1),r3 + sub a(r1),r3 /L-A + cmp r2,r3 + ble 1f + mov r2,r0 + jsr pc,allocate + mov 2(sp),r0 /r1 + jsr pc,swap + jsr pc,release + mov r0,r1 + mov 0(sp),r0 /r0 +/ +1: mov a(r0),(r0) + mov a(r1),(r1) +1: dec r2 + blt 1f + movb *(r0),*(r1) + inc (r0) + inc (r1) + br 1b +/ +/ fix up read ptr of new string +/ +1: mov r(r0),r2 + sub a(r0),r2 + add a(r1),r2 + mov r2,r(r1) +/ +/ restore and return +/ + mov (sp)+,r0 + mov (sp)+,r1 + mov (sp)+,r2 + mov (sp)+,r3 + rts pc +/ +/ +/ routine to rewind read pointer of string +/ pointed to by r1 +/ +/ mov ...,r1 +/ jsr pc,rewind +/ +rewind: + .if testing + jsr pc,plausible + inc stats+10. + .endif + mov a(r1),r(r1) + rts pc +/ +/ routine to rewind write pointer of string +/ pointed to by r1 +/ +/ mov ...,r1 +/ jsr pc,create +/ +create: + .if testing + jsr pc,plausible + inc stats+10. + .endif + mov a(r1),w(r1) + mov a(r1),r(r1) + rts pc +/ +/ +/ routine to zero a string +/ +/ mov ...,r1 +/ jsr pc,zero +/ +zero: + mov r0,-(sp) + .if testing + jsr pc,preposterous + .endif + mov a(r1),r0 +1: cmp r0,l(r1) + bhis 1f + clrb (r0)+ + br 1b +1: mov (sp)+,r0 + rts pc +/ +/ diff --git a/source/s1/dc5.s b/source/s1/dc5.s new file mode 100644 index 0000000..5dff572 --- /dev/null +++ b/source/s1/dc5.s @@ -0,0 +1,540 @@ +/ +/ +/ here to allocate a new block +/ +/ mov ...,r0 +/ jsr pc,allocate +/ mov r1,... +/ +/ requested size in bytes in r0 +/ pointer to header of allocated block returned in r1 +/ r0 is preserved +/ +/ convert to words, adjust for header, round up +/ to a power of two +/ +/ each block has a four-word header +/ W - write ptr (also used as link ptr in frlist) +/ R - read ptr +/ A - pointer to head of data +/ L - ptr to (end+1) of data +w=0 +r=2 +a=4 +l=6 +/ +allocate: + clr garbage + mov r0,-(sp) + mov r2,-(sp) + tst stats + bne 1f + jsr pc,init +1: + inc stats + bne 9f; inc stats; 9: + cmp r0,$strend-strbuf + blos 9f; 4; 9: +1: + cmp $8.,r0 + blo 2f + mov $3.,r0 + br 1f +2: + sub $1,r0 + bmi 1f + jsr pc,log2 + add $1,r0 +1: asl r0 /bite to word + mov r0,-(sp) + add $2,r0 + cmp r0,$frend-frlist+2 + blo zzz + jmp err +/ +/ look on free list for block of required size +/ +zzz: + mov (sp),r0 + tst frlist(r0) + beq xxx +/ +/ found it, allocate and return +/ + mov frlist(r0),r1 + mov (r1),frlist(r0) + mov a(r1),r0 + mov r0,w(r1) /W + mov r0,r(r1) /R + tst (sp)+ + mov (sp)+,r2 + mov (sp)+,r0 + rts pc +/ +/ no block of required size +/ look for larger block +/ +xxx: + tst hdrptr + bne 1f + mov r0,-(sp) + jsr pc,morehd + tst r0 + bne out + mov (sp)+,r0 +1: + tst (r0)+ + cmp r0,$frend-frlist + bhis www + tst frlist(r0) + bne yyy + br xxx +/ +/ there are no larger blocks; must garbage collect +/ +www: + jsr pc,collect + tst r0 + bne zzz + jsr pc,moresp + tst r0 + beq zzz +/ +/ out of space +/ +out: + mov $1,r0 + sys write; 1f; 2f-1f + jmp reset +1: +2: .even +/ +/ split larger block into two smaller pieces and +/ link together as smaller blocks in the free list. +/ +yyy: + mov frlist(r0),r1 + mov (r1),frlist(r0) + mov hdrptr,r2 + bne 1f + mov r0,-(sp) + jsr pc,morehd + tst r0 + bne out + mov (sp)+,r0 + mov hdrptr,r2 +1: + mov (r2),hdrptr + clr (r2) + mov r2,(r1) + mov r1,hdrptr(r0) + mov l(r1),l(r2) + mov l(r1),r0 + sub a(r1),r0 + asr r0 + add a(r1),r0 + mov r0,l(r1) + mov r0,a(r2) + br zzz +/ +/ +/ here to release a block +/ +/ mov ...,r1 +/ jsr pc,release +/ +/ pointer to block in r1 +/ +release: +/ +/ discover that this is a plausible pointer +/ + mov r0,-(sp) + jsr pc,preposterous +/ +/ find free list index and link block to that entry +/ + inc stats+2 + mov frlist(r0),(r1) + clr r(r1) + mov r1,frlist(r0) + clr r1 /self-defense + mov (sp)+,r0 + rts pc +/ +/ +/ jsr pc,collect +/ +/ coalesce free storage by rejoining paired blocks +/ on the free list. +/ zero is returned in r0 if no paired blocks were found. +/ +collect: + mov r1,-(sp) + mov r2,-(sp) + mov r3,-(sp) + mov r4,-(sp) + clr useful + inc stats+4. + clr r0 /start with smallest blocks + /r0 contains frlist index +loop1: mov $frlist,r1 + add r0,r1 +/ +/ try next list member at this level +/ +loop2: mov (r1),r3 + beq advance /list is empty + tst *(r1) /W + beq advance /only one list element +/ +/ calculate address of buddy +/ + mov a(r3),r4 + mov $block,r2 +1: + cmp r4,(r2) + blo 1f + cmp r2,lblock + beq 2f + add $2,r2 + br 1b +1: + sub $2,r2 +2: + mov (r2),beg + sub beg,r4 + bit exp2(r0),r4 + beq 2f + bic exp2(r0),r4 + br 1f +2: bis exp2(r0),r4 +1: add beg,r4 +/ +/ and search for him +/ +loop3: tst 0(r3) + beq nocoal + mov (r3),r2 + cmp a(r2),r4 + beq coal + mov (r3),r3 + br loop3 +/ +/ have found a pair; remove both blocks from list, +/ coalesce them, and put them on next higher list +/ +coal: inc useful + mov (r3),r4 + mov (r4),(r3) /remove him from list + mov (r1),r2 + mov (r2),(r1) /remove the other one + cmp a(r2),a(r4) + bgt 1f + mov r2,-(sp) + mov r4,r2 + mov (sp)+,r4 +1: add exp2(r0),l(r4) + clr r(r4) + mov frlist+2(r0),(r4) + mov r4,frlist+2(r0) + mov hdrptr,(r2) + mov r2,hdrptr + clr r(r2) + mov beg,a(r2) + mov beg,l(r2) + br loop2 +/ +/ no buddy found, try next block on this list +/ +nocoal: + mov (r1),r1 + br loop2 +/ +/ advance to next free list +/ +advance: + tst (r0)+ + cmp r0,$frend-frlist + blo loop1 + mov useful,r0 +/ +/ do we have enough headers to continue? +/ + cmp garbage,$2 + blo 1f + mov $1,r0 + sys write; 4f; 5f-4f + jmp reset +/ +4: +5: .even +/ +/ +/ restore registers and return +/ +1: + inc garbage + mov (sp)+,r4 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r1 + rts pc +/ +.bss +garbage: .=.+2 +.text +/ +/ routine to get more space for strings +/ +moresp: + mov r2,-(sp) + mov r1,-(sp) + mov brk,r1 + mov $block,r2 + add nblock,r2 + cmp r2,$blkend + bhis rout + mov r1,(r2) + mov r1,lblock + add $2,nblock + add $10000,r1 + mov r1,9f + sys break;9:.. + bes 2f + mov hdrptr,r2 + bne 1f + jsr pc,morehd + tst r0 + beq 2f + mov hdrptr,r2 +1: + mov (r2),hdrptr + mov brk,a(r2) + mov r1,brk + mov r1,l(r2) + clr r(r2) + mov $10000,r0 + jsr pc,log2 + asl r0 + mov frlist(r0),w(r2) + mov r2,frlist(r0) + clr r0 + mov (sp)+,r1 + mov (sp)+,r2 + rts pc +2: + mov $1,r0 + mov (sp)+,r1 + mov (sp)+,r2 + rts pc +/ +/ routine to get move space for headers +/ +morehd: + mov r2,-(sp) + mov brk,r0 + mov $hblock,r2 + add nhdr,r2 + cmp r2,$hblkend + bhis rout + mov r0,(r2) + mov r0,lhblock + add $2,nhdr + add $1024.,r0 + mov r0,9f + sys break;9:.. + bes 2f + mov brk,r2 + mov r2,hdrptr + mov r0,brk + sub $8,r0 +1: + add $8,r2 + mov r2,-8(r2) + cmp r2,r0 + blos 1b + clr -8(r2) + clr r0 + mov (sp)+,r2 + rts pc +2: + mov $1,r0 + mov (sp)+,r2 + rts pc +rout: + mov $1,r0 + sys write; 4f; 5f-4f + jmp reset +/ +4: +5: .even +/ +/ routine to find integer part of log2(x) +/ +/ jsr pc,log2 +/ +/ r0 = log2(r0) +/ +log2: + mov r0,-(sp) + bge 9f; 4; 9: + mov $15.,r0 +1: + rol (sp) + bmi 1f + sob r0,1b +1: + dec r0 + tst (sp)+ + rts pc +/ + 0 /Don't move me, I'm exp(-1) +exp2: + 1;2;4;10;20;40;100;200;400;1000;2000;4000; + 10000;20000;40000;100000 +/ +/ routine to discover whether r1 points to +/ a plausible header - to avoid ruination. +/ +/ r1 is preserved and r0 gets a suitable index for frlist +/ +/ jsr pc,preposterous +/ +preposterous: + mov r2,-(sp) + mov $hblock,r2 +1: + cmp r1,(r2) + blo 1f + cmp (r2),lhblock + beq 2f + add $2,r2 + br 1b +1: + sub $2,r2 +2: + mov (r2),r2 + add $1024.,r2 + cmp r1,r2 + blo 9f;4;9: + mov $block,r2 +1: + cmp a(r1),(r2) + blo 1f + cmp (r2),lblock + beq 2f + add $2,r2 + br 1b +1: + sub $2,r2 +2: + cmp l(r1),(r2) + bhis 9f;4;9: + mov (r2),r2 + add $10000,r2 + cmp a(r1),r2 + blo 9f;4;9: + cmp l(r1),r2 + blos 9f;4;9: + mov (sp)+,r2 + mov l(r1),r0 /L + sub a(r1),r0 /A + mov r0,-(sp) + jsr pc,log2 + asl r0 + cmp exp2(r0),(sp) + beq 9f; 4; 9: + add $2,r0 + cmp r0,$frend-frlist+2 + blo 9f; 4; 9: + sub $2,r0 + mov r0,(sp) + mov frlist(r0),r0 +1: beq 1f + cmp r0,r1 + bne 9f; 4; 9: + mov (r0),r0 + br 1b +1: mov (sp)+,r0 + rts pc +/ +/ +/ routine to initialize storage area, headers and +/ free list upon first call to allocate a block. +/ The entire storage area is formed into a single block. +/ +init: + mov r0,-(sp) + mov r1,-(sp) +/ +/ form all the headers into a single list. +/ + mov $headers,r0 + mov r0,hdrptr +1: add $8,r0 + mov r0,-8(r0) + cmp r0,$headend-8 + blos 1b + clr -8(r0) + mov $frlist,r0 +1: clr (r0)+ + cmp r0,$frend + blo 1b +/ + mov hdrptr,r1 + mov (r1),hdrptr + clr w(r1) + mov $strbuf,r0 + mov r0,a(r1) + mov $strend-strbuf,r0 + jsr pc,log2 + asl r0 + cmp r0,$frend-frlist + blo 9f; 4; 9: + mov r1,frlist(r0) + mov exp2(r0),r0 + add $strbuf,r0 + mov r0,l(r1) + mov $hdrptr,r1 +1: mov (r1),r1 + tst r1 + beq 1f + mov $strbuf,a(r1) + mov $strbuf,l(r1) + br 1b +1: + mov $end,brk + add $2,nblock + mov $strbuf,block + mov $strbuf,lblock + mov $headers,hblock + add $2,nhdr + mov $headers,lhblock + mov (sp)+,r1 + mov (sp)+,r0 + rts pc +/ +/ +.bss +nhdr: .=.+2 +lhblock: .=.+2 +hblock: .=.+20. +hblkend: +stats: .=.+16. +useful: .=.+2 +beg: .=.+2 +lblock: .=.+2 +nblock: .=.+2 +block: .=.+40. +blkend: +brk: .=.+2 +hdrptr: .=.+2 /do not move me +frlist: .=hdrptr+32. +frend: +headers:.=hdrptr+1024. +headend: +strbuf: .=.+10000 +strend: +end: +signal = 48. diff --git a/source/s1/dcheck.c b/source/s1/dcheck.c new file mode 100644 index 0000000..5bedc8d --- /dev/null +++ b/source/s1/dcheck.c @@ -0,0 +1,219 @@ +# + +char *dargv[] +{ + "/dev/rrk2", + "/dev/rrp0", + 0 +}; + +#define NINODE 16*16 +#define NI 20 + +#include "/usr/sys/ino.h" +#include "/usr/sys/filsys.h" + +struct inode inode[NINODE]; +struct filsys sblock; + +int sflg; +int headpr; + +int ilist[NI] { -1}; +int fi; +char *ecount; +char *lasts; +int ino; +int nerror; +int nfiles; +struct dir { + int ino; + char name[14]; +}; + +main(argc, argv) +char **argv; +{ + register char **p; + register int n, *lp; + + ecount = sbrk(0); + if (argc == 1) { + for (p = dargv; *p;) + check(*p++); + return(nerror); + } + while (--argc) { + argv++; + if (**argv=='-') switch ((*argv)[1]) { + case 's': + sflg++; + continue; + + case 'i': + lp = ilist; + while (lp < &ilist[NI-1] && (n = number(argv[1]))) { + *lp++ = n; + argv++; + argc--; + } + *lp++ = -1; + continue; + + default: + printf("Bad flag\n"); + } + check(*argv); + } + return(nerror); +} + +check(file) +char *file; +{ + register i, j; + fi = open(file, 0); + if(fi < 0) { + printf("cannot open %s\n", file); + return; + } + headpr = 0; + printf("%s:\n", file); + sync(); + bread(1, &sblock, 512); + nfiles = sblock.s_isize*16; + if (lasts < nfiles) { + if ((sbrk(nfiles - lasts)) == -1) { + printf("Not enough core\n"); + exit(04); + } + lasts = nfiles; + } + for (i=0; ii_mode&IALLOC) == 0) + return; + if((ip->i_mode&IFMT) != IFDIR) + return; + doff = 0; + while (dp = dread(ip, doff)) { + doff =+ 16; + if (dp->ino==0) + continue; + for (i=0; ilist[i] != -1; i++) + if (ilist[i]==dp->ino) + printf("%5l arg; %l/%.14s\n", dp->ino, ino, dp->name); + ecount[dp->ino]++; + } +} + +pass2(aip) +{ + register struct inode *ip; + register i; + + ip = aip; + i = ino; + if ((ip->i_mode&IALLOC)==0 && ecount[i]==0) + return; + if (ip->i_nlink==ecount[i] && ip->i_nlink!=0) + return; + if (headpr==0) { + printf("entries link cnt\n"); + headpr++; + } + printf("%l %d %d\n", ino, + ecount[i]&0377, ip->i_nlink&0377); +} + +dread(aip, aoff) +{ + register b, off; + register struct inode *ip; + static ibuf[256]; + static char buf[512]; + + off = aoff; + ip = aip; + if ((off&0777)==0) { + if (off==0177000) { + printf("Monstrous directory %l\n", ino); + return(0); + } + if ((ip->i_mode&ILARG)==0) { + if (off>=010000 || (b = ip->i_addr[off>>9])==0) + return(0); + bread(b, buf, 512); + } else { + if (off==0) { + if (ip->i_addr[0]==0) + return(0); + bread(ip->i_addr[0], ibuf, 512); + } + if ((b = ibuf[(off>>9)&0177])==0) + return(0); + bread(b, buf, 512); + } + } + return(&buf[off&0777]); +} + +bread(bno, buf, cnt) +{ + + seek(fi, bno, 3); + if(read(fi, buf, cnt) != cnt) { + printf("read error %d\n", bno); + exit(); + } +} + +bwrite(bno, buf) +{ + + seek(fi, bno, 3); + if(write(fi, buf, 512) != 512) { + printf("write error %d\n", bno); + exit(); + } +} + +number(as) +char *as; +{ + register n, c; + register char *s; + + s = as; + n = 0; + while ((c = *s++) >= '0' && c <= '9') { + n = n*10+c-'0'; + } + return(n); +} diff --git a/source/s1/dd.c b/source/s1/dd.c new file mode 100644 index 0000000..75eb0d4 --- /dev/null +++ b/source/s1/dd.c @@ -0,0 +1,458 @@ +#define LCASE 01 +#define UCASE 02 +#define SWAB 04 +#define NERR 010 +#define SYNC 020 +int cflag; +int fflag; +int skip; +int count; +char *string; +char *ifile; +char *ofile; +char *ibuf; +char *obuf; +char *ibs 512; +char *obs 512; +char *bs; +char *cbs; +char *ibc; +char *obc; +char *cbc; +int nifr; +int nipr; +int nofr; +int nopr; +int ntrunc; +int ibf; +int obf; +char *op; +int nspace; +char etoa[] +{ + 0000,0001,0002,0003,0234,0011,0206,0177, + 0227,0215,0216,0013,0014,0015,0016,0017, + 0020,0021,0022,0023,0235,0205,0010,0207, + 0030,0031,0222,0217,0034,0035,0036,0037, + 0200,0201,0202,0203,0204,0012,0027,0033, + 0210,0211,0212,0213,0214,0005,0006,0007, + 0220,0221,0026,0223,0224,0225,0226,0004, + 0230,0231,0232,0233,0024,0025,0236,0032, + 0040,0240,0241,0242,0243,0244,0245,0246, + 0247,0250,0133,0056,0074,0050,0053,0041, + 0046,0251,0252,0253,0254,0255,0256,0257, + 0260,0261,0135,0044,0052,0051,0073,0136, + 0055,0057,0262,0263,0264,0265,0266,0267, + 0270,0271,0174,0054,0045,0137,0076,0077, + 0272,0273,0274,0275,0276,0277,0300,0301, + 0302,0140,0072,0043,0100,0047,0075,0042, + 0303,0141,0142,0143,0144,0145,0146,0147, + 0150,0151,0304,0305,0306,0307,0310,0311, + 0312,0152,0153,0154,0155,0156,0157,0160, + 0161,0162,0313,0314,0315,0316,0317,0320, + 0321,0176,0163,0164,0165,0166,0167,0170, + 0171,0172,0322,0323,0324,0325,0326,0327, + 0330,0331,0332,0333,0334,0335,0336,0337, + 0340,0341,0342,0343,0344,0345,0346,0347, + 0173,0101,0102,0103,0104,0105,0106,0107, + 0110,0111,0350,0351,0352,0353,0354,0355, + 0175,0112,0113,0114,0115,0116,0117,0120, + 0121,0122,0356,0357,0360,0361,0362,0363, + 0134,0237,0123,0124,0125,0126,0127,0130, + 0131,0132,0364,0365,0366,0367,0370,0371, + 0060,0061,0062,0063,0064,0065,0066,0067, + 0070,0071,0372,0373,0374,0375,0376,0377, +}; +char atoe[] +{ + 0000,0001,0002,0003,0067,0055,0056,0057, + 0026,0005,0045,0013,0014,0015,0016,0017, + 0020,0021,0022,0023,0074,0075,0062,0046, + 0030,0031,0077,0047,0034,0035,0036,0037, + 0100,0117,0177,0173,0133,0154,0120,0175, + 0115,0135,0134,0116,0153,0140,0113,0141, + 0360,0361,0362,0363,0364,0365,0366,0367, + 0370,0371,0172,0136,0114,0176,0156,0157, + 0174,0301,0302,0303,0304,0305,0306,0307, + 0310,0311,0321,0322,0323,0324,0325,0326, + 0327,0330,0331,0342,0343,0344,0345,0346, + 0347,0350,0351,0112,0340,0132,0137,0155, + 0171,0201,0202,0203,0204,0205,0206,0207, + 0210,0211,0221,0222,0223,0224,0225,0226, + 0227,0230,0231,0242,0243,0244,0245,0246, + 0247,0250,0251,0300,0152,0320,0241,0007, + 0040,0041,0042,0043,0044,0025,0006,0027, + 0050,0051,0052,0053,0054,0011,0012,0033, + 0060,0061,0032,0063,0064,0065,0066,0010, + 0070,0071,0072,0073,0004,0024,0076,0341, + 0101,0102,0103,0104,0105,0106,0107,0110, + 0111,0121,0122,0123,0124,0125,0126,0127, + 0130,0131,0142,0143,0144,0145,0146,0147, + 0150,0151,0160,0161,0162,0163,0164,0165, + 0166,0167,0170,0200,0212,0213,0214,0215, + 0216,0217,0220,0232,0233,0234,0235,0236, + 0237,0240,0252,0253,0254,0255,0256,0257, + 0260,0261,0262,0263,0264,0265,0266,0267, + 0270,0271,0272,0273,0274,0275,0276,0277, + 0312,0313,0314,0315,0316,0317,0332,0333, + 0334,0335,0336,0337,0352,0353,0354,0355, + 0356,0357,0372,0373,0374,0375,0376,0377, +}; + + +main(argc, argv) +int argc; +char **argv; +{ + register (*conv)(); + register char *ip; + register c; + int ebcdic(), ascii(), null(), cnull(), term(); + int a; + + conv = null; + for(c=1; cibuf;) + *--ip = 0; + ibc = read(ibf, ibuf, ibs); + } + if(ibc == -1) { + perror("read"); + if((cflag&NERR) == 0) { + flsh(); + term(); + } + ibc = 0; + for(c=0; c>1) & ~1; + if(cflag&SWAB && c) + do { + a = *ip++; + ip[-1] = *ip; + *ip++ = a; + } while(--c); + ip = ibuf; + if (fflag) { + obc = ibc; + flsh(); + ibc = 0; + } + goto loop; + } + c = 0; + c =| *ip++; + (*conv)(c); + goto loop; +} + +flsh() +{ + register c; + + if(obc) { + if(obc == obs) + nofr++; else + nopr++; + c = write(obf, obuf, obc); + if(c != obc) { + perror("write"); + term(); + } + obc = 0; + } +} + +match(s) +char *s; +{ + register char *cs; + + cs = string; + while(*cs++ == *s) + if(*s++ == '\0') + goto true; + if(*s != '\0') + return(0); + +true: + cs--; + string = cs; + return(1); +} + +number() +{ + register char *cs; + register n; + + cs = string; + n = 0; + while(*cs >= '0' && *cs <= '9') + n = n*10 + *cs++ - '0'; + for(;;) + switch(*cs++) { + + case 'k': + n =* 1024; + continue; + + case 'w': + n =* 2; + continue; + + case 'b': + n =* 512; + continue; + + case '*': + case 'x': + string = cs; + n =* number(); + + case '\0': + return(n); + } + printf("not a number: %s\n", string); + exit(); +} + +cnull(cc) +{ + register c; + + c = cc; + if(cflag&UCASE && c>='a' && c<='z') + c =+ 'A'-'a'; + if(cflag&LCASE && c>='A' && c<='Z') + c =+ 'a'-'A'; + null(c); +} + +null(c) +{ + + *op = c; + op++; + if(++obc >= obs) { + flsh(); + op = obuf; + } +} + +ascii(cc) +{ + register c; + + c = 0; + c =| etoa[cc]; + if(cbs == 0) { + cnull(c); + return; + } + if(c == ' ') { + nspace++; + goto out; + } + while(nspace > 0) { + null(' '); + nspace--; + } + cnull(c); + +out: + if(++cbc >= cbs) { + null('\n'); + cbc = 0; + nspace = 0; + } +} + +ebcdic(cc) +{ + register c; + + c = cc; + if(cflag&UCASE && c>='a' && c<='z') + c =+ 'A'-'a'; + if(cflag&LCASE && c>='A' && c<='Z') + c =+ 'a'-'A'; + c = atoe[c] & 0377; + if(cbs == 0) { + null(c); + return; + } + if(cc == '\n') { + while(cbc < cbs) { + null(atoe[' ']); + cbc++; + } + cbc = 0; + return; + } + if(cbc == cbs) + ntrunc++; + cbc++; + if(cbc <= cbs) + null(c); +} + +term() +{ + + stats(); + exit(); +} + +stats() +{ + + printf("%l+%l records in\n", nifr, nipr); + printf("%l+%l records out\n", nofr, nopr); + if(ntrunc) + printf("%l truncated records\n", ntrunc); +} + +putchar(c) +{ + + write(2, &c, 1); +} diff --git a/source/s1/df.c b/source/s1/df.c new file mode 100644 index 0000000..97302a4 --- /dev/null +++ b/source/s1/df.c @@ -0,0 +1,97 @@ +char *dargv[] +{ + 0, + "/dev/rk2", + "/dev/rp0", + 0 +}; +struct +{ + char *s_isize; + char *s_fsize; + int s_nfree; + int s_free[100]; + int s_ninode; + int s_inode[100]; + char s_flock; + char s_ilock; + char s_fmod; + int time[2]; + int pad[50]; +} sblock; + +int fi; + +main(argc, argv) +char **argv; +{ + int i; + + if(argc <= 1) { + for(argc = 1; dargv[argc]; argc++); + argv = dargv; + } + + for(i=1; i 1) + printf("%s ", argv[i]); + dfree(argv[i]); + } +} + +dfree(file) +char *file; +{ + int i; + + fi = open(file, 0); + if(fi < 0) { + printf("cannot open %s\n", file); + return; + } + sync(); + bread(1, &sblock); + i = 0; + while(alloc()) + i++; + printf("%l\n", i); + close(fi); +} + +alloc() +{ + int b, i, buf[256]; + + i = --sblock.s_nfree; + if(i<0 || i>=100) { + printf("bad free count\n"); + return(0); + } + b = sblock.s_free[i]; + if(b == 0) + return(0); + if(b=sblock.s_fsize) { + printf("bad free block (%l)\n", b); + return(0); + } + if(sblock.s_nfree <= 0) { + bread(b, buf); + sblock.s_nfree = buf[0]; + for(i=0; i<100; i++) + sblock.s_free[i] = buf[i+1]; + } + return(b); +} + +bread(bno, buf) +{ + int n; + extern errno; + + seek(fi, bno, 3); + if((n=read(fi, buf, 512)) != 512) { + printf("read error %d\n", bno); + printf("count = %d; errno = %d\n", n, errno); + exit(); + } +} diff --git a/source/s1/diff1.c b/source/s1/diff1.c new file mode 100644 index 0000000..404e0b5 --- /dev/null +++ b/source/s1/diff1.c @@ -0,0 +1,463 @@ +/* diff - differential file comparison +* +* Uses an algorithm due to Harold Stone, which finds +* a pair of longest identical subsequences in the two +* files. +* +* The major goal is to generate the match vector J. +* J[i] is the index of the line in file1 corresponding +* to line i file0. J[i] = 0 if there is no +* such line in file1. +* +* Lines are hashed so as to work in core. All potential +* matches are located by sorting the lines of each file +* on the hash (called value_____). In particular, this +* collects the equivalence classes in file1 together. +* Subroutine equiv____ replaces the value of each line in +* file0 by the index of the first element of its +* matching equivalence in (the reordered) file1. +* To save space equiv_____ squeezes file1 into a single +* array member______ in which the equivalence classes +* are simply concatenated, except that their first +* members are flagged by changing sign. +* +* Next the indices that point into member______ are unsorted_______ into +* array class_____ according to the original order of file0. +* +* The cleverness lies in routine stone______. This marches +* through the lines of file0, developing a vector klist_____ +* of "k-candidates". At step i a k-candidate is a matched +* pair of lines x,y (x in file0 y in file1) such that +* there is a common subsequence of lenght k +* between the first i lines of file0 and the first y +* lines of file1, but there is no such subsequence for +* any smaller y. x is the earliest possible mate to y +* that occurs in such a subsequence. +* +* Whenever any of the members of the equivalence class of +* lines in file1 matable to a line in file0 has serial number +* less than the y of some k-candidate, that k-candidate +* with the smallest such y is replaced. The new +* k-candidate is chained (via pred____) to the current +* k-1 candidate so that the actual subsequence can +* be recovered. When a member has serial number greater +* that the y of all k-candidates, the klist is extended. +* At the end, the longest subsequence is pulled out +* and placed in the array J by unravel_______. +* +* With J in hand, the matches there recorded are +* check_____ed against reality to assure that no spurious +* matches have crept in due to hashing. If they have, +* they are broken, and "jackpot " is recorded--a harmless +* matter except that a true match for a spuriously +* mated line may now be unnecessarily reported as a change. +* +* Much of the complexity of the program comes simply +* from trying to minimize core utilization and +* maximize the range of doable problems by dynamically +* allocating what is needed and reusing what is not. +* The core requirements for problems larger than somewhat +* are (in words) 2*length(file0) + length(file1) + +* 3*(number of k-candidates installed), typically about +* 6n words for files of length n. There is also space for buf1 +* used which could, by moving data underfoot and reallocating +* buf1 together with buf2, be completely overlaid. +*/ +struct buf { + int fdes; + char data[516]; +} *buf1, *buf2; + +struct cand { + int x; + int y; + struct cand *pred; +} cand; +struct line { + int serial; + int value; +} *file[2], line; +int len[2]; +int *class; /*will be overlaid on file[0]*/ +int *member; /*will be overlaid on file[1]*/ +struct cand **klist; /*will be overlaid on file[0] after class*/ +int *J; /*will be overlaid on class*/ +int *ixold; /*will be overlaid on klist*/ +int *ixnew; /*will be overlaid on file[1]*/ + +char *area; +char *top; +alloc(n) +{ + register char *p; + p = area; + n = (n+1) & ~1; + area =+ n; + while(area > top) { + if(sbrk(1024) == -1) { + mesg("Out of space\n"); + exit(1); + } + top =+ 1024; + } + return(p); +} + +mesg(s) +char *s; +{ + while(*s) + write(2,s++,1); +} + +sort(a,n) /*shellsort CACM #201*/ +struct line *a; +{ + struct line w; + register int j,m; + struct line *ai; + register struct line *aim; + int k; + for(j=1;j<=n;j=* 2) + m = 2*j - 1; + for(m=/2;m!=0;m=/2) { + k = n-m; + for(j=1;j<=k;j++) { + for(ai = &a[j]; ai > a; ai =- m) { + aim = &ai[m]; + if(aim->value > ai[0].value || + aim->value == ai[0].value && + aim->serial > ai[0].serial) + break; + w.value = ai[0].value; + ai[0].value = aim->value; + aim->value = w.value; + w.serial = ai[0].serial; + ai[0].serial = aim->serial; + aim->serial = w.serial; + } + } + } +} + +unsort(f, l, b) +struct line *f; +int *b; +{ + int *a; + int i; + a = alloc((l+1)*sizeof(a[0])); + for(i=1;i<=l;i++) + a[f[i].serial] = f[i].value; + for(i=1;i<=l;i++) + b[i] = a[i]; + area = a; +} + +prepare(i, arg) +char *arg; +{ + register char *temp; + temp = file[i] = area; + alloc(sizeof(line)); + input(arg); + len[i] = (area - temp)/sizeof(line) - 1; + alloc(sizeof(line)); + sort(file[i], len[i]); +} + +input(arg) +{ + register int h, i; + register struct line *p; + if(fopen(arg,buf1) == -1) { + mesg("Cannot open "); + mesg(arg); + mesg("\n"); + exit(1); + } + for(i=0; h=readhash(buf1);) { + p = alloc(sizeof(line)); + p->serial = ++i; + p->value = h; + } + close(buf1->fdes); +} + +equiv(a,n,b,m,c) +struct line *a, *b; +int *c; +{ + register int i, j; + i = j = 1; + while(i<=n && j<=m) { + if(a[i].value 1 && *argv[1]=='-') { + argc--; + argv++; + } + if(argc!=3) { + mesg("Arg count\n"); + exit(1); + } + + area = top = sbrk(0); + buf1 = alloc(sizeof(*buf1)); + prepare(0, argv[1]); + prepare(1, argv[2]); + + member = file[1]; + equiv(file[0], len[0], file[1], len[1], member); + + class = file[0]; + unsort(file[0], len[0], class); + + klist = &class[len[0]+2]; + area = &member[len[1]+2]; + k = stone(class, len[0], member, klist); + J = class; + unravel(klist[k]); + + ixold = klist; + ixnew = file[1]; + area = &ixnew[len[1]+2]; + buf2 = alloc(sizeof(*buf2)); + if(check(argv)) + mesg("Jackpot\n"); + output(argv); +} + +stone(a,n,b,c) +int *a; +int *b; +struct cand **c; +{ + register int i, k,y; + int j, l; + int skip; + k = 0; + c[0] = 0; + for(i=1; i<=n; i++) { + j = a[i]; + if(j==0) + continue; + skip = 0; + do { + y = b[j]; + if(y<0) y = -y; + if(skip) + continue; + l = search(c, k, y); + if(l > k) { + c[k+1] = newcand(i,y,c[k]); + skip = 1; + k++; + } + else if(c[l]->y > y && c[l]->x < i) + c[l] = newcand(i,y,c[l-1]); + } while(b[++j] > 0); + } + return(k); +} + +struct cand * +newcand(x,y,pred) +struct cand *pred; +{ + struct cand *p; + p = alloc(sizeof(cand)); + p->x = x; + p->y = y; + p->pred = pred; + return(p); +} + +search(c, k, y) +struct cand **c; +{ + register int i, j, l; + int t; + i = 0; + j = k+1; + while((l=(i+j)/2) > i) { + t = c[l]->y; + if(t > y) + j = l; + else if(t < y) + i = l; + else + return(l); + } + return(l+1); +} + +unravel(p) +struct cand *p; +{ + int i; + for(i=0; i<=len[0]; i++) + J[i] = 0; + while(p) { + J[p->x] = p->y; + p = p->pred; + } +} + +/* check does double duty: +1. ferret out any fortuitous correspondences due +to counfounding by hashing (which result in "jackpot") +2. collect random access indexes to the two files */ + +check(argv) +char **argv; +{ + register int i, j; + int ctold, ctnew; + int jackpot; + char c,d; + fopen(argv[1],buf1); + fopen(argv[2],buf2); + j = 1; + ctold = ctnew = 0; + ixold[0] = ixnew[0] = 0; + jackpot = 0; + for(i=1;i<=len[0];i++) { + if(J[i]==0) { + while(getc(buf1)!='\n') ctold++; + ixold[i] = ++ctold; + continue; + } + while(jfdes); + close(buf2->fdes); + return(jackpot); +} + +output(argv) +char **argv; +{ + int dir; + int m; + int i0,i1,j0,j1; + extern fout; + dir = **argv=='-'; + fout = dup(1); + buf1->fdes = open(argv[1],0); + buf2->fdes = open(argv[2],0); + m = len[0]; + J[0] = 0; + J[m+1] = len[1]+1; + if(dir==0) for(i0=1;i0<=m;i0=i1+1) { + while(i0<=m&&J[i0]==J[i0-1]+1) i0++; + j0 = J[i0-1]+1; + i1 = i0-1; + while(i1=1;i0=i1-1) { + while(i0>=1&&J[i0]==J[i0+1]-1&&J[i0]!=0) i0--; + j0 = J[i0+1]-1; + i1 = i0+1; + while(i1>1&&J[i1-1]==0) i1--; + j1 = J[i1-1]+1; + J[i1] = j1; + change(i1,i0,j1,j0,dir); + } + if(m==0) + change(1,0,1,len[1],dir); + flush(); +} + +change(a,b,c,d,dir) +{ + if(a>b&&c>d) return; + range(a,b); + putchar(a>b?'a':c>d?'d':'c'); + if(dir==0) range(c,d); + putchar('\n'); + if(dir==0) { + fetch(ixold,a,b,buf1,"* "); + if(a<=b&&c<=d) printf("---\n"); + } + fetch(ixnew,c,d,buf2,dir==0?". ":""); + if(dir!=0&&c<=d) printf(".\n"); +} + +range(a,b) +{ + if(a>b) printf("%d",b); + if(a<=b) printf("%d",a); + if(afdes,f[i-1],0); + nc = read(lb->fdes,lb->data,f[i]-f[i-1]); + printf(pref); + for(j=0;jdata[j]); + } +} + diff --git a/source/s1/diff2.s b/source/s1/diff2.s new file mode 100644 index 0000000..fbb6888 --- /dev/null +++ b/source/s1/diff2.s @@ -0,0 +1,56 @@ +/ hash routine for diff +/ effectively spreads the string out into 7-bit +/ bytes, then sums the result 1's-complement +/ by 16-bit bytes and adds 1 to avoid zero answer + +/ r4 hash accumulator +/ r3 current offset +/ r2 first time flag +.globl _readhash +.globl getc + +.data +_readhash: + mov 2(sp),0f + mov r5,-(sp) + mov r4,-(sp) + mov r3,-(sp) + mov r2,-(sp) + mov $1,r4 + mov r4,r2 + clr r3 +1: + jsr r5,getc; 0: 0 + bes 2f + clr r2 + cmp r0,$'\n + beq 1f + ashc $-16.,r0 + ashc r3,r0 + add r0,r4 + adc r4 + add r1,r4 + adc r4 + add $7,r3 + cmp r3,$16. + blt 1b + sub $16.,r3 + br 1b +2: + tst r2 + bne 2f + mov $2,r0 + sys write; 3f; 4f-3f +2: + clr r4 +1: + mov r4,r0 + mov (sp)+,r2 + mov (sp)+,r3 + mov (sp)+,r4 + mov (sp)+,r5 + rts pc +3: + +4: +.even diff --git a/source/s1/dsw.s b/source/s1/dsw.s new file mode 100644 index 0000000..149dfb0 --- /dev/null +++ b/source/s1/dsw.s @@ -0,0 +1,95 @@ +/ dsw - delete from tty + + cmp (sp)+,$2 + blt 1f + tst (sp)+ + mov (sp)+,0f +1: + sys stat; 0:dot; stbuf + bes error + mov stbuf+4,r0 + bic $!60000,r0 + cmp r0,$40000 + bne error + mov 0b,0f + sys open; 0:..; 0 + bes error + mov r0,r1 +1: + clrb buf+17. + mov r1,r0 + sys read; buf; 16. + bes done + tst r0 + beq done + tst buf + beq 1b + mov 0b,r2 + mov $obuf,r3 +2: + movb (r2)+,(r3)+ + bne 2b + mov $buf+2,r2 + dec r3 + cmpb -1(r3),$'/ + beq 2f + movb $'/,(r3)+ +2: + movb (r2)+,(r3)+ + bne 2b + sys stat; obuf; stbuf + bes error + bit $60000,stbuf+4 + bne 1b + mov $buf+2,r2 +2: + tstb (r2)+ + bne 2b + movb $' ,-(r2) + sub $buf+1,r2 + mov r2,0f + +2: + mov $1,r0 + sys write; buf+2; 0:.. + clr r0 + sys read; ch; 1 + cmpb ch,$'\n + beq 1b + clr r0 + sys read; ch1; 1 + cmpb ch1,$'\n + beq 3f +4: + clr r0 + sys read; ch; 1 + cmpb ch,$'\n + beq 2b + br 4b +3: + cmpb ch,$'x + beq done + cmpb ch,$'y + bne 2b + sys unlink; obuf + bes error + br 1b + +done: + sys exit + +error: + mov $1,r0 + sys write; mes; 2 + sys exit + +dot: <.\0> +mes: + + .bss +obuf: .=.+100. +stbuf: .=.+40. +buf: .=.+18. +ch: .=.+1 +ch1: .=.+1 + diff --git a/source/s1/du.s b/source/s1/du.s new file mode 100644 index 0000000..d790e54 --- /dev/null +++ b/source/s1/du.s @@ -0,0 +1,203 @@ +/ dusg -- summarize disk usage + +.globl putc, flush, _end + mov $1,obuf + mov (sp)+,r5 + tst (sp)+ +1: + dec r5 + bgt 2f + tstb buf1 + beq 3f + jsr r5,flush; obuf + sys exit +3: + mov $dot,r0 + br 3f +2: + mov (sp)+,r0 +3: + cmpb (r0),$'- + bne 2f + cmpb 1(r0),$'a + bne 3f + inc aflg + br 1b +3: + cmpb 1(r0),$'s + bne 1b + dec aflg + br 1b +2: + mov $buf1,r1 +2: + movb (r0)+,(r1)+ + bne 2b + dec r1 + clr buf3+10. + mov $_end,iptr + mov $_end,brk + sys break; _end + jsr pc,tree + tst aflg + bpl 1b + jsr r5,name + br 1b + +tree: + sys stat; buf1; buf2 + bes 1f + bic $!60000,buf2+4 + bit $20000,buf2+4 + beq 2f +1: + clr r4 + rts pc +2: + mov $_end,r2 + mov buf2+2,r3 +1: + cmp r2,iptr + bhis 1f + cmp r3,(r2)+ + bne 1b + clr r4 + jsr r5,cname + rts pc +1: + cmp r2,brk + blo 1f + add $512.,brk + sys break; brk: .. +1: + mov r3,(r2)+ + mov r2,iptr + cmp $40000,buf2+4 + beq 1f + jsr pc,gsize + jsr r5,cname + rts pc +1: + jsr pc,gsize + mov r4,r3 + sys open; buf1; 0 + bec 1f + rts pc +1: + mov r0,-(sp) + mov r1,-(sp) +1: + mov 2(sp),r0 + sys read; buf3; 16. + bes 1f + tst r0 + beq 1f + tst buf3 + beq 1b + cmp buf3+2,$".\0 + beq 1b + cmp buf3+2,$".. + bne 2f + tst buf3+4 + beq 1b +2: + mov $buf3+2,r2 + mov (sp),r1 + movb $'/,(r1)+ + cmpb -2(r1),$'/ + bne 2f + dec r1 +2: + movb (r2)+,(r1)+ + bne 2b + dec r1 + mov r3,-(sp) + jsr pc,tree + mov r4,r3 + add (sp)+,r3 + br 1b +1: + mov (sp)+,r1 + clrb (r1) + mov (sp)+,r0 + sys close + mov r3,r4 + tst aflg + bmi 1f + jsr r5,name +1: + rts pc + +cname: + tst aflg + bgt name + rts r5 + +name: + jsr pc,pnum + mov $011,r0 + jsr pc,pchar + mov $buf1,r2 +1: + movb (r2)+,r0 + beq 1f + jsr pc,pchar + br 1b +1: + mov $'\n,r0 + jsr pc,pchar + rts r5 + +gsize: + mov r5,-(sp) + mov buf2+10.,r5 / size + movb buf2+9.,r4 + add $511.,r5 + adc r4 + alsc $-9,r4 + cmp r5,$8. + blo 1f + mov r5,-(sp) + add $255.,r5 + alsc $-8,r4 + add (sp)+,r5 +1: + mov r5,r4 + mov (sp)+,r5 + rts pc + +pnum: + mov r4,-(sp) + mov r5,-(sp) + mov r4,r5 + jsr pc,1f + mov (sp)+,r5 + mov (sp)+,r4 + rts pc +1: + clr r4 + dvd $10.,r4 + mov r5,-(sp) + mov r4,r5 + beq 1f + jsr pc,1b +1: + mov (sp)+,r0 + add $'0,r0 + jsr pc,pchar + rts pc + +pchar: + jsr r5,putc; obuf + rts pc + +dot: <.\0> + + .bss + +iptr: .=.+2 +buf1: .=.+100. +buf2: .=.+40. +buf3: .=.+18. +aflg: .=.+2 +obuf: .=.+520. diff --git a/source/s1/dump.c b/source/s1/dump.c new file mode 100644 index 0000000..89eba1c --- /dev/null +++ b/source/s1/dump.c @@ -0,0 +1,451 @@ +# + +/* + * incremental dump + * dump fisbuodh filesystem + * f take output tape from arglist + * i from date in /etc/dtab + * s specify tape size in feet (feet = blocks/9) + * b specify tape size in blocks + * u update /etc/dtab to current date + * 0 dump from the epoch + * d dump specified number of days + * h dump specified number of hours + * a on incremental dump, dump files even >= MAXSIZE + */ + +char *dargv[] +{ + 0, + "i", + "/dev/rp0", + 0 +}; + +#include "/usr/sys/ino.h" +#include "/usr/sys/filsys.h" +#define MAXSIZE 1000 +struct filsys sblock; +struct +{ + char name[16]; + int date[2]; +} dtab[10]; +char *dfile "/etc/dtab"; +char *ofile; +int *talist; +int fi; +int buf[256]; +int dbuf[256]; +int ibuf[256]; +int vbuf[256]; +char *date[2]; +char *ddate[2]; +int fo -1; +int pher; +int dflg; +int iflg; +int cflg; +int aflg; +char *tsize 19000; +char *taddr; + +main(argc, argv) +char **argv; +{ + char *key; + int s, i, nfil, nblk, f; + register *tap; + register struct inode *ip; + int ino; + + ofile = "/dev/mt0"; + time(date); + if(argc == 1) { + argv = dargv; + for(argc = 1; dargv[argc]; argc++); + } + + argc--; + argv++; + key = *argv; + while(*key) + switch(*key++) { + + default: + printf("bad character in key\n"); + exit(); + + case 'a': /* dump all (even large) */ + aflg++; + continue; + + case '-': + continue; + + case 'c': /* increment file name */ + cflg++; + continue; + + case 'f': /* file name from arg list */ + argc--; + argv++; + ofile = *argv; + continue; + + case 'i': /* date from date file */ + iflg++; + continue; + + case 's': /* tape size */ + tsize = number(argv[1]) * 9; + argv++; + argc--; + continue; + + case 'b': /* tape size */ + tsize = number(argv[1]); + argv++; + argc--; + continue; + + case 'u': /* rewrite date */ + dflg++; + continue; + + case '0': /* dump all */ + ddate[0] = ddate[1] = 0; + continue; + + case 'd': /* dump some number of days */ + i = 21600; + goto sd; + + case 'h': /* dump some number of hours */ + i = 900; + goto sd; + + sd: + ddate[0] = date[0]; + ddate[1] = date[1]; + s = number(argv[1])*4; + argv++; + argc--; + while(s) { + if(i > ddate[1]) + ddate[0]--; + ddate[1] =- i; + s--; + } + continue; + } + if(argc <= 1) { + printf("no file system specified\n"); + exit(); + } + if(iflg) { + f = open(dfile, 0); + if(f >= 0) { + read(f, dtab, sizeof dtab); + close(f); + for(i=0; i<10; i++) + if(equal(dtab[i].name, argv[1])) { + ddate[0] = dtab[i].date[0]; + ddate[1] = dtab[i].date[1]; + } + } + } + printf("%s:\n", argv[1]); + fi = open(argv[1], 0); + if(fi < 0) { + printf("cannot open %s\n", argv[1]); + exit(); + } + printf("incremental dump from\n"); + pdate(ddate); + sync(); + bread(1, &sblock); + talist = sbrk(size(0, sblock.s_isize*32)*512); + tap = talist; + if(tap == -1) { + printf("No memory\n"); + exit(); + } + nfil = 0; + nblk = size(0, sblock.s_isize*32); + ino = 0; + for(i=0; ii_mode == 0 || ip->i_nlink == 0) { + *tap++ = -1; + continue; + } + if(ip->i_mtime[0] < ddate[0]) + goto no; + if(ip->i_mtime[0] == ddate[0] && + ip->i_mtime[1] < ddate[1]) + goto no; + s = size(ip->i_size0&0377, ip->i_size1) + 1; + if (s>MAXSIZE && aflg==0 && iflg!=0) { + printf("%l big; not dumped.\n", ino); + goto no; + } + nfil++; + nblk =+ s; + *tap++ = s; + continue; + no: + *tap++ = 0; + } + } + printf("%l files\n%l blocks\n", nfil, nblk); + i = ldiv(0, nblk, ldiv(0, tsize, 10)); + printf("%l.%l tapes\n", i/10, i%10); + tap = buf; + clrbuf(tap); + *tap++ = sblock.s_isize; + *tap++ = sblock.s_fsize; + *tap++ = date[0]; + *tap++ = date[1]; + *tap++ = ddate[0]; + *tap++ = ddate[1]; + *tap++ = tsize; + swrite(buf); + i = size(0, sblock.s_isize*32); + tap = talist; + while(i--) { + bwrite(tap); + tap =+ 256; + } + tap = talist; + for(i=0; ii_mtime[2]) + *p++ = *q++; + swrite(dbuf); + if(ip->i_mode & (IFBLK&IFCHR)) { + if(sz != 0) + printf("special\n"); + return; + } + for(p = &ip->i_addr[0]; p < &ip->i_addr[8]; p++) + if(*p) { + if(ip->i_mode&ILARG) { + bread(*p, ibuf); + for(q = &ibuf[0]; q < &ibuf[256]; q++) + if(*q) { + if(p == &ip->i_addr[7]) { + bread(*q, vbuf); + for(r = &vbuf[0]; r < &vbuf[256]; r++) + if(*r) { + if(--sz < 0) + goto pe; + bread(*r, dbuf); + bwrite(dbuf); + } + continue; + } + if(--sz < 0) + goto pe; + bread(*q, dbuf); + bwrite(dbuf); + } + } else { + if(--sz < 0) + goto pe; + bread(*p, dbuf); + bwrite(dbuf); + } + } + if(sz) + goto pe; + return; + +pe: + clrbuf(dbuf); + while(--sz >= 0) + bwrite(dbuf); + pher++; +} + +bread(bno, b) +{ + + seek(fi, bno, 3); + if(read(fi, b, 512) != 512) { + printf("read error %l\n", bno); + } +} + +clrbuf(b) +int *b; +{ + register i, *p; + + p = b; + i = 256; + while(i--) + *p++ = 0; +} + +swrite(b) +int *b; +{ + register i, s, *p; + + i = 254; + s = taddr; + p = b; + while(i--) + s =+ *p++; + *p++ = taddr; + *p = 031415 - s; + bwrite(b); +} + +bwrite(b) +{ + + if(taddr == 0) { + if(fo != -1) { + printf("change tapes\n"); + close(fo); + rdline(); + } + otape(); + } +wloop: + if(write(fo, b, 512) != 512) { + printf("write error\n"); + rdline(); + seek(fo, taddr, 3); + goto wloop; + } + taddr++; + if(taddr >= tsize) + taddr = 0; +} + +rdline() +{ + int c; + +loop: + c = 0; + read(0, &c, 1); + if(c == 0) + exit(); + if(c != '\n') + goto loop; +} + +number(s) +char *s; +{ + register n, c; + + n = 0; + while(c = *s++) { + if(c<'0' || c>'9') + continue; + n = n*10+c-'0'; + } + return(n); +} + +size(s0, s1) +{ + register s; + extern ldivr; + + s = ldiv(s0&0377, s1, 512); + if(ldivr) + s++; + return(s); +} + +otape() +{ + register char *p; + + fo = creat(ofile, 0666); + if(fo < 0) { + printf("can not open %s\n", ofile); + exit(); + } + if(!cflg) + return; + p = ofile; + while(*p++) + ; + p[-2]++; +} + +equal(a, b) +char *a, *b; +{ + + while(*a++ == *b) + if(*b++ == 0) + return(1); + return(0); +} diff --git a/source/s1/echo.c b/source/s1/echo.c new file mode 100644 index 0000000..d51b548 --- /dev/null +++ b/source/s1/echo.c @@ -0,0 +1,10 @@ +main(argc, argv) +int argc; +char *argv[]; +{ + int i; + + argc--; + for(i=1; i<=argc; i++) + printf("%s%c", argv[i], i==argc? '\n': ' '); +} diff --git a/source/s1/ed.c b/source/s1/ed.c new file mode 100644 index 0000000..3514498 --- /dev/null +++ b/source/s1/ed.c @@ -0,0 +1,1333 @@ +# + +/* + * Editor + */ + +#define SIGHUP 1 +#define SIGINTR 2 +#define SIGQUIT 3 +#define FNSIZE 64 +#define LBSIZE 512 +#define ESIZE 128 +#define GBSIZE 256 +#define NBRA 5 +#define EOF -1 + +#define CBRA 1 +#define CCHR 2 +#define CDOT 4 +#define CCL 6 +#define NCCL 8 +#define CDOL 10 +#define CEOF 11 +#define CKET 12 + +#define STAR 01 + +#define error goto errlab +#define READ 0 +#define WRITE 1 + +int peekc; +int lastc; +char savedfile[FNSIZE]; +char file[FNSIZE]; +char linebuf[LBSIZE]; +char rhsbuf[LBSIZE/2]; +char expbuf[ESIZE+4]; +int circfl; +int *zero; +int *dot; +int *dol; +int *endcore; +int *fendcore; +int *addr1; +int *addr2; +char genbuf[LBSIZE]; +int count[2]; +char *nextip; +char *linebp; +int ninbuf; +int io; +int pflag; +int onhup; +int onquit; +int vflag 1; +int listf; +int col; +char *globp; +int tfile -1; +int tline; +char *tfname; +char *loc1; +char *loc2; +char *locs; +char ibuff[512]; +int iblock -1; +char obuff[512]; +int oblock -1; +int ichanged; +int nleft; +int errfunc(); +int *errlab errfunc; +char TMPERR[] "TMP"; +int names[26]; +char *braslist[NBRA]; +char *braelist[NBRA]; + +main(argc, argv) +char **argv; +{ + register char *p1, *p2; + extern int onintr(); + + onquit = signal(SIGQUIT, 1); + onhup = signal(SIGHUP, 1); + argv++; + if (argc > 1 && **argv=='-') { + vflag = 0; + /* allow debugging quits? */ + if ((*argv)[1]=='q') { + signal(SIGQUIT, 0); + vflag++; + } + argv++; + argc--; + } + if (argc>1) { + p1 = *argv; + p2 = savedfile; + while (*p2++ = *p1++); + globp = "r"; + } + fendcore = sbrk(0); + init(); + if ((signal(SIGINTR, 1) & 01) == 0) + signal(SIGINTR, onintr); + setexit(); + commands(); + unlink(tfname); +} + +commands() +{ + int getfile(), gettty(); + register *a1, c; + register char *p; + int r; + + for (;;) { + if (pflag) { + pflag = 0; + addr1 = addr2 = dot; + goto print; + } + addr1 = 0; + addr2 = 0; + do { + addr1 = addr2; + if ((a1 = address())==0) { + c = getchar(); + break; + } + addr2 = a1; + if ((c=getchar()) == ';') { + c = ','; + dot = a1; + } + } while (c==','); + if (addr1==0) + addr1 = addr2; + switch(c) { + + case 'a': + setdot(); + newline(); + append(gettty, addr2); + continue; + + case 'c': + delete(); + append(gettty, addr1-1); + continue; + + case 'd': + delete(); + continue; + + case 'e': + setnoaddr(); + if ((peekc = getchar()) != ' ') + error; + savedfile[0] = 0; + init(); + addr2 = zero; + goto caseread; + + case 'f': + setnoaddr(); + if ((c = getchar()) != '\n') { + peekc = c; + savedfile[0] = 0; + filename(); + } + puts(savedfile); + continue; + + case 'g': + global(1); + continue; + + case 'i': + setdot(); + nonzero(); + newline(); + append(gettty, addr2-1); + continue; + + case 'k': + if ((c = getchar()) < 'a' || c > 'z') + error; + newline(); + setdot(); + nonzero(); + names[c-'a'] = *addr2 | 01; + continue; + + case 'm': + move(0); + continue; + + case '\n': + if (addr2==0) + addr2 = dot+1; + addr1 = addr2; + goto print; + + case 'l': + listf++; + case 'p': + newline(); + print: + setdot(); + nonzero(); + a1 = addr1; + do + puts(getline(*a1++)); + while (a1 <= addr2); + dot = addr2; + listf = 0; + continue; + + case 'q': + setnoaddr(); + newline(); + unlink(tfname); + exit(); + + case 'r': + caseread: + filename(); + if ((io = open(file, 0)) < 0) { + lastc = '\n'; + error; + } + setall(); + ninbuf = 0; + append(getfile, addr2); + exfile(); + continue; + + case 's': + setdot(); + nonzero(); + substitute(globp); + continue; + + case 't': + move(1); + continue; + + case 'v': + global(0); + continue; + + case 'w': + setall(); + nonzero(); + filename(); + if ((io = creat(file, 0666)) < 0) + error; + putfile(); + exfile(); + continue; + + case '=': + setall(); + newline(); + count[1] = (addr2-zero)&077777; + putd(); + putchar('\n'); + continue; + + case '!': + unix(); + continue; + + case EOF: + return; + + } + error; + } +} + +address() +{ + register *a1, minus, c; + int n, relerr; + + minus = 0; + a1 = 0; + for (;;) { + c = getchar(); + if ('0'<=c && c<='9') { + n = 0; + do { + n =* 10; + n =+ c - '0'; + } while ((c = getchar())>='0' && c<='9'); + peekc = c; + if (a1==0) + a1 = zero; + if (minus<0) + n = -n; + a1 =+ n; + minus = 0; + continue; + } + relerr = 0; + if (a1 || minus) + relerr++; + switch(c) { + case ' ': + case '\t': + continue; + + case '+': + minus++; + if (a1==0) + a1 = dot; + continue; + + case '-': + case '^': + minus--; + if (a1==0) + a1 = dot; + continue; + + case '?': + case '/': + compile(c); + a1 = dot; + for (;;) { + if (c=='/') { + a1++; + if (a1 > dol) + a1 = zero; + } else { + a1--; + if (a1 < zero) + a1 = dol; + } + if (execute(0, a1)) + break; + if (a1==dot) + error; + } + break; + + case '$': + a1 = dol; + break; + + case '.': + a1 = dot; + break; + + case '\'': + if ((c = getchar()) < 'a' || c > 'z') + error; + for (a1=zero; a1<=dol; a1++) + if (names[c-'a'] == (*a1|01)) + break; + break; + + default: + peekc = c; + if (a1==0) + return(0); + a1 =+ minus; + if (a1dol) + error; + return(a1); + } + if (relerr) + error; + } +} + +setdot() +{ + if (addr2 == 0) + addr1 = addr2 = dot; + if (addr1 > addr2) + error; +} + +setall() +{ + if (addr2==0) { + addr1 = zero+1; + addr2 = dol; + if (dol==zero) + addr1 = zero; + } + setdot(); +} + +setnoaddr() +{ + if (addr2) + error; +} + +nonzero() +{ + if (addr1<=zero || addr2>dol) + error; +} + +newline() +{ + register c; + + if ((c = getchar()) == '\n') + return; + if (c=='p' || c=='l') { + pflag++; + if (c=='l') + listf++; + if (getchar() == '\n') + return; + } + error; +} + +filename() +{ + register char *p1, *p2; + register c; + + count[1] = 0; + c = getchar(); + if (c=='\n' || c==EOF) { + p1 = savedfile; + if (*p1==0) + error; + p2 = file; + while (*p2++ = *p1++); + return; + } + if (c!=' ') + error; + while ((c = getchar()) == ' '); + if (c=='\n') + error; + p1 = file; + do { + *p1++ = c; + } while ((c = getchar()) != '\n'); + *p1++ = 0; + if (savedfile[0]==0) { + p1 = savedfile; + p2 = file; + while (*p1++ = *p2++); + } +} + +exfile() +{ + close(io); + io = -1; + if (vflag) { + putd(); + putchar('\n'); + } +} + +onintr() +{ + signal(SIGINTR, onintr); + putchar('\n'); + lastc = '\n'; + error; +} + +errfunc() +{ + register c; + + listf = 0; + puts("?"); + count[0] = 0; + seek(0, 0, 2); + pflag = 0; + if (globp) + lastc = '\n'; + globp = 0; + peekc = lastc; + while ((c = getchar()) != '\n' && c != EOF); + if (io > 0) { + close(io); + io = -1; + } + reset(); +} + +getchar() +{ + if (lastc=peekc) { + peekc = 0; + return(lastc); + } + if (globp) { + if ((lastc = *globp++) != 0) + return(lastc); + globp = 0; + return(EOF); + } + if (read(0, &lastc, 1) <= 0) + return(lastc = EOF); + lastc =& 0177; + return(lastc); +} + +gettty() +{ + register c, gf; + register char *p; + + p = linebuf; + gf = globp; + while ((c = getchar()) != '\n') { + if (c==EOF) { + if (gf) + peekc = c; + return(c); + } + if ((c =& 0177) == 0) + continue; + *p++ = c; + if (p >= &linebuf[LBSIZE-2]) + error; + } + *p++ = 0; + if (linebuf[0]=='.' && linebuf[1]==0) + return(EOF); + return(0); +} + +getfile() +{ + register c; + register char *lp, *fp; + + lp = linebuf; + fp = nextip; + do { + if (--ninbuf < 0) { + if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0) + return(EOF); + fp = genbuf; + } + if (lp >= &linebuf[LBSIZE]) + error; + if ((*lp++ = c = *fp++ & 0177) == 0) { + lp--; + continue; + } + if (++count[1] == 0) + ++count[0]; + } while (c != '\n'); + *--lp = 0; + nextip = fp; + return(0); +} + +putfile() +{ + int *a1; + register char *fp, *lp; + register nib; + + nib = 512; + fp = genbuf; + a1 = addr1; + do { + lp = getline(*a1++); + for (;;) { + if (--nib < 0) { + write(io, genbuf, fp-genbuf); + nib = 511; + fp = genbuf; + } + if (++count[1] == 0) + ++count[0]; + if ((*fp++ = *lp++) == 0) { + fp[-1] = '\n'; + break; + } + } + } while (a1 <= addr2); + write(io, genbuf, fp-genbuf); +} + +append(f, a) +int (*f)(); +{ + register *a1, *a2, *rdot; + int nline, tl; + struct { int integer; }; + + nline = 0; + dot = a; + while ((*f)() == 0) { + if (dol >= endcore) { + if (sbrk(1024) == -1) + error; + endcore.integer =+ 1024; + } + tl = putline(); + nline++; + a1 = ++dol; + a2 = a1+1; + rdot = ++dot; + while (a1 > rdot) + *--a2 = *--a1; + *rdot = tl; + } + return(nline); +} + +unix() +{ + register savint, pid, rpid; + int retcode; + + setnoaddr(); + if ((pid = fork()) == 0) { + signal(SIGHUP, onhup); + signal(SIGQUIT, onquit); + execl("/bin/sh", "sh", "-t", 0); + exit(); + } + savint = signal(SIGINTR, 1); + while ((rpid = wait(&retcode)) != pid && rpid != -1); + signal(SIGINTR, savint); + puts("!"); +} + +delete() +{ + register *a1, *a2, *a3; + + setdot(); + newline(); + nonzero(); + a1 = addr1; + a2 = addr2+1; + a3 = dol; + dol =- a2 - a1; + do + *a1++ = *a2++; + while (a2 <= a3); + a1 = addr1; + if (a1 > dol) + a1 = dol; + dot = a1; +} + +getline(tl) +{ + register char *bp, *lp; + register nl; + + lp = linebuf; + bp = getblock(tl, READ); + nl = nleft; + tl =& ~0377; + while (*lp++ = *bp++) + if (--nl == 0) { + bp = getblock(tl=+0400, READ); + nl = nleft; + } + return(linebuf); +} + +putline() +{ + register char *bp, *lp; + register nl; + int tl; + + lp = linebuf; + tl = tline; + bp = getblock(tl, WRITE); + nl = nleft; + tl =& ~0377; + while (*bp = *lp++) { + if (*bp++ == '\n') { + *--bp = 0; + linebp = lp; + break; + } + if (--nl == 0) { + bp = getblock(tl=+0400, WRITE); + nl = nleft; + } + } + nl = tline; + tline =+ (((lp-linebuf)+03)>>1)&077776; + return(nl); +} + +getblock(atl, iof) +{ + extern read(), write(); + register bno, off; + + bno = (atl>>8)&0377; + off = (atl<<1)&0774; + if (bno >= 255) { + puts(TMPERR); + error; + } + nleft = 512 - off; + if (bno==iblock) { + ichanged =| iof; + return(ibuff+off); + } + if (bno==oblock) + return(obuff+off); + if (iof==READ) { + if (ichanged) + blkio(iblock, ibuff, write); + ichanged = 0; + iblock = bno; + blkio(bno, ibuff, read); + return(ibuff+off); + } + if (oblock>=0) + blkio(oblock, obuff, write); + oblock = bno; + return(obuff+off); +} + +blkio(b, buf, iofcn) +int (*iofcn)(); +{ + seek(tfile, b, 3); + if ((*iofcn)(tfile, buf, 512) != 512) { + puts(TMPERR); + error; + } +} + +init() +{ + register char *p; + register pid; + + close(tfile); + tline = 0; + iblock = -1; + oblock = -1; + tfname = "/tmp/exxxxx"; + ichanged = 0; + pid = getpid(); + for (p = &tfname[11]; p > &tfname[6];) { + *--p = (pid&07) + '0'; + pid =>> 3; + } + close(creat(tfname, 0600)); + tfile = open(tfname, 2); + brk(fendcore); + dot = zero = dol = fendcore; + endcore = fendcore - 2; +} + +global(k) +{ + register char *gp; + register c; + register int *a1; + char globuf[GBSIZE]; + + if (globp) + error; + setall(); + nonzero(); + if ((c=getchar())=='\n') + error; + compile(c); + gp = globuf; + while ((c = getchar()) != '\n') { + if (c==EOF) + error; + if (c=='\\') { + c = getchar(); + if (c!='\n') + *gp++ = '\\'; + } + *gp++ = c; + if (gp >= &globuf[GBSIZE-2]) + error; + } + *gp++ = '\n'; + *gp++ = 0; + for (a1=zero; a1<=dol; a1++) { + *a1 =& ~01; + if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k) + *a1 =| 01; + } + for (a1=zero; a1<=dol; a1++) { + if (*a1 & 01) { + *a1 =& ~01; + dot = a1; + globp = globuf; + commands(); + a1 = zero; + } + } +} + +substitute(inglob) +{ + register gsubf, *a1, nl; + int getsub(); + + gsubf = compsub(); + for (a1 = addr1; a1 <= addr2; a1++) { + if (execute(0, a1)==0) + continue; + inglob =| 01; + dosub(); + if (gsubf) { + while (*loc2) { + if (execute(1)==0) + break; + dosub(); + } + } + *a1 = putline(); + nl = append(getsub, a1); + a1 =+ nl; + addr2 =+ nl; + } + if (inglob==0) + error; +} + +compsub() +{ + register seof, c; + register char *p; + int gsubf; + + if ((seof = getchar()) == '\n') + error; + compile(seof); + p = rhsbuf; + for (;;) { + c = getchar(); + if (c=='\\') + c = getchar() | 0200; + if (c=='\n') + error; + if (c==seof) + break; + *p++ = c; + if (p >= &rhsbuf[LBSIZE/2]) + error; + } + *p++ = 0; + if ((peekc = getchar()) == 'g') { + peekc = 0; + newline(); + return(1); + } + newline(); + return(0); +} + +getsub() +{ + register char *p1, *p2; + + p1 = linebuf; + if ((p2 = linebp) == 0) + return(EOF); + while (*p1++ = *p2++); + linebp = 0; + return(0); +} + +dosub() +{ + register char *lp, *sp, *rp; + int c; + + lp = linebuf; + sp = genbuf; + rp = rhsbuf; + while (lp < loc1) + *sp++ = *lp++; + while (c = *rp++) { + if (c=='&') { + sp = place(sp, loc1, loc2); + continue; + } else if (c<0 && (c =& 0177) >='1' && c < NBRA+'1') { + sp = place(sp, braslist[c-'1'], braelist[c-'1']); + continue; + } + *sp++ = c&0177; + if (sp >= &genbuf[LBSIZE]) + error; + } + lp = loc2; + loc2 = sp + linebuf - genbuf; + while (*sp++ = *lp++) + if (sp >= &genbuf[LBSIZE]) + error; + lp = linebuf; + sp = genbuf; + while (*lp++ = *sp++); +} + +place(asp, al1, al2) +{ + register char *sp, *l1, *l2; + + sp = asp; + l1 = al1; + l2 = al2; + while (l1 < l2) { + *sp++ = *l1++; + if (sp >= &genbuf[LBSIZE]) + error; + } + return(sp); +} + +move(cflag) +{ + register int *adt, *ad1, *ad2; + int getcopy(); + + setdot(); + nonzero(); + if ((adt = address())==0) + error; + newline(); + ad1 = addr1; + ad2 = addr2; + if (cflag) { + ad1 = dol; + append(getcopy, ad1++); + ad2 = dol; + } + ad2++; + if (adt= ad2) { + dot = adt++; + reverse(ad1, ad2); + reverse(ad2, adt); + reverse(ad1, adt); + } else + error; +} + +reverse(aa1, aa2) +{ + register int *a1, *a2, t; + + a1 = aa1; + a2 = aa2; + for (;;) { + t = *--a2; + if (a2 <= a1) + return; + *a2 = *a1; + *a1++ = t; + } +} + +getcopy() +{ + if (addr1 > addr2) + return(EOF); + getline(*addr1++); + return(0); +} + +compile(aeof) +{ + register eof, c; + register char *ep; + char *lastep; + char bracket[NBRA], *bracketp; + int nbra; + int cclcnt; + + ep = expbuf; + eof = aeof; + bracketp = bracket; + nbra = 0; + if ((c = getchar()) == eof) { + if (*ep==0) + error; + return; + } + circfl = 0; + if (c=='^') { + c = getchar(); + circfl++; + } + if (c=='*') + goto cerror; + peekc = c; + for (;;) { + if (ep >= &expbuf[ESIZE]) + goto cerror; + c = getchar(); + if (c==eof) { + *ep++ = CEOF; + return; + } + if (c!='*') + lastep = ep; + switch (c) { + + case '\\': + if ((c = getchar())=='(') { + if (nbra >= NBRA) + goto cerror; + *bracketp++ = nbra; + *ep++ = CBRA; + *ep++ = nbra++; + continue; + } + if (c == ')') { + if (bracketp <= bracket) + goto cerror; + *ep++ = CKET; + *ep++ = *--bracketp; + continue; + } + *ep++ = CCHR; + if (c=='\n') + goto cerror; + *ep++ = c; + continue; + + case '.': + *ep++ = CDOT; + continue; + + case '\n': + goto cerror; + + case '*': + if (*lastep==CBRA || *lastep==CKET) + error; + *lastep =| STAR; + continue; + + case '$': + if ((peekc=getchar()) != eof) + goto defchar; + *ep++ = CDOL; + continue; + + case '[': + *ep++ = CCL; + *ep++ = 0; + cclcnt = 1; + if ((c=getchar()) == '^') { + c = getchar(); + ep[-2] = NCCL; + } + do { + if (c=='\n') + goto cerror; + *ep++ = c; + cclcnt++; + if (ep >= &expbuf[ESIZE]) + goto cerror; + } while ((c = getchar()) != ']'); + lastep[1] = cclcnt; + continue; + + defchar: + default: + *ep++ = CCHR; + *ep++ = c; + } + } + cerror: + expbuf[0] = 0; + error; +} + +execute(gf, addr) +int *addr; +{ + register char *p1, *p2, c; + + if (gf) { + if (circfl) + return(0); + p1 = linebuf; + p2 = genbuf; + while (*p1++ = *p2++); + locs = p1 = loc2; + } else { + if (addr==zero) + return(0); + p1 = getline(*addr); + locs = 0; + } + p2 = expbuf; + if (circfl) { + loc1 = p1; + return(advance(p1, p2)); + } + /* fast check for first character */ + if (*p2==CCHR) { + c = p2[1]; + do { + if (*p1!=c) + continue; + if (advance(p1, p2)) { + loc1 = p1; + return(1); + } + } while (*p1++); + return(0); + } + /* regular algorithm */ + do { + if (advance(p1, p2)) { + loc1 = p1; + return(1); + } + } while (*p1++); + return(0); +} + +advance(alp, aep) +{ + register char *lp, *ep, *curlp; + char *nextep; + + lp = alp; + ep = aep; + for (;;) switch (*ep++) { + + case CCHR: + if (*ep++ == *lp++) + continue; + return(0); + + case CDOT: + if (*lp++) + continue; + return(0); + + case CDOL: + if (*lp==0) + continue; + return(0); + + case CEOF: + loc2 = lp; + return(1); + + case CCL: + if (cclass(ep, *lp++, 1)) { + ep =+ *ep; + continue; + } + return(0); + + case NCCL: + if (cclass(ep, *lp++, 0)) { + ep =+ *ep; + continue; + } + return(0); + + case CBRA: + braslist[*ep++] = lp; + continue; + + case CKET: + braelist[*ep++] = lp; + continue; + + case CDOT|STAR: + curlp = lp; + while (*lp++); + goto star; + + case CCHR|STAR: + curlp = lp; + while (*lp++ == *ep); + ep++; + goto star; + + case CCL|STAR: + case NCCL|STAR: + curlp = lp; + while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); + ep =+ *ep; + goto star; + + star: + do { + lp--; + if (lp==locs) + break; + if (advance(lp, ep)) + return(1); + } while (lp > curlp); + return(0); + + default: + error; + } +} + +cclass(aset, ac, af) +{ + register char *set, c; + register n; + + set = aset; + if ((c = ac) == 0) + return(0); + n = *set++; + while (--n) + if (*set++ == c) + return(af); + return(!af); +} + +putd() +{ + register r; + extern ldivr; + + count[1] = ldiv(count[0], count[1], 10); + count[0] = 0; + r = ldivr; + if (count[1]) + putd(); + putchar(r + '0'); +} + +puts(as) +{ + register char *sp; + + sp = as; + col = 0; + while (*sp) + putchar(*sp++); + putchar('\n'); +} + +char line[70]; +char *linp line; + +putchar(ac) +{ + register char *lp; + register c; + + lp = linp; + c = ac; + if (listf) { + col++; + if (col >= 72) { + col = 0; + *lp++ = '\\'; + *lp++ = '\n'; + } + if (c=='\t') { + c = '>'; + goto esc; + } + if (c=='\b') { + c = '<'; + esc: + *lp++ = '-'; + *lp++ = '\b'; + *lp++ = c; + goto out; + } + if (c<' ' && c!= '\n') { + *lp++ = '\\'; + *lp++ = (c>>3)+'0'; + *lp++ = (c&07)+'0'; + col =+ 2; + goto out; + } + } + *lp++ = c; +out: + if(c == '\n' || lp >= &line[64]) { + linp = line; + write(1, line, lp-line); + return; + } + linp = lp; +} + +/* + * Get process ID routine if system call is unavailable. +getpid() +{ + register f; + int b[1]; + + f = open("/dev/kmem", 0); + if(f < 0) + return(-1); + seek(f, 0140074, 0); + read(f, b, 2); + seek(f, b[0]+8, 0); + read(f, b, 2); + close(f); + return(b[0]); +} + */ diff --git a/source/s1/exit.c b/source/s1/exit.c new file mode 100644 index 0000000..79ca444 --- /dev/null +++ b/source/s1/exit.c @@ -0,0 +1,5 @@ +/* exit -- end runcom */ + +main() { + seek(0, 0, 2); +} diff --git a/source/s1/fc.c b/source/s1/fc.c new file mode 100644 index 0000000..584a634 --- /dev/null +++ b/source/s1/fc.c @@ -0,0 +1,468 @@ +/* Fortran command */ + +char *tmp; +char ts[1000]; +char *tsp ts; +char *av[50]; +char *clist[50]; +char *llist[50]; +int instring; +int pflag; +int cflag; +char *complr; +int *ibuf; +int *ibuf1; +int *ibuf2; +int *obuf; +char *lp; +char *line; +int lineno; +int exfail; +struct symtab { + char name[8]; + char *value; +} *symtab; +int symsiz 200; +struct symtab *defloc; +struct symtab *incloc; +char *stringbuf; + +main(argc, argv) +char *argv[]; { + char *t; + int nc, nl, i, j, c, nxo; + int dexit(); + + complr = "/usr/fort/fc1"; + i = nc = nl = nxo = 0; + while(++i < argc) { + if(*argv[i] == '-') + switch (argv[i][1]) { + default: + goto passa; + case 'p': + pflag++; + case 'c': + cflag++; + break; + case '2': + complr = "/usr/fort/fc2"; + break; + } + else { + passa: + t = argv[i]; + if(getsuf(t)=='f') { + clist[nc++] = t; + t = setsuf(copy(t), 'o'); + } + if (nodup(llist, t)) { + llist[nl++] = t; + if (getsuf(t)=='o') + nxo++; + } + } + } + if(nc==0) + goto nocom; + if ((signal(2, 1) & 01) == 0) + signal(2, &dexit); + for (i=0; i1) + printf("%s:\n", clist[i]); + tmp = 0; + av[0] = complr; + av[1] = expand(clist[i]); + if (pflag || exfail) + continue; + if (av[1] == 0) { + cflag++; + continue; + } + av[2] = 0; + t = callsys(complr, av); + if(tmp) + cunlink(tmp); + if(t) { + cflag++; + continue; + } + av[0] = "as"; + av[1] = "-"; + av[2] = "f.tmp1"; + av[3] = 0; + callsys("/bin/as", av); + t = setsuf(clist[i], 'o'); + cunlink(t); + if(link("a.out", t) || cunlink("a.out")) { + printf("move failed: %s\n", t); + cflag++; + } + } +nocom: + if (cflag==0 && nl!=0) { + i = 0; + av[0] = "ld"; + av[1] = "-x"; + av[2] = "/lib/fr0.o"; + j = 3; + while(ivalue = defloc->name; + incloc = lookup("include", 1); + incloc->value = incloc->name; + stringbuf = sbf; + line = ln; + lineno = 0; + tmp = setsuf(copy(file), 'i'); + if (fcreat(tmp, obuf) < 0) { + printf("Can't creat %s\n", tmp); + dexit(); + } + while(getline()) { +/* + if (ibuf==ibuf2) + putc(001, obuf); /*SOH: insert */ + if (ln[0] != '#') + for (lp=line; *lp!='\0'; lp++) + putc(*lp, obuf); + putc('\n', obuf); + } + fflush(obuf); + close(obuf[0]); + close(ibuf1[0]); + return(tmp); +} + +getline() +{ + int c, sc, state; + struct symtab *np; + char *namep, *filname; + + if (ibuf==ibuf1) + lineno++; + lp = line; + *lp = '\0'; + state = 0; + if ((c=getch()) == '#') + state = 1; + while (c!='\n' && c!='\0') { + if ('a'<=c && c<='z' || 'A'<=c && c<='Z' || c=='_') { + namep = lp; + sch(c); + while ('a'<=(c=getch()) && c<='z' + ||'A'<=c && c<='Z' + ||'0'<=c && c<='9' + ||c=='_') + sch(c); + sch('\0'); + lp--; + np = lookup(namep, state); + if (state==1) { + if (np==defloc) + state = 2; + else if (np==incloc) + state = 3; + else { + error("Undefined control"); + while (c!='\n' && c!='\0') + c = getch(); + return(c); + } + } else if (state==2) { + np->value = stringbuf; + while ((c=getch())!='\n' && c!='\0') + savch(c); + savch('\0'); + return(1); + } + continue; + } else if ((sc=c)=='\'' || sc=='"') { + sch(sc); + filname = lp; + instring++; + while ((c=getch())!=sc && c!='\n' && c!='\0') { + sch(c); + if (c=='\\') + sch(getch()); + } + instring = 0; + if (state==3) { + *lp = '\0'; + while ((c=getch())!='\n' && c!='\0'); + if (ibuf==ibuf2) + error("Nested 'include'"); + if (fopen(filname, ibuf2)<0) + error("Missing file %s", filname); + else + ibuf = ibuf2; + return(c); + } + } + sch(c); + c = getch(); + } + sch('\0'); + if (state>1) + error("Control syntax"); + return(c); +} + +error(s, x) +{ + printf("%d: ", lineno); + printf(s, x); + putchar('\n'); + exfail++; + cflag++; +} + +sch(c) +{ + if (lp==line+194) + error("Line overflow"); + *lp++ = c; + if (lp>line+195) + lp = line+195; +} + +savch(c) +{ + *stringbuf++ = c; +} + +getch() +{ + static peekc; + int c; + + if (peekc) { + c = peekc; + peekc = 0; + return(c); + } +loop: + if ((c=getc1())=='/' && !instring) { + if ((peekc=getc1())!='*') + return('/'); + peekc = 0; + for(;;) { + c = getc1(); + cloop: + switch (c) { + + case '\0': + return('\0'); + + case '*': + if ((c=getc1())=='/') + goto loop; + goto cloop; + + case '\n': + if (ibuf==ibuf1) { + putc('\n', obuf); + lineno++; + } + continue; + } + } + } + return(c); +} + +getc1() +{ + int c; + + if ((c = getc(ibuf)) < 0 && ibuf==ibuf2) { + close(ibuf2[0]); + ibuf = ibuf1; + putc('\n', obuf); + c = getc1(); + } + if (c<0) + return(0); + return(c); +} + +lookup(namep, enterf) +char *namep; +{ + char *np, *snp; + struct symtab *sp; + int i, c; + + np = namep; + i = 0; + while (c = *np++) + i =+ c; + i =% symsiz; + sp = &symtab[i]; + while (sp->name[0]) { + snp = sp; + np = namep; + while (*snp++ == *np) + if (*np++ == '\0' || np==namep+8) { + if (!enterf) + subst(namep, sp); + return(sp); + } + if (sp++ > &symtab[symsiz]) + sp = symtab; + } + if (enterf) { + for (i=0; i<8; i++) + if (sp->name[i] = *namep) + namep++; + while (*namep) + namep++; + } + return(sp); +} + +subst(np, sp) +char *np; +struct symtab *sp; +{ + char *vp; + + lp = np; + if ((vp = sp->value) == 0) + return; + sch(' '); + while (*vp) + sch(*vp++); + sch(' '); +} + +getsuf(s) +char s[]; +{ + int c; + char t, *os; + + c = 0; + os = s; + while(t = *s++) + if (t=='/') + c = 0; + else + c++; + s =- 3; + if (c<=14 && c>2 && *s++=='.') + return(*s); + return(0); +} + +setsuf(s, ch) +char s[]; +{ + char *os; + + os = s; + while(*s++); + s[-2] = ch; + return(os); +} + +callsys(f, v) +char f[], *v[]; { + int t, status; + + if ((t=fork())==0) { + execv(f, v); + printf("Can't find %s\n", f); + exit(1); + } else + if (t == -1) { + printf("Try again\n"); + return(1); + } + while(t!=wait(&status)); + if ((t=(status&0377)) != 0 && t!=14) { + if (t!=2) /* interrupt */ + printf("Fatal error in %s\n", f); + dexit(); + } + return((status>>8) & 0377); +} + +copy(s) +char s[]; { + char *otsp; + + otsp = tsp; + while(*tsp++ = *s++); + return(otsp); +} + +nodup(l, s) +char **l, s[]; { + char *t, *os, c; + + if (getsuf(s) != 'o') + return(1); + os = s; + while(t = *l++) { + s = os; + while(c = *s++) + if (c != *t++) + break; + if (*t++ == '\0') + return(0); + } + return(1); +} + +cunlink(f) +char *f; +{ + if (f==0) + return(0); + return(unlink(f)); +} diff --git a/source/s1/fed1.s b/source/s1/fed1.s new file mode 100644 index 0000000..47f57a3 --- /dev/null +++ b/source/s1/fed1.s @@ -0,0 +1,110 @@ +signal = 48. +testing = 0 +/ +/ command interpreter for form letter editor +/ +/ +/ +command: + sys signal; 2; inter + jsr pc,initl + mov sp,spi +loop: + mov spi,sp + mov $buffer,r2 + clr r4 + clr iflag +1: + jsr pc,tfiget + cmpb $' ,r0 + beq 1f + cmpb $'\n,r0 + bne 2f + clrb (r2) + br 4f +2: + movb r0,(r2)+ + br 1b +1: + clrb (r2) + mov $argc,r3 +3: + mov $arg,r2 +2: + jsr pc,tfiget + cmpb $' ,r0 + beq 1f + cmpb $'\n,r0 + beq 1f + movb r0,(r2)+ + br 2b +1: + clrb (r2)+ + inc r4 +1: + movb -(r2),sv + cmp r2,$arg + blos 1f + movb -(r2),-(sp) + movb sv,1(sp) + cmp r2,$arg + bhi 1b + mov sp,(r3)+ + br 2f +1: + clrb -(sp) + movb sv,1(sp) + mov sp,(r3) + add $1,(r3)+ +2: + cmpb r0,$'\n + bne 3b +1: + mov -(r3),-(sp) + cmp r3,$argc + bhi 1b +4: + mov r4,-(sp) +3: + clr r0 + mov $tabl,r4 +2: + mov (r4)+,r1 + cmp r4,$tend + bhi error + add $2,r0 + mov $buffer,r2 +1: + cmpb (r1)+,(r2)+ + bne 2b + tstb (r1) + bne 1b + tstb (r2) + bne 2b + sub $2,r0 + add $jtable,r0 + clr vflag + clr qflag + jmp *(r0) +/ +error: + mov $1,r0 + sys write; err; 2 + br loop +/ +/ +tabl: c1; c2; c3; c4; c5; c6; c7; c8; +tend: 0 +c1: +c2: +c3: +c4: +c5: +c6: +c7: +c8: +err: +endt: .even +jtable: list; listf; ed; remove; rename; fin; q; memck; +spi: .=.+2 +sv: .=.+2 diff --git a/source/s1/fed2.s b/source/s1/fed2.s new file mode 100644 index 0000000..9c20fcf --- /dev/null +++ b/source/s1/fed2.s @@ -0,0 +1,533 @@ +/ +/ +ed: + mov (sp)+,r3 + ble error +econ: + sys stat; ftemp; buffer + bec 2f + sys creat; ftemp; 666 + mov r0,tmpw + sys open; ftemp; 0 + mov r0,tmpr + br 1f +2: + cmpb $'z,ftemp+9. + bne 2f + mov $1,r0 + sys write; erm; 23. + jmp loop +2: + incb ftemp+9. + br econ +1: + mov (sp),r0 + jsr pc,getspq + bes 3f + mov r0,r4 + mov r2,r1 + jsr pc,rewind + mov $buffer,r2 +1: + jsr pc,getchar + bes 1f + movb r0,(r2)+ + br 1b +1: + movb $'\n,(r2)+ + jsr pc,output + mov r4,r1 + jsr pc,rewind +2: + mov $buffer,r2 +1: + jsr pc,getchar + bes 1f + movb r0,(r2)+ + cmp r2,$bufend + blo 1b + mov tmpw,r0 + sys write; buffer; 512. + br 2b +1: + sub $buffer,r2 + beq 4f + mov r2,0f + mov tmpw,r0 + sys write; buffer; 0:.. +4: + tst iflag + beq 1f + mov tmpw,r0 + sys close + mov tmpr,r0 + sys close + sys unlink; ftemp + jmp loop +1: + mov tmpw,r0 + sys close + sys fork + br 5f + mov r1,-(sp) + sys wait + sys signal; 2; inter + mov (sp)+,r1 + mov a(r1),w(r1) +2: + mov tmpr,r0 + sys read; buffer; 512. + tst r0 + beq 2f + add $buffer,r0 + mov r0,bufend + mov $buffer,r2 +1: + movb (r2)+,r0 + jsr pc,putchar + cmp r2,bufend + blo 1b + br 2b +2: + mov tmpr,r0 + sys close + sys unlink; ftemp + tst iflag + beq 1f + jmp loop +1: + tst qflag + bgt 1f + tst (sp)+ + dec r3 + bgt 1f + jmp loop +1: jmp econ + jmp loop +3: + mov (sp),r2 + mov $2,r0 + jsr pc,allocate +1: + tstb (r2) + beq 1f + movb (r2)+,r0 + jsr pc,putchar + br 1b +1: + mov r1,r0 + mov asmem,r1 + jsr pc,putword + mov $2,r0 + jsr pc,allocate + mov r1,r0 + mov asmem,r1 + jsr pc,putword + mov r0,r1 + br 4b +5: + mov $2,r0 +1: + sys close + inc r0 + cmp r0,$10. + blo 1b + sys exec; edd; eda + sys exit +eda: edd; ftemp; 0 +edd: + .even +ftemp: +erm: + .even +tmpw: .=.+2 +tmpr: .=.+2 +/ +/ remove a 'file' from memory +/ +remove: + mov (sp)+,r3 + bgt 5f + mov $1,vflag + mov asmem,r1 + jsr pc,rewind + mov r(r1),-(sp) +4: + tst iflag + beq 1f + jmp loop +1: + jsr pc,getword + bes 4f + mov r0,r2 + jsr pc,ask + bec 1f + mov r(r1),(sp) + br 4b +1: + jsr pc,getword + br 2f +5: + mov (sp),r0 + jsr pc,getspq + bec 2f + tst qflag + blt 6f + mov (sp),r1 + jsr pc,nothere + br 3f +2: + mov r0,r1 + jsr pc,release + mov r2,r1 + jsr pc,release + jsr pc,rm +3: + tst vflag + bne 3f + tst iflag + beq 1f + jmp loop +1: + tst qflag + bgt 5b +6: + tst (sp)+ + dec r3 + bgt 5b + jmp loop +3: + mov asmem,r1 + mov (sp),r(r1) + br 4b +4: + tst (sp)+ + jmp loop +/ +/ rename a 'file' +/ +rename: + mov (sp)+,r3 + bne 1f + jmp error +1: + sub $2,r3 + blt 1f +5: + mov (sp),r0 + jsr pc,getsp + bes 4f + tst (sp)+ + sub $4,r(r1) + mov (sp),r0 + mov r2,-(sp) + mov r(r1),-(sp) + jsr pc,getsp + bes 3f + mov r2,-(sp) + mov r0,r1 + jsr pc,release + jsr pc,rm + mov (sp)+,r0 + mov (sp)+,r(r1) + jsr pc,alterword + mov (sp)+,r1 + jsr pc,release + br 5f +3: + mov (sp)+,r(r1) + mov (sp)+,r1 + jsr pc,release + mov $2,r0 + jsr pc,allocate + mov (sp)+,r2 +2: + movb (r2)+,r0 + beq 2f + jsr pc,putchar + br 2b +2: + mov r1,r0 + mov asmem,r1 + jsr pc,alterword +5: + tst iflag + beq 2f + jmp loop +2: + tst r3 + beq 2f + sub $2,r3 + bge 5b +1: + tst (sp)+ + jmp error +2: + jmp loop +4: + mov (sp)+,r1 + jsr pc,nothere + tst (sp)+ + br 5b +/ +/ list contents of asmem +/ +list: + mov $buffer,r2 + movb $'\n,(r2)+ + jsr pc,output + mov (sp)+,r3 + beq 1f + mov $1,vflag +5: + tst iflag + beq 2f + jmp loop +2: + mov (sp),r0 + jsr pc,getspq + bes 4f + mov r2,r1 + br 3f +1: + mov asmem,r1 + jsr pc,fsfile + sub $2,r(r1) +2: + tst iflag + bne 2f + jsr pc,backword + bes 2f + mov r0,r1 +3: + jsr pc,getn + movb $'\n,(r2)+ + jsr pc,output + tst vflag + bne 1f + mov asmem,r1 + sub $2,r(r1) + br 2b +1: + tst qflag + bgt 5b +4: + tst (sp)+ + dec r3 + bgt 5b +2: + mov $buffer,r2 + movb $'\n,(r2)+ + jsr pc,output + jmp loop +/ +/ list a 'file +/ +listf: + mov (sp)+,r3 + bgt 4f + jmp error +4: + mov (sp),r0 + jsr pc,getspq + bes 3f + mov r0,r4 + mov r2,r1 + jsr pc,rewind + mov $buffer,r2 + movb $'\n,(r2)+ +1: + jsr pc,getchar + bes 1f + movb r0,(r2)+ + cmp r2,$bufend + blo 1b + jsr pc,output + br 1b +1: + mov r4,r1 + jsr pc,rewind + movb $':,(r2)+ + cmp r2,$bufend + blo 2f + jsr pc,output +2: + movb $'\n,(r2)+ +1: + tst iflag + beq 2f + jmp loop +2: + cmp r2,$bufend + blo 2f + jsr pc,output +2: + jsr pc,getchar + bes 1f + movb r0,(r2)+ + br 1b +1: + jsr pc,output +3: + tst qflag + bgt 4b + tst (sp)+ + dec r3 + bgt 4b + mov $buffer,r2 + movb $'\n,(r2)+ + jsr pc,output + jmp loop +/ +fin: + jsr pc,flush + jsr pc,whead + 4 +q: + jsr pc,flush + jsr pc,whead + sys exit +memck: mov (sp)+,r3 +2: + ble 2f + mov (sp)+,r1 + cmpb (r1),$'p + bne 1f + bis $1,vflag + br 3f +1: + cmpb (r1),$'f + bne 3f + bis $2,vflag +3: + dec r3 + br 2b +2: + clr freeh + mov $freeb,r2 +1: + clr (r2)+ + cmp r2,$freen + blo 1b + mov $headers,r2 +2: + cmp l(r2),$hsz + beq 6f + jsr pc,ck + bec 1f + cmp r2,asmem + beq 1f + mov asmem,r1 + jsr pc,rewind + clr r3 +4: + inc r3 + jsr pc,getword + bes 5f + cmp r0,r2 + bne 4b +6: + inc freeh +1: +cont: + add $8.,r2 + cmp r2,$headend-4 + blo 2b + mov asmem,r1 + jsr pc,rewind +4: + jsr pc,getword + bes 4f + tst r(r0) + beq 2f + mov r0,r2 + jsr pc,ck + bes 4b +2: + sub $hblk,r0 + jsr r5,oct + mov $1,r0 + sys write; re; 24. + cmp vflag,$1 + beq 4b + bit $1,r3 + beq 2f + jsr pc,getword + mov r0,r1 + jsr pc,release + br 3f +2: + jsr pc,backword + add $4,r(r1) + mov r0,r1 + jsr pc,release +3: + jsr pc,rm + clr r3 + br 4b +4: + mov freeh,r0 + jsr r5,decml + mov $1,r0 + sys write; frh; 14. + mov $freeb,r2 + mov $1,r3 +6: + cmp r2,$freen + bhis 6f + mov (r2)+,r0 + beq 3f + jsr r5,decml + mov $1,r0 + sys write; frb; 18. + mov r3,r0 + jsr r5,decml + mov $1,r0 + sys write; lf; 1. +3: + asl r3 + br 6b +6: + mov $1,r0 + sys write; lf; 1. + jmp loop +5: + mov r2,r0 + sub $hblk,r0 + jsr r5,oct + mov $1,r0 + sys write; un; 26. + tst vflag + beq 1b + mov r2,r1 + cmp vflag,$2 + beq 3f + jsr pc,rewind + mov $buffer,r2 +2: + jsr pc,getchar + bes 2f + movb r0,(r2)+ + cmp r2,$buffer+80. + blo 2b + jsr pc,output + br 2b +2: + movb $'\n,(r2)+ + jsr pc,output + mov r1,r2 + cmp vflag,$1 + bne 3f + jmp cont +3: + jsr pc,release + jmp cont +/ +interrupt: 4 +/ +un: < header not accounted for\n> +re: < part of asmem released\n> +lf: <\n> +frh: < free headers\n > +frb: < free blocks size > +endc: .even diff --git a/source/s1/fed3.s b/source/s1/fed3.s new file mode 100644 index 0000000..7d76a07 --- /dev/null +++ b/source/s1/fed3.s @@ -0,0 +1,358 @@ +rti = 2 +.globl rm +.globl ck +.globl loop +.globl oct +.globl argc +.globl arg +.globl tfiget +.globl asmem +.globl qflag +.globl vflag +.globl getspq +.globl q +.globl ask +.globl getword +.globl r +.globl w +.globl output +.globl buffer +.globl bufend +.globl fv +.globl getsp +.globl release +.globl nothere +.globl getn +.globl getchar +.globl rewind +.globl iflag +.globl inter +/ output buffer +/ r2 = last char in buffer + 1 +/ r2 returned at beginning of buffer +/ +output: + sub $buffer,r2 + blos 1f + mov r2,0f + mov $1,r0 + sys write; buffer; 0:.. + mov $buffer,r2 +1: + rts pc +/ +/ +/ routine to find the string pointed to by r0 +/ in either memory or curly +/ r1 = where to look +/ +/ returns error set if string not there +/ returns r1 = header of string if there +getsp: + mov r0,-(sp) + mov asmem,r1 + jsr pc,rewind /memory +3: + jsr pc,getword + bes 1f + mov r0,r1 + jsr pc,rewind + mov (sp),r2 +2: + jsr pc,getchar + bes 2f + tstb (r2) + beq 4f + cmpb r0,(r2)+ + beq 2b +4: + mov asmem,r1 + add $2,r(r1) + br 3b +2: + tstb (r2) + bne 4b + mov r1,r2 + mov asmem,r1 + jsr pc,getword + tst (sp)+ + rts pc +1: + mov (sp)+,r0 + sec + rts pc +/ +/ finds header of string with name same as that pointed to by r0 +/ taking into account ? and * +getspq: + mov r0,-(sp) + mov asmem,r1 + tst qflag + bgt 1f + jsr pc,rewind +1: + jsr pc,getword + bes 1f + mov r0,r1 + jsr pc,rewind + mov (sp),r2 +2: + cmpb (r2),$'* + bne 3f + clr strflg + mov $2,qflag + inc r2 + tstb (r2) + beq 6f + mov r2,ch +3: + jsr pc,getchar + bes 2f + tstb (r2) + bne 3f + cmp $2,qflag + bne 4f + mov ch,r2 +3: + cmpb (r2),$'? + bne 3f + inc r2 + tst qflag + bne 2b + mov $1,qflag + br 2b +3: + cmpb r0,(r2)+ + bne 5f + inc strflg + br 2b +5: + cmp $2,qflag + bne 4f + tst strflg + bne 4f + dec r2 + br 2b +4: + mov asmem,r1 + add $2,r(r1) + br 1b +2: + tstb (r2) + bne 4b +6: + mov r1,r2 + mov asmem,r1 + jsr pc,getword + tst (sp)+ + rts pc +1: + mov $-1.,qflag + mov (sp)+,r0 + sec + rts pc +/ +/ tfiget +/ jsr r5,tfiget +/ +tfiget: + clr r0 + sys read; ch; 1 + bes 1f + tst iflag + beq 9f; jmp loop; 9: + tst r0 + beq 1f + movb ch,r0 + rts pc +1: jmp q +/ +/ routine to print file name and error message +/ r2 = next free byte in buffer +/ +nothere: + mov $buffer,r2 +1: + tstb (r1) + beq 1f + movb (r1)+,(r2)+ + br 1b +1: + sub $buffer,r2 + mov r2,0f + mov $1,r0 + sys write; buffer; 0:.. + mov $1,r0 + sys write; err4; 16. + rts pc +/ +/ +/ routine to put characters from string in buffer +/ r1 = header of string +/ on return r2 = next free byte in buffer +/ +getn: + mov $buffer,r2 + jsr pc,rewind +1: + jsr pc,getchar + bes 1f + movb r0,(r2)+ + cmp r2,$bufend + bhis 1f + br 1b +1: rts pc +/ +ask: + mov r2,-(sp) + mov r0,r1 + jsr pc,getn + movb $' ,(r2)+ + jsr pc,output + jsr pc,tfiget + cmpb $'\n,r0 + bne 1f +2: + mov asmem,r1 + add $2,r(r1) + mov (sp)+,r2 + sec + rts pc +1: + cmpb r0,$'y + beq 4f + cmpb r0,$'q + beq 3f +1: + tst iflag + bne 2b + jsr pc,tfiget + cmpb $'\n,r0 + bne 1b + br 2b +4: + tst iflag + bne 2b + jsr pc,tfiget + cmpb $'\n,r0 + bne 1b + mov asmem,r1 + mov (sp)+,r2 + clc + rts pc +3: + tst iflag + bne 2b + jsr pc,tfiget + cmpb $'\n,r0 + bne 1b + mov (sp)+,r2 + jmp loop +inter: + inc iflag + rti +/ to remove an entry from asmem - r points to name ptr +/ +rm: + mov r3,-(sp) + mov asmem,r1 + mov r(r1),r3 + sub $4,r(r1) + mov r(r1),r2 + mov r2,-(sp) +1: + mov r3,r(r1) + jsr pc,getword + bes 1f + mov r(r1),r3 + mov r2,r(r1) + jsr pc,alterword + mov r(r1),r2 + br 1b +1: + mov r2,w(r1) + mov (sp)+,r(r1) + mov (sp)+,r3 + rts pc +/ +/ check that header pointed to by r2 released +/ +ck: + mov r2,-(sp) + mov l(r2),r0 + sub a(r2),r0 + sub $hblk,r2 + jsr pc,log2 + asl r0 + mov r0,ch + mov frlist(r0),r0 +1: + beq 1f + cmp r2,r0 + beq 2f + add $hblk,r0 + mov (r0),r0 + br 1b +2: + mov ch,r0 + inc freeb(r0) + mov (sp)+,r2 + rts pc +1: + mov (sp)+,r2 + sec + rts pc +oct: + mov r1,-(sp) + mov r0,r1 + clr r0 + div $8.,r0 + mov r1,-(sp) + add $'0,(sp) + tst r0 + beq 1f + jsr r5,oct +1: + movb (sp)+,ch + mov $1,r0 + sys write; ch; 1 + mov (sp)+,r1 + rts r5 + +decml: + mov r1,-(sp) + mov r0,r1 + clr r0 + div $10.,r0 + mov r1,-(sp) + add $'0,(sp) + tst r0 + beq 1f + jsr r5,decml +1: + movb (sp)+,ch + mov $1,r0 + sys write; ch; 1 + mov (sp)+,r1 + rts r5 +/ +/ +iflag: 0 +qflag: 0 +vflag: 0 + .data +err4: < not in memory.\n> +err1: +end1: .even + .bss +freeh: .=.+2 +freeb: .=.+32. +freen: +ch: .=.+2 +strflg: .=.+2 +buffer: .=.+512. +bufend: .=.+2 +argc = buffer + 20. +arg = buffer + 256. +fv: .=.+2 + .text diff --git a/source/s1/file.c b/source/s1/file.c new file mode 100644 index 0000000..10f70c0 --- /dev/null +++ b/source/s1/file.c @@ -0,0 +1,237 @@ +int in; +int i 0; +char buf[512]; +int *wd { + &buf[0]}; +char *fort[]{ + "function","subroutine","common","dimension","block","integer", + "real","data","double",0}; +char *asc[]{ + "sys","mov","tst","clr","jmp",0}; +char *c[]{ + "int","char","float","double","struct","extern",0}; +char *as[]{ + "globl","byte","even","text","data","bss","comm",0}; +int ibuf[260]; +main(argc, argv) +char **argv; +{ + + while(argc > 1) { + printf("%s: ", argv[1]); + type(argv[1]); + argc--; + argv++; + } +} + +type(file) +char *file; +{ + int j,nl; + char ch; + int mbuf[20]; + + if(stat(file, mbuf) < 0) { + printf("cannot stat\n"); + return; + } + switch(mbuf[2]&060000) { + + case 020000: + printf("character"); + goto spcl; + + case 040000: + printf("directory\n"); + return; + + case 060000: + printf("block"); + +spcl: + printf(" special (%d/%d)\n", + (mbuf[6]>>8)&0377, + mbuf[6]&0377); + return; + } + + ibuf[0] = open(file, 0); + if(ibuf[0] < 0) { + printf("cannot open\n"); + return; + } + in = read(ibuf[0], buf, 512); + switch(*wd) { + + case 0407: + printf("executable\n"); + goto out; + + case 0410: + printf("pure executable\n"); + goto out; + + case 0411: + printf("separate executable\n"); + goto out; + + case 0177555: + printf("archive\n"); + goto out; + } + + i = 0; + if(ccom() == 0)goto notc; + while(buf[i] == '#'){ + j = i; + while(buf[i++] != '\n'){ + if(i - j > 255){ + printf("data\n"); + goto out; + } + if(i >= in)goto notc; + } + if(ccom() == 0)goto notc; + } +check: + if(lookup(c) == 1){ + while((ch = buf[i++]) != ';' && ch != '{')if(i >= in)goto notc; + printf("c program"); + goto outa; + } + nl = 0; + while(buf[i] != '('){ + if(buf[i] <= 0){ + printf("data\n"); + goto out; + } + if(buf[i] == ';'){ + i++; + goto check; + } + if(buf[i++] == '\n') + if(nl++ > 6)goto notc; + if(i >= in)goto notc; + } + while(buf[i] != ')'){ + if(buf[i++] == '\n') + if(nl++ > 6)goto notc; + if(i >= in)goto notc; + } + while(buf[i] != '{'){ + if(buf[i++] == '\n') + if(nl++ > 6)goto notc; + if(i >= in)goto notc; + } + printf("c program"); + goto outa; +notc: + i = 0; + while(buf[i] == 'c' || buf[i] == '#'){ + while(buf[i++] != '\n')if(i >= in)goto notfort; + } + if(lookup(fort) == 1){ + printf("fortran"); + goto outa; + } +notfort: + i=0; + if(ascom() == 0)goto notas; + j = i-1; + if(buf[i] == '.'){ + i++; + if(lookup(as) == 1){ + printf("assembler program"); + goto outa; + } + else if(buf[j] == '\n'){ + printf("roff, nroff, or eqn input"); + goto outa; + } + } + while(lookup(asc) == 0){ + if(ascom() == 0)goto notas; + while(buf[i] != '\n' && buf[i++] != ':') + if(i >= in)goto notas; + while(buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\t')if(i++ >= in)goto notas; + j = i-1; + if(buf[i] == '.'){ + i++; + if(lookup(as) == 1){ + printf("assembler program"); + goto outa; + } + else if(buf[j] == '\n'){ + printf("roff, nroff, or eqn input"); + goto outa; + } + } + } + printf("assembler program"); + goto outa; +notas: + for(i=0; i < in; i++)if(buf[i] <= 0){ + printf("data\n"); + goto out; + } + if((mbuf[2] & 00111) != 0) + printf("commands"); + else printf("probably text"); +outa: + while(i < in) + if(buf[i++] <= 0){ + printf(" with garbage\n"); + goto out; + } + while((in = read(ibuf[0],buf,512)) > 0) + for(i = 0; i < in; i++) + if(buf[i] <= 0){ + printf(" with garbage\n"); + goto out; + } + printf("\n"); +out: + close(ibuf[0]); +} +lookup(tab) +char *tab[]; +{ + char r; + int k,j,l; + while(buf[i] == ' ' || buf[i] == '\t' || buf[i] == '\n')i++; + for(j=0; tab[j] != 0; j++){ + l=0; + for(k=i; ((r=tab[j][l++]) == buf[k] && r != '\0');k++); + if(r == '\0') + if(buf[k] == ' ' || buf[k] == '\n' || buf[k] == '\t' + || buf[k] == '{' || buf[k] == '/'){ + i=k; + return(1); + } + } + return(0); +} +ccom(){ + char cc; + while((cc = buf[i]) == ' ' || cc == '\t' || cc == '\n')if(i++ >= in)return(0); + if(buf[i] == '/' && buf[i+1] == '*'){ + i =+ 2; + while(buf[i] != '*' || buf[i+1] != '/'){ + if(buf[i] == '\\')i =+ 2; + else i++; + if(i >= in)return(0); + } + if((i =+ 2) >= in)return(0); + } + if(buf[i] == '\n')if(ccom() == 0)return(0); + return(1); +} +ascom(){ + while(buf[i] == '/'){ + i++; + while(buf[i++] != '\n')if(i >= in)return(0); + while(buf[i] == '\n')if(i++ >= in)return(0); + } + return(1); +} diff --git a/source/s1/find.c b/source/s1/find.c new file mode 100644 index 0000000..d23bb72 --- /dev/null +++ b/source/s1/find.c @@ -0,0 +1,449 @@ +/* find -- find files in a pathname. + Use of find is documented in /usr/man/man1/find.1 . + + In addition, find has a secret first arg "+" which + causes each file name to be printed along with a period + if the predicates succeed. + */ +int randlast; +char *pathname; +int verbose; +struct anode { + int (*F)(); + struct anode *L, *R; +} node[100]; +int nn; /* number of nodes */ +char *fname, *path; +int now[2]; +int ap, ac; +char **av; + +struct ibuf { + int idev; + int inum; + int iflags; + char inl; + char iuid; + char igid; + char isize0; + char *isize; + int iaddr[8]; + int iatime[2]; + int imtime[2]; +} statb; + +main(argc,argv) char *argv[]; { + +struct anode *exlist; +int find(); + + time(&now); + ac = argc; av = argv; ap = 2; + pathname = argv[1]; + if(compstr(argv[1],"+")==0) { + verbose++; + ap++; + pathname = argv[2]; + } else verbose = 0; + argv[argc] = 0; + if(argc<3) { + printf("Insufficient args\n"); + exit(9); + } + if(!(exlist = exp())) { /* parse and compile the arguments */ + printf("Odd usage\n"); + exit(9); + } + if(ap=ac) return(""); + return(av[ap++]); +} + +find(exlist,fullname) /* execute predicat list with current file */ +struct anode *exlist; +char *fullname; +{ +register int i; + path = fullname; + if(verbose) printf("%s",path); + for(i=0;fullname[i];++i) + if(fullname[i]=='/') fname = &fullname[i+1]; + i = (*exlist->F)(exlist); + if(verbose) + if(i) printf(".\n"); + else printf("\n"); +} + +/* execution time functions */ +and(p) struct anode *p; { + return(((*p->L->F)(p->L)) && ((*p->R->F)(p->R))?1:0); +} +or(p) struct anode *p; { + return(((*p->L->F)(p->L)) || ((*p->R->F)(p->R))?1:0); +} +not(p) struct anode *p; { + return( !((*p->L->F)(p->L))); +} +glob(p) struct { int f; char *pat; } *p; { + return(gmatch(fname,p->pat)); +} +print() { + printf("%s\n",path); + return(1); +} +mtime(p) struct { int f, t, s; } *p; { + return(scomp((now[0]-statb.imtime[0])*3/4,p->t,p->s)); +} +atime(p) struct { int f, t, s; } *p; { + return(scomp((now[0]-statb.iatime[0])*3/4,p->t,p->s)); +} +user(p) struct { int f, u, s; } *p; { + return(scomp(statb.iuid,p->u,p->s)); +} +group(p) struct { int f, u; } *p; { + return(p->u == statb.igid); +} +links(p) struct { int f, link, s; } *p; { + return(scomp(statb.inl,p->link,p->s)); +} +size(p) struct { int f, sz, s; } *p; { + register int i; + i = statb.isize0 << 7; + i = i | ((statb.isize>>9) & 0177); + return(scomp(i,p->sz,p->s)); +} +perm(p) struct { int f, per, s; } *p; { +int i; + i = (p->s=='-') ? p->per : 03777; /* '-' means only arg bits */ + return((statb.iflags & i & 017777) == p->per); +} +type(p) struct { int f, per, s; } *p; { + return((statb.iflags&060000)==p->per); +} +exeq(p) struct { int f, com; } *p; { + return(doex(p->com)); +} +ok(p) struct { int f, com; } *p; { + char c; int yes; + yes = 0; + printf("%s ... %s ...? ",av[p->com],path); + if((c=getchar())=='y') yes = 1; + while(c!='\n') c = getchar(); + if(yes) return(doex(p->com)); + return(0); +} + +/* support functions */ +scomp(a,b,s) char s; { /* funny signed compare */ + if(s == '+') + return(a > b); + if(s == '-') + return(a < (b * -1)); + return(a == b); +} +doex(com) { + int ccode; + int np, i, c; + char *nargv[50], *ncom, *na; + + ccode = np = 0; + while (na=av[com++]) { + if(compstr(na,";")==0) break; + if(compstr(na,"{}")==0) nargv[np++] = path; + else nargv[np++] = na; + } + nargv[np] = 0; + if (np==0) return(9); + if(fork()) /*parent*/ wait(&ccode); + else { /*child*/ + execv(nargv[0], nargv, np); + i = 0; + ncom = "/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + while(c=nargv[0][i]) { + ncom[9+i++] = c; + } + ncom[9+i] = '\0'; + execv(ncom+4, nargv, np); + execv(ncom, nargv, np); + exit(9); + } + return(ccode ? 0:1); +} + +char fin[518]; +getunum(s) char *s; { /* find username in /etc/passwd & return num. */ +int i; +char str[20], *sp, c; + i = -1; + fin[0] = open("/etc/passwd",0); + while(c = getchar()) { + if(c=='\n') { + sp = str; + while((*sp = getchar()) != ':') + if(! *sp++) goto RET; + *sp = '\0'; + if(compstr(str,s)==0) { + while((c=getchar()) != ':') + if(! c) goto RET; + sp = str; + while((*sp = getchar()) != ':') sp++; + *sp = '\0'; + i = atoi(str); + break; + } + } + } + RET: + close(fin); + fin[0] = 0; + return(i); +} + +compstr(s1,s2) char s1[], s2[]; { /* compare strings: */ +register char *c1, *c2; + c1 = s1; c2 = s2; + while(*c1 == *c2) + if(*c1++ == '\0') + return(0); /* s1 == s2 */ + else c2++; + return(*c1 > *c2 ? 1 : -1); +} + +int descend(name,goal,func,arg) +int (*func)(); +char *name, goal; +{ + int dir /* open directory */, offset /* in directory */; + int dsize, top; + struct { + int dinode; + char dname[14]; + } dentry[32]; + register int i, j, k; + char aname[128]; + + if(stat(name,&statb)<0) { + printf("--bad status %s\n",name); + return(0); + } +/* + if((statb.iflags&060000)!=040000){ /*not a directory*/ +/* + if(goal=='f'||goal=='b') /* search goal for files */ +/* + (*func)(arg,name); + return(1); + } else if(goal=='d' || goal=='b') /* search goal is directories */ +/* + (*func)(arg,name); +*/ + (*func)(arg,name); + if((statb.iflags&060000)!=040000) + return(1); + + top = statb.isize; + for(offset=0 ; offset < top ; offset =+ 512) { /* each block */ + dsize = 512<(top-offset) ? 512 : (top-offset); + if((dir=open(name,0))<0) { + printf("--cannot open %s\n",name); + return(0); + } + if(offset) seek(dir,offset,0); + if(read(dir,&dentry,dsize)<0) { + printf("--cannot read %s\n",name); + return(0); + } + close(dir); + for(i = 0; i < (dsize>>4); ++i) { /* each dir. entry */ + if(dentry[i].dinode==0 || + compstr(dentry[i].dname,".")==0 || + compstr(dentry[i].dname,"..")==0) + continue; + if (dentry[i].dinode == -1) break; + for(j=0;aname[j]=name[j];++j); + if(aname[j-1]!='/') aname[j++] = '/'; + for(k=0; (aname[j++]=dentry[i].dname[k]) && + k<13; ++k); + aname[j] = '\0'; + if(descend(aname,goal,func,arg)==0) + printf("--%s\n",name); + } + } + return(1); +} + +gmatch(s, p) /* string match as in glob */ +char *s, *p; { + if (*s=='.' && *p!='.') return(0); + return(amatch(s, p)); +} + +amatch(s, p) +char *s, *p; +{ + register int cc, scc, k; + int c, lc; + + scc = *s; + lc = 077777; + switch (c = *p) { + + case '[': + k = 0; + while (cc = *++p) { + switch (cc) { + + case ']': + if (k) + return(amatch(++s, ++p)); + else + return(0); + + case '-': + k =| lc <= scc & scc <= (cc=p[1]); + } + if (scc==(lc=cc)) k++; + } + return(0); + + case '?': + caseq: + if(scc) return(amatch(++s, ++p)); + return(0); + case '*': + return(umatch(s, ++p)); + case 0: + return(!scc); + } + if (c==scc) goto caseq; + return(0); +} + +umatch(s, p) +char *s, *p; +{ + if(*p==0) return(1); + while(*s) + if (amatch(s++,p)) return(1); + return(0); +} diff --git a/source/s1/form1.s b/source/s1/form1.s new file mode 100644 index 0000000..5a1edf1 --- /dev/null +++ b/source/s1/form1.s @@ -0,0 +1,165 @@ +signal = 48. +testing = 0 +/ form letter generator +/ command sequence +/ form proto arg1 arg2... +/ where proto is letter +rfo: + sys signal; 2; int + mov $-1,buf + mov (sp)+,r2 /arg count + tst (sp)+ /skip first arg + sub $2,r2 + bge 2f + mov $default,-(sp) +2: + mov (sp)+,letter + +1: sys stat; otfil; buf + bec 2f + sys creat; otfil; 666 + bec cont +2: cmpb $'z,otfil+4 + beq err3 + incb otfil+4 + br 1b + +err3: + mov $1,r0 + sys write; mes3; 24. + sys exit +mes3: +otfil: +default: + .even + +cont: mov r0,rfo + clr rfo+2 + jsr pc,initl + +/ set up argument list +/ + mov $arg,r3 + mov $10.,r0 + jsr pc,allocate + mov r1,(r3)+ +1: + dec r2 + blt 1f + mov $10.,r0 + jsr pc,allocate + mov r1,(r3)+ + mov (sp)+,r4 +2: + movb (r4)+,r0 + beq 1b + jsr pc,putchar + br 2b + +1: + sys time + ashc $-7,r0 + div $675.,r0 + mov $daytab,r2 + sub $1461.,r0 + +1: sub (r2)+,r0 + bge 1b + add -(r2),r0 + mov r0,-(sp) + mov arg,r1 + mov montab-daytab(r2),r2 +1: + movb (r2)+,r0 + beq 1f + jsr pc,putchar + br 1b +1: + movb $' ,r0 + jsr pc,putchar + clr r0 + mov (sp),r1 + inc r1 + div $10.,r0 + mov r1,(sp) + mov arg,r1 + tst r0 + beq 1f + add $'0,r0 + jsr pc,putchar +1: + mov (sp)+,r0 + add $'0,r0 + jsr pc,putchar + jmp loop + +daytab: 31.; 28.; 31.; 30.; 31.; 30.; 31.; 31.; 30.; 31.; 30.; 999. + +montab: m1; m2; m3; m4; m5; m6; m7; m8; m9; m10; m11; m12 + +m1: +m2: +m3: +m4: +m5: +m6: +m7: +m8: +m9: +m10: +m11: +m12: + +buf: .=.+34. +.=rfo+516. + +loop: + mov $10.,r0 + jsr pc,allocate + mov r1,opointer + jsr pc,allocate + mov r1,ipointer + jsr pc,allocate + mov r1,curly + mov $10.,r0 + jsr pc,allocate + mov r1,scr + mov letter,r3 + movb $'\{,r0 + jsr pc,putchar +1: + movb (r3)+,r0 + beq 1f + jsr pc,putchar + br 1b +1: + movb $'\},r0 + jsr pc,putchar + + clr switch + + tst iflag + beq 1f + mov $1,tflag + jmp interrupt +1: + jsr pc,scan + + movb $'\n,r0 + jsr r5,putc + jsr r5,flushb + + mov scr,r1 + jsr pc,release + jsr pc,relarg + mov opointer,r1 + jsr pc,release + mov ipointer,r1 + jsr pc,release + jsr pc,relcurl + jsr pc,flush + jsr pc,whead + .if testing + 4 + .endif + sys exit diff --git a/source/s1/form2.s b/source/s1/form2.s new file mode 100644 index 0000000..d9c9674 --- /dev/null +++ b/source/s1/form2.s @@ -0,0 +1,92 @@ +/ scan +/ r1 = pointer to input header +/ r0 = pointer to output header +/ switch = 0 real output +/ not 0 output to r0 +scan: + mov r0,-(sp) + mov r1,-(sp) + +1: + mov (sp),r1 + jsr pc,getchar + bes 5f + cmpb r0,$'\\ + beq 3f + cmpb r0,$'\[ + beq 4f + cmpb r0,$'\{ + beq 4f + cmpb r0,$'\] + beq 1f + cmpb r0,$'\} + beq 7f + cmpb r0,$'\n + bne 6f + jsr pc,lookchar + bes 5f + movb $'\n,r0 +6: + tst switch + beq 2f + mov 2(sp),r1 + jsr pc,putchar + br 1b +2: + jsr r5,putc + br 1b +3: + jsr pc,getchar + br 6b +/ have [ or { +4: + mov r(r1),-(sp) + jsr pc,getchar + bes 1f + cmpb r0,$'0 + blt 4f + cmpb r0,$'9 + bgt 4f + jsr pc,getchar + cmpb r0,$'\] + beq 3f + cmpb r0,$'\} + beq 3f + +4: + mov (sp)+,r(r1) + mov 2(sp),r0 + jsr pc,esub + mov r1,(sp) + mov r0,2(sp) + br 1b + +/ have arg +3: + tst switch + beq 2f + mov opointer,r1 + mov 4(sp),r0 + jsr pc,putword + mov 2(sp),r1 +2: + mov (sp)+,r(r1) + jsr pc,getchar + inc r(r1) /skip ] + jsr pc,earg + br 1b + +5: + tst argf + bne 1f + mov ipointer,r1 + jsr pc,pop + bes 1f + mov r0,(sp) + br 1b +7: + inc curlyf +1: + mov (sp)+,r1 + mov (sp)+,r0 + rts pc diff --git a/source/s1/form3.s b/source/s1/form3.s new file mode 100644 index 0000000..6c58111 --- /dev/null +++ b/source/s1/form3.s @@ -0,0 +1,147 @@ +/ esub +/ r1 = pointer to input string +/ +esub: + mov r1,-(sp) + tst switch + beq 1f + mov opointer,r1 + jsr pc,putword +1: + tst iflag + beq 1f + mov $2,tflag + jmp interrupt +1: + inc switch + mov $10.,r0 + jsr pc,allocate + mov r1,r0 + mov opointer,r1 + jsr pc,putword + mov (sp)+,r1 + jsr pc,scan + + tst iflag + beq 1f + mov $3,tflag + jmp interrupt +1: + mov r2,-(sp) + mov r1,r0 + mov ipointer,r1 + jsr pc,putword + mov opointer,r1 + jsr pc,pop + bec 9f; 4; 9: + mov r0,-(sp) /last output + mov asmem,r1 + jsr pc,getsp + bes 2f +5: + clr curlyf + mov (sp),r1 + mov r0,r2 + jsr pc,release +6: + mov opointer,r1 + jsr pc,pop + bec 4f + clr switch +4: mov r2,r1 + jsr pc,rewind + tst (sp)+ + mov (sp)+,r2 + rts pc + + +/ not in memory +2: + mov curly,r1 + jsr pc,getsp + bes 2f + br 5b +2: + mov (sp),r1 + jsr pc,rewind + mov $'\[,r0 +1: + jsr r5,tfoput + jsr pc,getchar + bec 1b + mov $'\],r0 + jsr r5,tfoput + mov $10.,r0 + jsr pc,allocate + mov r1,r2 + mov (sp),r0 + tst curlyf + beq 1f + clr curlyf + mov curly,r1 + jsr pc,addentry + br 2f +1: + mov asmem,r1 + jsr pc,whead + jsr pc,addentry +2: + mov r2,r1 + jsr pc,accept + br 6b +/ +/ +/ earg +/ r0 = number in ascii +/ +earg: + tst iflag + beq 1f + mov $4,tflag + jmp interrupt +1: + mov r1,-(sp) + inc argf + sub $'0,r0 + asl r0 + mov arg(r0),r1 + beq 5f +4: + mov (sp),r0 + mov r1,(sp) + mov ipointer,r1 + jsr pc,putword + mov opointer,r1 + jsr pc,pop + bec 3f + clr switch +3: + mov (sp)+,r1 + jsr pc,rewind + jsr pc,scan + mov r0,-(sp) + mov ipointer,r1 + jsr pc,pop + bec 9f; 4; 9: + mov r0,r1 + clr argf + clr curlyf + mov (sp)+,r0 + rts pc +5: + mov r0,-(sp) + mov $'\[,r0 + jsr r5,tfoput + mov (sp),r0 + asr r0 + add $'0,r0 + jsr r5,tfoput + mov $'\],r0 + jsr r5,tfoput + mov $10.,r0 + jsr pc,allocate + mov (sp)+,r0 + mov r1,arg(r0) + jsr pc,accept + + br 4b diff --git a/source/s1/form4.s b/source/s1/form4.s new file mode 100644 index 0000000..6c7259b --- /dev/null +++ b/source/s1/form4.s @@ -0,0 +1,250 @@ +rti = 2 +/ accept +/ r1 = header of where to put it +/ +accept: + mov r0,-(sp) + movb $':,r0 + jsr r5,tfoput + movb $' ,r0 + jsr r5,tfoput +2: + jsr r5,tfiget + cmpb r0,$'\n + beq 1f + jsr pc,putchar + br 2b +1: + jsr pc,putchar + jsr r5,tfiget + cmpb r0,$'\n + beq 1f + jsr pc,putchar + br 2b +1: + mov (sp)+,r0 + rts pc +/ +/ +/ routine to get the last word from the string +/ r1=header addr +/ +pop: + jsr pc,fsfile + jsr pc,backword + bes 1f + sub $2,w(r1) +1: + rts pc +/ +/ +/ routine to add an entry to assoc mem or curly +/ r1 = header +/ r0 = header of string name +/ r2 = header of string +/ +addentry: + jsr pc,putword + mov r2,r0 + jsr pc,putword + rts pc +/ +/ +/ routine to find the string pointed to by r0 +/ in either memory or curly +/ r1 = where to look +/ +/ returns error set if string not there +/ returns r1 = header of string if there +/ +getsp: + mov r0,-(sp) + mov r1,-(sp) + jsr pc,rewind /memory +3: + mov 2(sp),r1 + jsr pc,rewind /output + mov (sp),r1 + jsr pc,getword + bes 1f + mov r0,r1 + mov r0,-(sp) + jsr pc,rewind /string +2: + mov (sp),r1 + jsr pc,getchar + bes 2f + movb r0,r2 + mov 4(sp),r1 + jsr pc,getchar + bes 4f + cmpb r0,r2 + beq 2b +4: + tst (sp)+ +4: + mov (sp),r1 + add $2,r(r1) + br 3b +2: + tst (sp)+ + mov 2(sp),r1 + cmp r(r1),w(r1) + bne 4b + mov (sp)+,r1 + jsr pc,getword + tst (sp)+ + rts pc +1: + mov (sp)+,r1 + mov (sp)+,r0 + sec + rts pc +/ +/ +/ tfoput +/ +/ jsr r5,tfoput +/ +tfoput: + mov r0,ch + mov $1,r0 + sys write; ch; 1 + rts r5 +/ +/ +/ tfiget +/ +/ jsr r5,tfiget +/ +tfiget: + clr r0 + sys read; ch; 1 + bes 1f + tst r0 + beq 1f + movb ch,r0 + rts r5 +1: + jsr r5,flushb + tst argf + beq 1f + mov opointer,r1 + jsr pc,pop +1: + mov $5,tflag + jmp interrupt +/ +/ putc +/ jsr r5,putc +/ +putc: + mov r1,-(sp) + mov r2,-(sp) + mov $rfo+2,r1 + mov r1,r2 + add (r1),r2 + movb r0,2(r2) + inc (r1) + cmp (r1),$512. + bge 1f + mov (sp)+,r2 + mov (sp)+,r1 + rts r5 +1: + mov (sp)+,r2 + mov (sp)+,r1 +/ +/ +/ flush output buffer to output file. +/ +flushb: + mov r1,-(sp) + mov r0,-(sp) + mov $rfo,r1 + mov (r1)+,r0 + mov (r1),0f+2 + beq 1f + clr (r1)+ + mov r1,0f + sys write; 0:..;.. +1: + mov (sp)+,r0 + mov (sp)+,r1 + rts r5 +relarg: + mov $arg,r2 +1: + mov (r2)+,r1 + beq 2f + jsr pc,release + br 1b +2: + cmp r2,$arge + blt 1b + rts pc +/ +relcurl: + mov curly,r1 + jsr pc,rewind +1: + jsr pc,getword + bes 1f + mov r0,r1 + jsr pc,release + mov curly,r1 + br 1b +1: + jsr pc,release + rts pc +/ +int: + inc iflag + rti +/ +interrupt: + jsr pc,relarg + tst opointer + beq 2f +1: + mov opointer,r1 + jsr pc,rewind +1: + jsr pc,getword + bes 1f + mov r0,r1 + jsr pc,release + mov opointer,r1 + br 1b +1: + mov opointer,r1 + jsr pc,release + tst ipointer + beq 2f + mov ipointer,r1 + jsr pc,release + tst curly + beq 2f + jsr pc,relcurl + tst scr + beq 2f + mov scr,r1 + jsr pc,release +2: + jsr pc,flush + jsr pc,whead + sys exit +letter: .=.+2 +arg: .=.+20. +arge: 0 +argf: .=.+2 +switch: .=.+2 +curly: .=.+2 +curlyf: .=.+2 +ch: .=.+2 +opointer: .=.+2 +ipointer: .=.+2 +scr: .=.+2 +iflag: 0 +tflag: 0 +end: diff --git a/source/s1/form5.s b/source/s1/form5.s new file mode 100644 index 0000000..10bed27 --- /dev/null +++ b/source/s1/form5.s @@ -0,0 +1,741 @@ +.globl b1 +.globl hblk +.globl headers +.globl initl +.globl asmem +.globl b1s +.globl b1e +.globl w1 +.globl stats +.globl lookchar +.globl flush +.globl fsfile +.globl seekchar +.globl backspace +.globl alterchar +.globl zero +.globl getchar +.globl putchar +.globl copy +.globl rewind +.globl create +.globl allocate +.globl release +.globl collect +.globl w,r,a,l +.globl getword +.globl putword +.globl backword +.globl alterword +/ +/ +/ routine to read next character from string +/ pointer to by r1; character returned in r0 +/ c-bit set if character not availiable (eof) +/ +/ mov ...,r1 +/ jsr pc,getchar +/ movb r0,... +/ +getchar: + jsr pc,lookchar + bes 1f + inc r(r1) + tst r0 /clears c-bit +1: rts pc +/ +/ +/ routine to read a string backwards +/ the read pointer is decremented before reading +/ +/ mov ...,r1 +/ jsr pc,backspace +/ mov r0,... +/ +backspace: + cmp a(r1),r(r1) + bhis nochc + dec r(r1) + jsr pc,lookchar + rts pc +nochc: clr r0 + sec + rts pc +/ +/ +/ routine to put a word onto the string +/ +/ mov ...,r1 +/ mov ...,r0 +/ jsr pc,putword +/ +putword: + mov r0,-(sp) + sub $hblk,r0 + jsr pc,putchar + swab r0 + jsr pc,putchar + mov (sp)+,r0 + rts pc +/ +/ +/ routine to get a word from the string +/ +/ mov ...,r1 +/ jsr pc,getword +/ mov r0,... +/ +getword: + jsr pc,lookchar + bes 1f + movb r0,nchar + inc r(r1) + jsr pc,lookchar + bes 1f + movb r0,nchar+1 + inc r(r1) + mov nchar,r0 + add $hblk,r0 +1: rts pc +/ +/ +/ routine to alter the word pointed to by r(r1) +/ by replacing the word there with r0 +/ +/ mov wd,r0 +/ mov ...,r1 +/ jsr pc,alterword +/ +alterword: + mov r0,-(sp) + sub $hblk,r0 + jsr pc,alterchar + swab r0 + jsr pc,alterchar + mov (sp)+,r0 + rts pc +/ +/ +/ routine to get words backwards from string +/ +/ mov ...,r1 +/ jsr pc,backword +/ mov r0,... +/ +backword: + cmp a(r1),r(r1) + bhis nochw + dec r(r1) + jsr pc,lookchar + movb r0,nchar+1 + cmp a(r1),r(r1) + bhis nochw + dec r(r1) + jsr pc,lookchar + movb r0,nchar + mov nchar,r0 + add $hblk,r0 + rts pc +/ +nochw: + clr r0 + sec + rts pc +/ +/ +/ routine to copy the contents of one string +/ to another. +/ +/ mov source,r0 +/ mov dest,r1 +/ jsr pc,copy +/ mov r1,... +/ +/ on return, r1 points to the new string and should +/ be saved. r0 is preserved. +/ +copy: + inc stats+12. + mov r0,-(sp) + mov r1,-(sp) + mov r2,-(sp) + mov r3,-(sp) + mov w(r0),r2 + sub a(r0),r2 /W-A (old) + mov l(r1),r3 + sub a(r1),r3 /L-A (new) + cmp r2,r3 + blos 1f + mov r2,r0 + jsr pc,allocate + mov 4(sp),r0 /new + jsr pc,swap + jsr pc,release + mov r0,r1 + mov 0(sp),r0 /old +1: + mov a(r1),w(r1) /rewind w pointer + cmp r2,$512. + blos copy1 /is a short string +/ + jsr pc,flush + jsr pc,reset +/ + mov a(r0),-(sp) +4: + mov (sp),0f + mov afi,r0 + sys seek;0:.. ;0 /set input pointer + cmp r2,$512. + blos 2f + mov $512.,r3 /# output this time + mov r3,0f + mov r3,3f + add r3,(sp) + sub r3,r2 /# left to output + br 1f +2: + mov r2,0f + mov r2,3f + mov r2,r3 + clr r2 +1: + mov afi,r0 + sys read;b1;0:.. + bes bad + cmp r0,r3 + bne bad + mov afout,r0 + mov (r1),0f + add r3,(r1) + sys seek;0:.. ;0 + sys write;b1;3:.. + bes bad + tst r2 + bgt 4b + tst (sp)+ +/ +/ fix up read ptr of new string +/ +copy2: + mov 6(sp),r0 /restore r0 + mov r(r0),r2 + sub a(r0),r2 + add a(r1),r2 + mov r2,r(r1) +/ +/ restore and return +/ + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r1 + mov (sp)+,r0 + rts pc +/ +bad: mov $1,r0 + sys write;1f;2f-1f + 4 +1: +2: .even +/ +swap: + mov w(r1),-(sp) + mov w(r0),w(r1) + mov (sp),w(r0) + mov r(r1),(sp) + + mov r(r0),r(r1) + mov (sp),r(r0) + mov a(r1),(sp) + mov a(r0),a(r1) + mov (sp),a(r0) + mov l(r1),(sp) + mov l(r0),l(r1) + mov (sp)+,l(r0) + rts pc +/ +/ copy a short string +/ +copy1: + mov r(r0),-(sp) + mov a(r0),r(r0) + mov nchar,-(sp) + mov r0,r2 /old + mov r1,r3 /new +1: + mov r2,r1 + jsr pc,getchar + bes 1f + mov r3,r1 + jsr pc,putchar + br 1b +1: + mov r2,r0 + mov (sp)+,nchar + mov (sp)+,r(r0) + mov r3,r1 + br copy2 +/ +/ +/ +/ +/ +/ routine to rewind read pointer of string +/ pointed to by r1 +/ +/ mov ...,r1 +/ jsr pc,rewind +/ +rewind: + mov a(r1),r(r1) + rts pc +/ +/ +/ routine to rewind write pointer of string +/ pointed to by r1 +/ +/ mov ...,r1 +/ jsr pc,create +/ +create: + mov a(r1),w(r1) + mov a(r1),r(r1) + rts pc +/ +/ +/ routine to zero a string +/ +/ mov ...,r1 +/ jsr pc,zero +/ +zero: + mov r0,-(sp) + .if testing + jsr pc,preposterous + .endif + mov a(r1),w(r1) + clrb r0 +1: cmp w(r1),l(r1) + bhis 1f + jsr pc,putchar + br 1b +1: mov a(r1),w(r1) + mov (sp)+,r0 + rts pc +/ +/ +/ +/ routine to move the read pointer of a string to the +/ relative position indicated by r0. the string is +/ extended if necessary - there is no error return. +/ +/ mov position,r0 +/ mov ...,r1 +/ jsr pc,seekchar +/ +seekchar: + mov r1,-(sp) + mov r0,-(sp) + .if testing + jsr pc,preposterous + .endif + inc stats+10. +1: + mov (sp),r0 + add a(r1),r0 + cmp r0,l(r1) + bhi 3f + mov r0,r(r1) + cmp r0,w(r1) + blo 1f + mov r0,w(r1) + br 1f +3: + mov (sp),r0 + jsr pc,allocate + mov 2(sp),r0 + jsr pc,copy + jsr pc,swap + jsr pc,release + mov 2(sp),r1 + br 1b +1: + mov (sp)+,r0 + mov (sp)+,r1 + rts pc +/ +/ +/ routine to move read pointer of string to end of string +/ +/ mov ...,r1 +/ jsr pc,fsfile +/ +fsfile: + mov r0,-(sp) + .if testing + jsr pc,preposterous + .endif + inc stats+10. + mov w(r1),r(r1) + mov (sp)+,r0 + rts pc +/ +/ +/ routine to place the character in r0 at the current +/ position of the read pointer - the read pointer +/ is not moved. +/ +/ movb ch,r0 +/ mov ...,r1 +/ jsr pc,alterchar +/ mov r1,... +/ +alterchar: + mov r2,-(sp) + mov r1,-(sp) + mov r0,nchar + .if testing + jsr pc,preposterous + .endif + inc stats+8. +1: cmp r(r1),l(r1) /W,L + blo 3f + mov l(r1),r0 + inc r0 + sub a(r1),r0 /W-A+1 + jsr pc,allocate + mov (sp),r0 + jsr pc,copy + jsr pc,swap + jsr pc,release + mov (sp),r1 +3: + mov r(r1),r0 + jsr pc,bufchar + bec 2f + jsr pc,getbuf + +2: movb nchar,(r0) + mov $1,w1(r2) + mov nchar,r0 /to preserve r0 for user + inc r(r1) + cmp r(r1),w(r1) + blos 3f + mov r(r1),w(r1) +3: + mov (sp)+,r1 + mov (sp)+,r2 + rts pc +/ +/ +/ routine to look at next character from string +/ pointed to by r1; character returned in r0 +/ c-bit set if character not available (end of file) +/ r1 is preserved +/ +/ mov ...,r1 +/ jsr pc,lookchar +/ movb r0,... +/ +lookchar: + mov r2,-(sp) + inc stats+6. + .if testing + jsr pc,preposterous + .endif + cmp w(r1),r(r1) /W,R + blos noch + mov r(r1),r0 + jsr pc,bufchar + bec 2f + jsr pc,getbuf +/ +2: + inc flag + bne 2f + jsr pc,fixct + br 1f +2: + mov flag,u1(r2) +1: + mov (sp)+,r2 + movb (r0),r0 + tst r0 /clears c-bit + rts pc +/ +noch: + mov (sp)+,r2 + clr r0 + sec + rts pc +/ +/ +/ routine to put a character into the string +/ pointed to by r1; character in r0 +/ r0 is preserved; r1 points to the string +/ after return and must be saved. +/ +/ movb ch,r0 +/ mov ...,r1 +/ jsr pc,putchar +/ mov r1,... +/ +putchar: + mov r2,-(sp) + mov r1,-(sp) + mov r0,nchar + .if testing + jsr pc,preposterous + .endif + inc stats+8. +1: cmp w(r1),l(r1) /W,L + blo 3f + mov w(r1),r0 + inc r0 + sub a(r1),r0 /W-A+1 + jsr pc,allocate + mov (sp),r0 + jsr pc,copy + jsr pc,swap + jsr pc,release + mov (sp),r1 +3: + mov w(r1),r0 + jsr pc,bufchar + bec 2f + jsr pc,getbuf +2: movb nchar,(r0) + mov $1,w1(r2) + mov nchar,r0 /to preserve r0 for user + inc w(r1) + inc flag + bne 2f + jsr pc,fixct + br 1f +2: + mov flag,u1(r2) +1: + mov (sp)+,r1 + mov (sp)+,r2 + rts pc +/ +/ +/ routine to flush contents of all buffers. +/ +/ jsr pc,flush +/ +flush: + mov r1,-(sp) + mov r2,-(sp) + mov r3,-(sp) + clr r3 +1: + cmp r3,$numb + bhis 1f + mov r3,r2 + asl r2 + tst w1(r2) + ble 2f + mov r3,r1 + ashc $9.,r1 + bic $777,r1 + add $b1,r1 + jsr pc,clean +2: + inc r3 + br 1b +1: + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r1 + rts pc +/ +/ +reset: + mov r3,-(sp) + mov r2,-(sp) + clr r3 +1: + cmp r3,$numb + bge 1f + mov r3,r2 + asl r2 + mov $-1.,w1(r2) + clr b1s(r2) + clr b1e(r2) + clr u1(r2) + inc r3 + br 1b +1: + clr flag + mov (sp)+,r2 + mov (sp)+,r3 + rts pc +/ +/ +/ routine to read from disc to a buffer +/ wcing the buffer if necessary +/ +/ mov disc addr,r0 +/ mov buffer addr,r2 +/ jsr pc,getb +/ +/ on return r0 = addr of byte in buffer +/ +getb: + mov r3,-(sp) + mov r1,-(sp) + mov r0,-(sp) + mov r2,r3 + asr r3 + mov r3,r1 + ashc $9.,r1 + bic $777,r1 + add $b1,r1 + tst w1(r2) / w + ble 1f + + jsr pc,clean + +1: mov (sp),r0 + bic $777,r0 /get lowest multiple of 512. + mov r0,0f + mov r0,b1s(r2) /set start + mov afi,r0 + sys seek;0:..;0 + mov r1,0f + sys read;0:..;512. + + mov b1s(r2),b1e(r2) + add $512.,b1e(r2) / set end + clr w1(r2) /clear w + mov (sp)+,r0 + sub b1s(r2),r0 + add r1,r0 / set r0=byte addr in buffer + mov (sp)+,r1 + mov (sp)+,r3 + rts pc +/ +/ +/ routine to wc a buffer +/ +/ mov buffer addr,r2 +/ mov buffer addr+6,r1 beginning of buffer +/ jsr pc,clean +/ +clean: + inc stats+24. + mov r0,-(sp) + mov b1s(r2),0f + mov afout,r0 + sys seek;0:..;0 + mov r1,0f + sys write;0:..;512. + + clr w1(r2) /clear w + mov (sp)+,r0 + rts pc +/ +/ +/ routine to get buffer addr of byte whose disc +/ addr is in r0 - also returns addr of write +/ flag for buffer in r2 +/ +/ mov disc addr,r0 +/ jsr pc,bufchar +/ mov (r0),r0 for read +/ inc (r2) for write must inc w +/ +/ c-bit set if char not in either buffer +/ +bufchar: + mov r1,-(sp) + mov r3,-(sp) + clr r3 +1: + mov r3,r2 + asl r2 + cmp r0,b1s(r2) + blo 2f + cmp r0,b1e(r2) + bhis 2f + sub b1s(r2),r0 + mov r3,r1 + ashc $9.,r1 + bic $777,r1 + add r1,r0 + add $b1,r0 + mov (sp)+,r3 + mov (sp)+,r1 + clc + rts pc +2: + inc r3 + cmp r3,$numb + blt 1b + mov (sp)+,r3 + mov (sp)+,r1 + sec + rts pc +/ +/ +/ routine to get a buffer +/ +/ mov disc addr,r0 +/ jsr pc,getbuf +/ mov (r0),r0 (for read) +/ inc (r2) must inc w for w +/ +getbuf: + mov r4,-(sp) + mov r3,-(sp) + mov $2,r3 + clr r2 + mov $1,r4 +1: + cmp r4,$numb + bge 1f + cmp u1(r3),u1(r2) + bhis 2f + mov r3,r2 +2: + inc r4 + add $2.,r3 + br 1b +1: + mov r2,r3 + jsr pc,getb + add $stats+14.,r3 + inc (r3) + mov (sp)+,r3 + mov (sp)+,r4 + rts pc +/ +/ +/ this routine renumbers the time used cell u1(r2) +/ of the buffers when the clock overflows +/ +fixct: + mov r1,-(sp) + mov r3,-(sp) + mov $numb,r1 + mov $numb,flag +2: + mov r1,u1(r2) + dec r1 + bge 1f + mov (sp)+,r3 + mov (sp)+,r1 + rts pc +1: + clr r2 + mov $2,r3 +1: + cmp r3,$numb2 + bge 2b + cmp u1(r3),u1(r2) + blo 2f + mov r3,r2 +2: + add $2,r3 + br 1b diff --git a/source/s1/form6.s b/source/s1/form6.s new file mode 100644 index 0000000..bfd41e5 --- /dev/null +++ b/source/s1/form6.s @@ -0,0 +1,456 @@ +.globl b1 +.globl log2 +.globl frlist +.globl stats +.globl b1s +.globl b1e +.globl w1 +/ here to allocate a new block +/ +/ +/ mov ...,r0 +/ jsr pc,allocate +/ mov r1,... +/ +/ requested size in bytes in r0 +/ pointer to header of allocated block returned in r1 +/ r0 is preserved +/ +/ convert to words, adjust for header, round up +/ to a power of two +/ +/ each block has a four-word header +/ W - write ptr (also used as link ptr in frlist) +/ R - read ptr +/ A - pointer to head of data +/ L - ptr to (end+1) of data +hsz=6144. +datasz = 32768. +numb=4. +numb2=2*numb +w=0 +r=2 +a=4 +l=6 +/ +allocate: + clr garbage + mov r0,-(sp) + mov r2,-(sp) + mov r3,-(sp) + inc stats + bne 9f; inc stats; 9: + cmp r0,$datasz + blo 9f; 4; 9: + dec r0 + bmi 1f + jsr pc,log2 + inc r0 +1: asl r0 + mov r0,-(sp) + add $2,r0 + cmp r0,$frend-frlist+2 + blo zzz + 4 +/ +/ look on free list for block of required size +/ +zzz: + mov (sp),r0 + tst frlist(r0) + beq xxx +/ +/ found it, allocate and return +/ + mov frlist(r0),r1 + add $hblk,r1 + mov (r1),frlist(r0) + mov a(r1),r0 + mov r0,w(r1) /W + mov r0,r(r1) /R + tst (sp)+ + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r0 +/ jsr pc,whead + rts pc +/ +/ no block of required size +/ look for larger block +/ +xxx: + tst hblk + beq www + tst (r0)+ + cmp r0,$frend-frlist + bhis www + tst frlist(r0) + bne yyy + br xxx +/ +/ there are no larger blocks; must garbage collect +/ +www: jsr pc,collect + tst r0 + bne zzz +/ +/ out of space +/ + mov $1,r0 + sys write; 1f; 2f-1f + jmp interrupt +1: +2: .even +/ +/ split larger block into two smaller pieces and +/ link together as smaller blocks in the free list. +/ +yyy: + mov hblk,r3 /get free header block + beq www /should never get this + mov frlist(r0),r1 + add $hblk,r1 + mov w(r1),frlist(r0) + mov r3,w(r1) + add $hblk,r3 + mov exp2-2(r0),r2 + add a(r1),r2 + mov w(r3),hblk + mov l(r1),l(r3) + mov r2,l(r1) /L + mov r2,a(r3) + clr w(r3) /W' + mov r1,r2 + sub $hblk,r2 + mov r2,frlist-2(r0) + br zzz +/ +/ +/ here to release a block +/ +/ mov ...,r1 +/ jsr pc,release +/ +/ pointer to block in r1 +/ +release: +/ +/ discover that this is a plausible pointer +/ + mov r0,-(sp) + jsr pc,preposterous +/ +/ find free list index and link block to that entry +/ + inc stats+2 + mov frlist(r0),w(r1) + clr r(r1) + sub $hblk,r1 + mov r1,frlist(r0) + clr r1 /self-defense + mov (sp)+,r0 + rts pc +/ +/ +/ jsr pc,collect +/ +/ coalesce free storage by rejoining paired blocks +/ on the free list. +/ zero is returned in r0 if no paired blocks were found. +/ +collect: + mov r1,-(sp) + mov r2,-(sp) + mov r3,-(sp) + mov r4,-(sp) + clr useful + inc stats+4. + clr r0 /start with smallest blocks + /r0 contains frlist index +loop1: mov $frlist,r1 + add r0,r1 +/ +/ try next list member at this level +/ +loop2: mov (r1),r3 + beq advance /list is empty + add $hblk,r3 + tst (r3) /W + beq advance /only one list element +/ +/ calculate address of buddy +/ + mov a(r3),r4 + sub $hsz,r4 + mov exp2(r0),r2 + xor r2,r4 +1: add $hsz,r4 +/ +/ and search for him +/ +loop3: + cmp a(r3),r4 + beq coal + mov r3,r2 + mov w(r3),r3 + tst r3 + beq nocoal + add $hblk,r3 + br loop3 +/ +/ have found a pair; remove both blocks from list, +/ coalesce them, and put them on next higher list +/ +coal: mov $1,useful + mov w(r3),w(r2) /remove him from list + mov (r1),r2 + add $hblk,r2 + mov r3,r4 + mov w(r2),w(r1) /remove other one + cmp a(r2),a(r4) + bhi 1f + mov r2,-(sp) + mov r4,r2 + mov (sp)+,r4 +1: mov hblk,(r2) + clr r(r2) + mov $hsz,a(r2) + mov $hsz,l(r2) + sub $hblk,r2 + mov r2,hblk + add exp2(r0),l(r4) /L + clr r(r4) + mov frlist+2(r0),w(r4) + sub $hblk,r4 + mov r4,frlist+2(r0) + br loop2 +/ +/ no buddy found, try next block on this list +/ +nocoal: + mov (r1),r1 + add $hblk,r1 + br loop2 +/ +/ advance to next free list +/ +advance: + tst (r0)+ + cmp r0,$frend-frlist + blo loop1 + mov useful,r0 +/ +/ do we have enough headers to continue? +/ + tst garbage + beq 1f + mov $1,r0 + sys write; 4f; 5f-4f + 4 +/ +4: +5: .even +/ +/ +/ restore registers and return +/ +1: + inc garbage + mov (sp)+,r4 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r1 + rts pc +/ +garbage:.=.+2 +/ +/ routine to find integer part of log2(x) +/ +/ jsr pc,log2 +/ +/ r0 = log2(r0) +/ +log2: + mov $15.,-(sp) + tst r0 + bne 1f + clr (sp) + br 2f +1: asl r0 + bcs 2f + dec (sp) + br 1b +2: mov (sp)+,r0 + rts pc +/ + 0 +exp2: + 1;2;4;10;20;40;100;200;400;1000;2000;4000; + 10000;20000;40000;100000 +/ +/ routine to discover whether r1 points to +/ a plausible header - to avoid ruination. +/ +/ r1 is preserved and r0 gets a suitable index for frlist +/ +/ jsr pc,preposterous +/ +preposterous: + cmp r1,$headers + bhis 9f; 4; 9: + cmp r1,$headend + blo 9f; 4; 9: + cmp a(r1),$hsz /A + bhis 9f; 4; 9: + cmp l(r1),$hsz+datasz /L + blos 9f; 4; 9: + mov l(r1),r0 /L + sub a(r1),r0 /A + mov r0,-(sp) + jsr pc,log2 + asl r0 + cmp exp2(r0),(sp) + beq 9f; 4; 9: + add $2,r0 + cmp r0,$frend-frlist+2 + blo 9f; 4; 9: + sub $2,r0 + mov r0,(sp) + mov frlist(r0),r0 +1: beq 1f + add $hblk,r0 + cmp r0,r1 + bne 9f; 4; 9: + mov (r0),r0 + br 1b +1: mov (sp)+,r0 + rts pc +/ +/ +/ +whead: + inc stats+22. + mov r0,-(sp) + mov afout,r0 + sys seek; 0; 0 + sys write; hblk; hsz + mov (sp)+,r0 + rts pc +/ +/ +initl: + clr hblk + mov r0,-(sp) + mov r2,-(sp) + sys open;almem; 1 /open for write + bec 2f + sys creat;almem; 666 + bes err2 + inc hblk +2: + mov r0,afout + sys open; almem; 0 /open for read + bes err2 + mov r0,afi + br 1f +/ +err2: + mov $1,r0 + sys write; 4f; 5f-4f + 4 + .data +4: +5: +almem: + .even + .text +/ +1: + tst hblk + bgt 1f + sys read; hblk; hsz /r0 already afi + mov asmdisc,asmem + add $hblk,asmem + br 2f +1: + mov $headers,r2 + mov r2,r0 + sub $hblk,r0 + mov r0,hblk +1: + add $8,r0 + mov r0,(r2) + add $8,r2 + cmp r2,$headend-8. + blo 1b + clr -8(r2) + mov $frlist,r0 +1: + clr (r0)+ + cmp r0,$frend + blo 1b + + mov hblk,r2 + add $hblk,r2 + mov (r2),hblk + clr w(r2) + mov $hsz,a(r2) + mov $hsz+datasz,l(r2) + mov $datasz,r0 + jsr pc,log2 + asl r0 + cmp r0,$frend-frlist + blo 9f; 4; 9: + sub $hblk,r2 + mov r2,frlist(r0) +/ +/ install plausible pointers to make octal dumps look nice +/ + mov $hblk,r1 +1: + mov (r1),r1 + tst r1 + beq 1f + add $hblk,r1 + mov $hsz,a(r1) + mov $hsz,l(r1) + mov $hsz,r(r1) + br 1b +1: + mov afout,r0 + sys write;hblk;hsz + jsr pc,reset + mov $4,r0 + jsr pc,allocate + mov r1,asmem + mov r1,asmdisc + sub $hblk,asmdisc +2: + mov (sp)+,r2 + mov (sp)+,r0 + rts pc +/ +/ + .bss +/ +b1s: .=.+numb2 +b1e: .=.+numb2 +w1: .=.+numb2 +u1: .=.+numb2 +b1: .=. + [512.*numb] +flag: .=.+2 +stats: .=.+24. /alloc/release/collect/get/put/seek/copy +useful: .=.+2 +afi: .=.+2 +afout: .=.+2 +asmem: .=.+2 +nchar: .=.+2 +/ +/ +hblk: .=.+2 /must remain here - pointer to free header +frlist: .=hblk+34. +frend: +asmdisc:.=.+2 +headers: .=hblk+hsz +headend: + .text diff --git a/source/s1/getty.c b/source/s1/getty.c new file mode 100644 index 0000000..17998a3 --- /dev/null +++ b/source/s1/getty.c @@ -0,0 +1,199 @@ +# +/* + * getty -- adapt to terminal speed on dialup, and call login + */ + +/* + * tty flags + */ +#define HUPCL 01 +#define XTABS 02 +#define LCASE 04 +#define ECHO 010 +#define CRMOD 020 +#define RAW 040 +#define ODDP 0100 +#define EVENP 0200 +#define ANYP 0300 + +/* + * Delay algorithms + */ +#define CR1 010000 +#define CR2 020000 +#define CR3 030000 +#define NL1 000400 +#define NL2 001000 +#define NL3 001400 +#define TAB1 002000 +#define TAB2 004000 +#define TAB3 006000 +#define FF1 040000 + +#define ERASE '#' +#define KILL '@' + +/* + * speeds + */ +#define B110 3 +#define B150 5 +#define B300 7 +#define B9600 13 + +#define SIGINT 2 +#define SIGQIT 3 + +struct sgtty { + char sgispd, sgospd; + char sgerase, sgkill; + int sgflag; +} tmode; + +struct tab { + int tname; /* this table name */ + int nname; /* successor table name */ + int iflags; /* initial flags */ + int fflags; /* final flags */ + int ispeed; /* input speed */ + int ospeed; /* output speed */ + char *message; /* login message */ +} itab[] { + +/* table '0'-1-2 300,150,110 */ + + '0', 1, + ANYP+RAW+NL1+CR1, ANYP+ECHO+CR1, + B300, B300, + "\n\r\033;\007login: ", + + 1, 2, + ANYP+RAW+NL1+CR1, EVENP+ECHO+FF1+CR2+TAB1+NL1, + B150, B150, + "\n\r\033:\006\006\017login: ", + + 2, '0', + ANYP+RAW+NL1+CR1, ANYP+ECHO+CRMOD+XTABS+LCASE+CR1, + B110, B110, + "\n\rlogin: ", + +/* table '-' -- Console TTY 110 */ + '-', '-', + ANYP+RAW+NL1+CR1, ANYP+ECHO+CRMOD+XTABS+LCASE+CR1, + B110, B110, + "\n\rlogin: ", + +/* table '1' -- 150 */ + '1', '1', + ANYP+RAW+NL1+CR1, EVENP+ECHO+FF1+CR2+TAB1+NL1, + B150, B150, + "\n\r\033:\006\006\017login: ", + +/* table '2' -- 9600 */ + '2', '2', + ANYP+RAW+NL1+CR1, ANYP+XTABS+ECHO+CRMOD+FF1, + B9600, B9600, + "\n\r\033;login: ", +}; + +#define NITAB sizeof itab/sizeof itab[0] + +char name[16]; +int crmod; +int upper; +int lower; + +main(argc, argv) +char **argv; +{ + register struct tab *tabp; + register tname; + +/* + signal(SIGINT, 1); + signal(SIGQIT, 0); +*/ + tname = '0'; + if (argc > 1) + tname = *argv[1]; + for (;;) { + for(tabp = itab; tabp < &itab[NITAB]; tabp++) + if(tabp->tname == tname) + break; + if(tabp >= &itab[NITAB]) + tabp = itab; + tmode.sgispd = tabp->ispeed; + tmode.sgospd = tabp->ospeed; + tmode.sgflag = tabp->iflags; + tmode.sgispd = tabp->ispeed; + tmode.sgospd = tabp->ospeed; + stty(0, &tmode); + puts(tabp->message); + stty(0, &tmode); + if(getname()) { + tmode.sgerase = ERASE; + tmode.sgkill = KILL; + tmode.sgflag = tabp->fflags; + if(crmod) + tmode.sgflag =| CRMOD; + if(upper) + tmode.sgflag =| LCASE; + if(lower) + tmode.sgflag =& ~LCASE; + stty(0, &tmode); + execl("/bin/login", "login", name, 0); + exit(1); + } + tname = tabp->nname; + } +} + +getname() +{ + register char *np; + register c; + static cs; + + crmod = 0; + upper = 0; + lower = 0; + np = name; + do { + if (read(0, &cs, 1) <= 0) + exit(0); + if ((c = cs&0177) == 0) + return(0); + write(1, &cs, 1); + if (c>='a' && c <='z') + lower++; + else if (c>='A' && c<='Z') { + upper++; + c =+ 'a'-'A'; + } else if (c==ERASE) { + if (np > name) + np--; + continue; + } else if (c==KILL) { + np = name; + continue; + } + *np++ = c; + } while (c!='\n' && c!='\r' && np <= &name[16]); + *--np = 0; + if (c == '\r') { + write(1, "\n", 1); + crmod++; + } else + write(1, "\r", 1); + return(1); +} + +puts(as) +char *as; +{ + register char *s; + + s = as; + while (*s) + write(1, s++, 1); +} diff --git a/source/s1/glob.c b/source/s1/glob.c new file mode 100644 index 0000000..a4ef186 --- /dev/null +++ b/source/s1/glob.c @@ -0,0 +1,256 @@ +# +/* global command -- + + glob params + + "*" in params matches r.e ".*" + "?" in params matches r.e. "." + "[...]" in params matches character class + "[...a-z...]" in params matches a through z. + + perform command with argument list + constructed as follows: + if param does not contain "*", "[", or "?", use it as is + if it does, find all files in current directory + which match the param, sort them, and use them + + prepend the command name with "/bin" or "/usr/bin" + as required. +*/ + +#define E2BIG 7 +#define ENOEXEC 8 +#define ENOENT 2 + +#define STRSIZ 522 +char ab[STRSIZ]; /* generated characters */ +char *ava[200]; /* generated arguments */ +char **av &ava[1]; +char *string ab; +int errno; +int ncoll; + +main(argc, argv) +char *argv[]; +{ + register char *cp; + + if (argc < 3) { + write(2, "Arg count\n", 10); + return; + } + argv++; + *av++ = *argv; + while (--argc >= 2) + expand(*++argv); + if (ncoll==0) { + write(2, "No match\n", 9); + return; + } + execute(ava[1], &ava[1]); + cp = cat("/usr/bin/", ava[1]); + execute(cp+4, &ava[1]); + execute(cp, &ava[1]); + write(2, "Command not found.\n", 19); +} + +expand(as) +char *as; +{ + register char *s, *cs; + register int dirf; + char **oav; + static struct { + int ino; + char name[16]; + } entry; + + s = cs = as; + while (*cs!='*' && *cs!='?' && *cs!='[') { + if (*cs++ == 0) { + *av++ = cat(s, ""); + return; + } + } + for (;;) { + if (cs==s) { + dirf = open(".", 0); + s = ""; + break; + } + if (*--cs == '/') { + *cs = 0; + dirf = open(s==cs? "/": s, 0); + *cs++ = 0200; + break; + } + } + if (dirf<0) { + write(2, "No directory\n", 13); + exit(); + } + oav = av; + while (read(dirf, &entry, 16) == 16) { + if (entry.ino==0) + continue; + if (match(entry.name, cs)) { + *av++ = cat(s, entry.name); + ncoll++; + } + } + close(dirf); + sort(oav); +} + +sort(oav) +char **oav; +{ + register char **p1, **p2, **c; + + p1 = oav; + while (p1 < av-1) { + p2 = p1; + while(++p2 < av) { + if (compar(*p1, *p2) > 0) { + c = *p1; + *p1 = *p2; + *p2 = c; + } + } + p1++; + } +} + +execute(afile, aarg) +char *afile; +char **aarg; +{ + register char *file, **arg; + + arg = aarg; + file = afile; + execv(file, arg); + if (errno==ENOEXEC) { + arg[0] = file; + *--arg = "/bin/sh"; + execv(*arg, arg); + } + if (errno==E2BIG) + toolong(); +} + +toolong() +{ + write(2, "Arg list too long\n", 18); + exit(); +} + +match(s, p) +char *s, *p; +{ + if (*s=='.' && *p!='.') + return(0); + return(amatch(s, p)); +} + +amatch(as, ap) +char *as, *ap; +{ + register char *s, *p; + register scc; + int c, cc, ok, lc; + + s = as; + p = ap; + if (scc = *s++) + if ((scc =& 0177) == 0) + scc = 0200; + switch (c = *p++) { + + case '[': + ok = 0; + lc = 077777; + while (cc = *p++) { + if (cc==']') { + if (ok) + return(amatch(s, p)); + else + return(0); + } else if (cc=='-') { + if (lc<=scc && scc<=(c = *p++)) + ok++; + } else + if (scc == (lc=cc)) + ok++; + } + return(0); + + default: + if (c!=scc) + return(0); + + case '?': + if (scc) + return(amatch(s, p)); + return(0); + + case '*': + return(umatch(--s, p)); + + case '\0': + return(!scc); + } +} + +umatch(s, p) +char *s, *p; +{ + if(*p==0) + return(1); + while(*s) + if (amatch(s++,p)) + return(1); + return(0); +} + +compar(as1, as2) +char *as1, *as2; +{ + register char *s1, *s2; + + s1 = as1; + s2 = as2; + while (*s1++ == *s2) + if (*s2++ == 0) + return(0); + return (*--s1 - *s2); +} + +cat(as1, as2) +char *as1, *as2; +{ + register char *s1, *s2; + register int c; + + s2 = string; + s1 = as1; + while (c = *s1++) { + if (s2 > &ab[STRSIZ]) + toolong(); + c =& 0177; + if (c==0) { + *s2++ = '/'; + break; + } + *s2++ = c; + } + s1 = as2; + do { + if (s2 > &ab[STRSIZ]) + toolong(); + *s2++ = c = *s1++; + } while (c); + s1 = string; + string = s2; + return(s1); +} diff --git a/source/s1/goto.c b/source/s1/goto.c new file mode 100644 index 0000000..e81d3be --- /dev/null +++ b/source/s1/goto.c @@ -0,0 +1,67 @@ +int offset 0; + +main(argc, argv) +char *argv[]; +{ + extern fin; + char line[64]; + + if (argc<2 || ttyn(0)!='x') { + write(1, "goto error\n", 11); + seek(0, 0, 2); + return; + } + seek(0, 0, 0); + fin = dup(0); + +loop: + if (getlin(line)) { + write(1, "label not found\n", 16); + return; + } + if (compar(line, argv[1])) goto loop; + seek(0, offset, 0); +} + +getlin(s) +char s[]; +{ + int ch, i; + + i = 0; +l: + if ((ch=getc())=='\0') return(1); + if (ch!=':') { + while(ch!='\n' && ch!='\0') + ch = getc(); + goto l; + } + while ((ch=getc())==' '); + while (ch!=' ' && ch!='\n' && ch!='\0') { + s[i++] = ch; + ch = getc(); + } + while(ch != '\n') + ch = getc(); + s[i] = '\0'; + return(0); +} + +compar(s1, s2) +char s1[], s2[]; +{ + int c, i; + + i = 0; +l: + if(s1[i] != s2[i]) return(1); + if (s1[i++] == '\0') return(0); + goto l; +} + +getc() +{ + + offset++; + return(getchar()); +} diff --git a/source/s1/grep.c b/source/s1/grep.c new file mode 100644 index 0000000..26b864d --- /dev/null +++ b/source/s1/grep.c @@ -0,0 +1,342 @@ +# +/* + * grep -- print lines matching (or not matching) a pattern + * + */ + +#define CCHR 2 +#define CDOT 4 +#define CCL 6 +#define NCCL 8 +#define CDOL 10 +#define CEOF 11 + +#define STAR 01 + +#define LBSIZE 256 +#define ESIZE 256 + +char ibuf[512]; +char expbuf[ESIZE]; +int lnum[2]; +char linebuf[LBSIZE+1]; +int bflag; +int nflag; +int cflag; +int vflag; +int nfile; +int circf; +int blkno; +int tln[2]; + +main(argc, argv) +char **argv; +{ + extern fout; + + fout = dup(1); + flush(); + while (--argc > 0 && (++argv)[0][0]=='-') + switch (argv[0][1]) { + + case 'v': + vflag++; + continue; + + case 'b': + bflag++; + continue; + + case 'c': + cflag++; + continue; + + case 'n': + nflag++; + continue; + + default: + printf2("Unknown flag\n"); + continue; + } + if (argc<=0) + exit(2); + compile(*argv); + nfile = --argc; + if (argc<=0) + execute(0); + else while (--argc >= 0) { + argv++; + execute(*argv); + } + flush(); + exit(0); +} + +compile(astr) +char *astr; +{ + register c; + register char *ep, *sp; + char *lastep; + int cclcnt; + + ep = expbuf; + sp = astr; + if (*sp == '^') { + circf++; + sp++; + } + for (;;) { + if (ep >= &expbuf[ESIZE]) + goto cerror; + if ((c = *sp++) != '*') + lastep = ep; + switch (c) { + + case '\0': + *ep++ = CEOF; + return; + + case '.': + *ep++ = CDOT; + continue; + + case '*': + if (lastep==0) + goto defchar; + *lastep =| STAR; + continue; + + case '$': + if (*sp != '\0') + goto defchar; + *ep++ = CDOL; + continue; + + case '[': + *ep++ = CCL; + *ep++ = 0; + cclcnt = 1; + if ((c = *sp++) == '^') { + c = *sp++; + ep[-2] = NCCL; + } + do { + *ep++ = c; + cclcnt++; + if (c=='\0' || ep >= &expbuf[ESIZE]) + goto cerror; + } while ((c = *sp++) != ']'); + lastep[1] = cclcnt; + continue; + + case '\\': + if ((c = *sp++) == '\0') + goto cerror; + defchar: + default: + *ep++ = CCHR; + *ep++ = c; + } + } + cerror: + printf2("RE error\n"); +} + +execute(file) +{ + register char *p1, *p2; + register c; + int f; + char *ebp, *cbp; + + if (file) { + if ((f = open(file, 0)) < 0) { + printf2("Can't open %s\n", file); + } + } else + f = 0; + ebp = ibuf; + cbp = ibuf; + lnum[0] = 0; + lnum[1] = 0; + tln[0] = 0; + tln[1] = 0; + blkno = -1; + for (;;) { + if ((++lnum[1])==0) + lnum[1]++; + if((lnum[1]&0377) == 0) + flush(); + p1 = linebuf; + p2 = cbp; + for (;;) { + if (p2 >= ebp) { + if ((c = read(f, ibuf, 512)) <= 0) { + close(f); + if (cflag) { + if (nfile > 1) + printf("%s:", file); + p1 = locv(tln[0],tln[1]); + printf("%s\n", p1); + } + return; + } + blkno++; + p2 = ibuf; + ebp = ibuf+c; + } + if ((c = *p2++) == '\n') + break; + if(c) + if (p1 < &linebuf[LBSIZE-1]) + *p1++ = c; + } + *p1++ = 0; + cbp = p2; + p1 = linebuf; + p2 = expbuf; + if (circf) { + if (advance(p1, p2)) + goto found; + goto nfound; + } + /* fast check for first character */ + if (*p2==CCHR) { + c = p2[1]; + do { + if (*p1!=c) + continue; + if (advance(p1, p2)) + goto found; + } while (*p1++); + goto nfound; + } + /* regular algorithm */ + do { + if (advance(p1, p2)) + goto found; + } while (*p1++); + nfound: + if (vflag) + succeed(file); + continue; + found: + if (vflag==0) + succeed(file); + } +} + +advance(alp, aep) +{ + register char *lp, *ep, *curlp; + char *nextep; + + lp = alp; + ep = aep; + for (;;) switch (*ep++) { + + case CCHR: + if (*ep++ == *lp++) + continue; + return(0); + + case CDOT: + if (*lp++) + continue; + return(0); + + case CDOL: + if (*lp==0) + continue; + return(0); + + case CEOF: + return(1); + + case CCL: + if (cclass(ep, *lp++, 1)) { + ep =+ *ep; + continue; + } + return(0); + + case NCCL: + if (cclass(ep, *lp++, 0)) { + ep =+ *ep; + continue; + } + return(0); + + case CDOT|STAR: + curlp = lp; + while (*lp++); + goto star; + + case CCHR|STAR: + curlp = lp; + while (*lp++ == *ep); + ep++; + goto star; + + case CCL|STAR: + case NCCL|STAR: + curlp = lp; + while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); + ep =+ *ep; + goto star; + + star: + do { + lp--; + if (advance(lp, ep)) + return(1); + } while (lp > curlp); + return(0); + + default: + printf2("RE botch\n"); + } +} + +cclass(aset, ac, af) +{ + register char *set, c; + register n; + + set = aset; + if ((c = ac) == 0) + return(0); + n = *set++; + while (--n) + if (*set++ == c) + return(af); + return(!af); +} + +printf2(s, a) +{ + extern fout; + flush(); + fout = 2; + printf(s, a); + flush(); + exit(2); +} + +succeed(f) +{ + if (cflag) { + if (++tln[1]==0) + tln[0]++; + return; + } + if (nfile > 1) + printf("%s:", f); + if (bflag) + printf("%l:", blkno); + if (nflag) + printf("%s:", locv(lnum[0], lnum[1])); + printf("%s\n", linebuf); +} diff --git a/source/s1/gsi.c b/source/s1/gsi.c new file mode 100644 index 0000000..e019268 --- /dev/null +++ b/source/s1/gsi.c @@ -0,0 +1,199 @@ +#define PLOT 006 /* ack */ +#define BEL 007 /* exit plot mode */ +#define ESC 033 /* escape */ +#define HFWD '9' +#define HREV '8' +#define FREV '7' +#define SO 016 /* shift out - enter greek */ +#define SI 017 /* shift in */ +#define UP 013 +#define DN 012 +#define RT ' ' +#define LF '\b' + +int restore(); +int svmode, mode[3]; + +main(argc,argv) int argc; char **argv; { + int c, textmode; + extern int fin,fout; + fin = dup(0); + fout = dup(1); + if ((signal(2, 1) & 01) == 0) + signal(2, &restore); + gtty(1, mode); + svmode = mode[2]; + mode[2] =& 0777757; /* turn off cr-lf */ + mode[2] =| 03; /* turn off delays, tabs */ + stty(1, mode); + textmode = 1; + while( (c=getchar()) != '\0' ){ + if( c==SO ){ + special(); + continue; + } + if (c== PLOT) textmode = 1-textmode; + if (c==BEL) textmode = 1; + if( c=='\n' && textmode ) + putchar(015); /* CR */ + if( c!=ESC ){ + putchar(c); + continue; + } + putchar(PLOT); + c = getchar(); + if( c == HREV ) + nplot(4,UP); + else if( c == HFWD ) + nplot(4,DN); + else if( c == FREV ) + nplot(8,UP); + putchar(PLOT); + } + flush(); + restore(); +} + +restore(){ + mode[2] = svmode; + stty(1, mode); + exit(); +} + +int tab[]{ + 'A', /* alpha */ + 'B', /* beta */ + 'D', /* delta */ + 'W', /* DELTA */ + 'S', /* epsilon */ + 'N', /* eta */ + '\\', /* gamma */ + 'G', /* GAMMA */ + 'o', /* infinity - not in M37 */ + '^', /* integral */ + 'L', /* lambda */ + 'E', /* LAMBDA */ + 'M', /* mu */ + '[', /* nabla (del) */ + '_', /* not */ + '@', /* nu */ + 'C', /* omega */ + 'Z', /* OMEGA */ + ']', /* partial */ + 'U', /* phi */ + 'F', /* PHI */ + 'V', /* psi */ + 'H', /* PSI */ + 'J', /* pi */ + 'P', /* PI */ + 'K', /* rho */ + 'Y', /* sigma */ + 'R', /* SIGMA */ + 'I', /* tau */ + 'T', /* theta */ + 'O', /* THETA */ + 'X', /* xi */ + 'Q', /* zeta */ + 0 +}; +int trans[]{ + alpha, + beta, + delta, + DELTA, + epsilon, + eta, + gamma, + GAMMA, + infinity, + integral, + lambda, + LAMBDA, + mu, + nabla, + not, + nu, + omega, + OMEGA, + partial, + phi, + PHI, + psi, + PSI, + pi, + PI, + rho, + sigma, + SIGMA, + tau, + theta, + THETA, + xi, + zeta, + 0 +}; + +int alpha[] {LF,'c',RT,RT,'(',LF,0}; +int beta[] {'B',LF,LF,DN,DN,'|',RT,RT,UP,UP,0}; +int delta[] {'o',UP,UP,'<',DN,DN,0}; +int DELTA[] {LF,LF,'/',-3,DN,'-',-4,RT,'-',-3,UP,'\\',LF,LF,0}; +int epsilon[] {'<','-',0}; +int eta[] {'n',RT,RT,DN,DN,'|',LF,LF,UP,UP,0}; +int gamma[] {')',RT,'/',LF,0}; +int GAMMA[] {LF,LF,'|',RT,RT,-3,UP,'-',-3,DN,RT,RT,'`',LF,LF,0}; +int infinity[] {LF,LF,'c',-4,RT,'o',LF,LF,0}; +int integral[] {'|','\'',RT,RT,'`',-3,LF,-6,DN,'\'',LF,'`',RT,RT,-6,UP,0}; +int lambda[] {'\\',-4,DN,LF,'\'',DN,LF,'\'',-5,UP,RT,RT,0}; +int LAMBDA[] {LF,LF,'/',-4,RT,'\\',LF,LF,0}; +int mu[] {'u',LF,LF,',',RT,RT,0}; +int nabla[] {LF,LF,'\\',-3,UP,'-',-4,RT,'-',-3,DN,'/',LF,LF,0}; +int not[] {'-',-2,RT,UP,',',DN,-2,LF,0}; +int nu[] {LF,'(',-3,RT,'/',LF,LF,0}; +int omega[] {LF,'u',-3,RT,'u',LF,LF,0}; +int OMEGA[] {'O',DN,DN,LF,'-',RT,RT,'-',LF,UP,UP,0}; +int partial[] {'o',RT,DN,'`',LF,UP,'`',LF,UP,'`',RT,DN,0}; +int phi[] {'o','/',0}; +int PHI[] {'o','[',']',0}; +int psi[] {'/','-',DN,DN,RT,RT,'\'',-4,LF,'\'',RT,RT,UP,UP,0}; +int PSI[] {'[',']','-',DN,DN,RT,RT,'\'',-4,LF,'`',RT,RT,UP,UP,0}; +int pi[] {UP,'-',-3,DN,'"',DN,'"',-3,UP,0}; +int PI[] {LF,LF,'[',']',-4,RT,'[',']',LF,LF,-3,UP,'-',-3,DN,0}; +int rho[] {'o',LF,LF,DN,DN,'|',UP,UP,RT,RT,0}; +int sigma[] {'o',DN,RT,RT,'~',UP,LF,LF,0}; +int SIGMA[] {'>',-2,DN,'-',-5,UP,'-',-3,DN,0}; +int tau[] {'t',DN,RT,RT,'~',LF,LF,LF,'~',RT,UP,0}; +int theta[] {'O','-',0}; +int THETA[] {'O','=',0}; +int xi[] {'c',RT,DN,',',LF,-3,UP,'c',LF,DN,'`',RT,DN,0}; +int zeta[] {'c',RT,DN,',',LF,-3,UP,'<',DN,DN,0}; + +special(){ + int c,i,j,t; + loop: + if( (c=getchar()) == SI ) + return; + for( i=0; tab[i]!=0; i++) + if( c==tab[i] ){ + plot(trans[i]); + goto loop; + } + putchar(c); + goto loop; +} + +plot(s) int *s; { + int i,c; + putchar(PLOT); + for( i=0; (c=s[i])!=0; i++ ) + if( c<0 ) + nplot(-c,s[++i]); + else + putchar(c); + putchar(PLOT); + putchar(' '); +} + +nplot(n,c) int n,c; { + while(n--) + putchar(c); +} diff --git a/source/s1/icheck.c b/source/s1/icheck.c new file mode 100644 index 0000000..38f34b2 --- /dev/null +++ b/source/s1/icheck.c @@ -0,0 +1,321 @@ +# + +char *dargv[] +{ + "/dev/rrk2", + "/dev/rrp0", + 0 +}; +#define NINODE 16*16 +#define NB 10 +#include "/usr/sys/ino.h" +#include "/usr/sys/filsys.h" + +struct inode inode[NINODE]; +struct filsys sblock; + +int sflg; + +int fi; +int nifiles; +int nfile; +int nspcl; +int nlarg; +int nvlarg; +int nindir; +int nvindir; +int ndir; +int nused; +int nfree; +int ino; +int ndup; +int blist[10] { -1}; +int nerror; +int bmap[4096]; + +main(argc, argv) +char **argv; +{ + register char **p; + register int n, *lp; + + if (argc == 1) { + for (p = dargv; *p;) + check(*p++); + return(nerror); + } + while (--argc) { + argv++; + if (**argv=='-') switch ((*argv)[1]) { + case 's': + sflg++; + continue; + + case 'b': + lp = blist; + while (lp < &blist[NB-1] && (n = number(argv[1]))) { + *lp++ = n; + argv++; + argc--; + } + *lp++ = -1; + continue; + + default: + printf("Bad flag\n"); + } + check(*argv); + } + return(nerror); +} + +check(file) +char *file; +{ + register *ip, i, j; + + fi = open(file, sflg?2:0); + if (fi < 0) { + printf("cannot open %s\n", file); + nerror =| 04; + return; + } + printf("%s:\n", file); + nfile = 0; + nspcl = 0; + nlarg = 0; + nvlarg = 0; + nindir = 0; + nvindir = 0; + ndir = 0; + nused = 0; + nfree = 0; + ndup = 0; + for (ip = bmap; ip < &bmap[4096];) + *ip++ = 0; + sync(); + bread(1, &sblock, 512); + nifiles = sblock.s_isize*16; + for(i=0; ino < nifiles; i =+ NINODE/16) { + bread(i+2, inode, sizeof inode); + for(j=0; ji_mode&IALLOC) == 0) + return; + if ((ip->i_mode&IFCHR&IFBLK) != 0) { + nspcl++; + return; + } + if ((ip->i_mode&IFMT) == IFDIR) + ndir++; + else + nfile++; + if ((ip->i_mode&ILARG) != 0) { + nlarg++; + for(i=0; i<7; i++) + if (ip->i_addr[i] != 0) { + nindir++; + if (chk(ip->i_addr[i], "indirect")) + continue; + bread(ip->i_addr[i], buf, 512); + for(j=0; j<256; j++) + if (buf[j] != 0) + chk(buf[j], "data (large)"); + } + if (ip->i_addr[7]) { + nvlarg++; + if (chk(ip->i_addr[7], "indirect")) + return; + bread(ip->i_addr[7], buf, 512); + for(i=0; i<256; i++) + if (buf[i] != 0) { + nvindir++; + if (chk(buf[i], "2nd indirect")) + continue; + bread(buf[i], vbuf, 512); + for(j=0; j<256; j++) + if (vbuf[j]) + chk(vbuf[j], "data (very large)"); + } + } + return; + } + for(i=0; i<8; i++) { + if (ip->i_addr[i] != 0) + chk(ip->i_addr[i], "data (small)"); + } +} + +chk(ab, s) +char *ab; +{ + register char *b; + register n, m; + + b = ab; + if (ino) + nused++; + if (b=sblock.s_fsize) { + printf("%l bad; inode=%l, class=%s\n", b, ino, s); + return(1); + } + m = 1 << (b&017); + n = (b>>4) & 07777; + if (bmap[n]&m) { + printf("%l dup; inode=%l, class=%s\n", b, ino, s); + ndup++; + } + bmap[n] =| m; + for (n=0; blist[n] != -1; n++) + if (b == blist[n]) + printf("%l arg; inode=%l, class=%s\n", b, ino, s); + return(0); +} + +alloc() +{ + register b, i; + int buf[256]; + + i = --sblock.s_nfree; + if (i<0 || i>=100) { + printf("bad freeblock\n"); + return(0); + } + b = sblock.s_free[i]; + if (b == 0) + return(0); + if (sblock.s_nfree <= 0) { + bread(b, buf, 512); + sblock.s_nfree = buf[0]; + for(i=0; i<100; i++) + sblock.s_free[i] = buf[i+1]; + } + return(b); +} + +bread(bno, buf, cnt) +int *buf; +{ + register *ip; + + seek(fi, bno, 3); + if (read(fi, buf, cnt) != cnt) { + printf("read error %d\n", bno); + if (sflg) { + printf("No update\n"); + sflg = 0; + } + for (ip = buf; ip < &buf[256];) + *ip++ = 0; + } +} + +free(in) +{ + register i; + int buf[256]; + + if (sblock.s_nfree >= 100) { + buf[0] = sblock.s_nfree; + for(i=0; i<100; i++) + buf[i+1] = sblock.s_free[i]; + sblock.s_nfree = 0; + bwrite(in, buf); + } + sblock.s_free[sblock.s_nfree++] = in; +} + +bwrite(bno, buf) +{ + + seek(fi, bno, 3); + if (write(fi, buf, 512) != 512) + printf("write error %d\n", bno); +} + +number(as) +char *as; +{ + register n, c; + register char *s; + + s = as; + n = 0; + while ((c = *s++) >= '0' && c <= '9') { + n = n*10+c-'0'; + } + return(n); +} + +makefree() +{ + register i; + + sblock.s_nfree = 0; + sblock.s_ninode = 0; + sblock.s_flock = 0; + sblock.s_ilock = 0; + sblock.s_fmod = 0; + free(0); + for(i=sblock.s_fsize-1; i>=sblock.s_isize+2; i--) { + if ((bmap[(i>>4)&07777] & (1<<(i&017)))==0) + free(i); + } + bwrite(1, &sblock); + close(fi); + sync(); + return; +} diff --git a/source/s1/if.c b/source/s1/if.c new file mode 100644 index 0000000..220dd97 --- /dev/null +++ b/source/s1/if.c @@ -0,0 +1,146 @@ +/* if command */ + +int ap; +int ac; +char **av; + +main(argc, argv) +char *argv[]; +{ + + argv[argc] = 0; + ac = argc; av = argv; ap = 1; + if (argc<2) return; + if (exp()) + if(doex(0)) { + write(1, "no command\n", 11); + seek(0, 0, 2); + } +} + +char *nxtarg() { + + if (ap>ac) return(0*ap++); + return(av[ap++]); +} + +exp(s) { + int p1; + + p1 = e1(); + if (eq(nxtarg(), "-o")) return(p1 | exp()); + ap--; + return(p1); +} + +e1() { + int p1; + + p1 = e2(); + if (eq(nxtarg(), "-a")) return (p1 & e1()); + ap--; + return(p1); +} + +e2() { + if (eq(nxtarg(), "!")) + return(!e3()); + ap--; + return(e3()); +} + +e3() { + int p1, ccode; + register char *a; + + ccode = 0; + if ((a=nxtarg())==0) goto err; + if(eq(a, "(")) { + p1 = exp(); + if(!eq(nxtarg(), ")")) goto err; + return(p1); + } + + if(eq(a, "-r")) + return(tio(nxtarg(), 0)); + + if(eq(a, "-w")) + return(tio(nxtarg(), 1)); + + if(eq(a, "-c")) + return(tcreat(nxtarg())); + + if(eq(a, "{")) { /* execute a command for exit code */ + if(fork()) /*parent*/ wait(&ccode); + else { /*child*/ + doex(1); + goto err; + } + while((a=nxtarg()) && (!eq(a,"}"))); + return(ccode? 0 : 1); + } + + p1 = nxtarg(); + if (p1==0) goto err; + if(eq(p1, "=")) + return(eq(a, nxtarg())); + + if(eq(p1, "!=")) + return(!eq(a, nxtarg())); +err: + write(1, "if error\n", 9); + exit(9); +} + +tio(a, f) { + + a = open(a, f); + if (a>=0) { + close(a); + return(1); + } + return(0); +} + +tcreat(a) { + return(1); +} + +eq(a, b) +char *a, *b; +{ + register int i; + + i = 0; +l: + if(a[i] != b[i]) + return(0); + if(a[i++] == '\0') + return(1); + goto l; +} + +doex(earg) { + + register int np, i, c; + char *nargv[50], *ncom, *na; + + np = 0; + while (na=nxtarg()) { + if(earg && eq(na,"}")) break; + nargv[np++] = na; + } + if(earg && (!eq(na, "}"))) return(9); + nargv[np] = 0; + if (np==0) return(earg); + execv(nargv[0], nargv, np); + i = 0; + ncom = "/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + while(c=nargv[0][i]) { + ncom[9+i++] = c; + } + ncom[9+i] = '\0'; + execv(ncom+4, nargv, np); + execv(ncom, nargv, np); + return(1); +} diff --git a/source/s1/init.c b/source/s1/init.c new file mode 100644 index 0000000..c92da43 --- /dev/null +++ b/source/s1/init.c @@ -0,0 +1,219 @@ +#define tabsize 20 +#define all p = &itab[0]; p < &itab[20]; p++ +#define ever ;; +#define single 0173030 +#define reboot 0173040 +char shell[] "/bin/sh"; +char minus[] "-"; +char runc[] "/etc/rc"; +char init[] "/etc/init"; +char ifile[] "/etc/ttys"; +char utmp[] "/etc/utmp"; +char wtmpf[] "/usr/adm/wtmp"; +char ctty[] "/dev/tty8"; +int fi; +struct +{ + int flag; + int line; + char coms[2]; +} line; +struct tab +{ + int pid; + int line; + int comn; +} itab[tabsize]; + +struct { + char name[8]; + char tty; + char fill; + int time[2]; + int wfill; +} wtmp; + +main() +{ + register i; + register struct tab *p, *q; + int reset(); + + /* + * if not single user, + * run shell sequence + */ + + if(getcsw() != single) { + i = fork(); + if(i == 0) { + open("/", 0); + dup(0); + dup(0); + execl(shell, shell, runc, 0); + exit(); + } + while(wait() != i); + close(creat(utmp, 0644)); + if ((i = open(wtmpf, 1)) >= 0) { + seek(i, 0, 2); + wtmp.tty = '~'; + time(wtmp.time); + write(i, &wtmp, 16); + close(i); + } + } + + /* + * main loop for hangup signal + * close all files and + * check switches for magic values + */ + + setexit(); + signal(1, reset); + for(i=0; i<10; i++) + close(i); + switch(getcsw()) { + + case single: + error: + termall(); + i = fork(); + if(i == 0) { + open(ctty, 2); + dup(0); + execl(shell, minus, 0); + exit(); + } + while(wait() != i); + + case reboot: + termall(); + execl(init, minus, 0); + reset(); + } + + /* + * open and merge in init file + */ + + fi = open(ifile, 0); + q = &itab[0]; + while(rline()) { + if(line.flag == '0') + continue; + for(all) + if(p->line==line.line || p->line==0) { + if(p >= q) { + i = p->pid; + p->pid = q->pid; + q->pid = i; + p->line = q->line; + p->comn = q->comn; + q->line = line.line; + q->coms[0] = line.comn; + q++; + } + break; + } + } + close(fi); + if(q == &itab[0]) + goto error; + for(; q < &itab[tabsize]; q++) + term(q); + for(all) + if(p->line != 0 && p->pid == 0) + dfork(p); + for(ever) { + i = wait(); + for(all) + if(p->pid == i) { + rmut(p); + dfork(p); + } + } +} + +termall() +{ + register struct tab *p; + + for(all) + term(p); +} + +term(ap) +struct tab *ap; +{ + register struct tab *p; + + p = ap; + if(p->pid != 0) { + rmut(p); + kill(p->pid, 9); + } + p->pid = 0; + p->line = 0; +} + +rline() +{ + static char c[4]; + + if(read(fi, c, 4) != 4 || c[3] != '\n') + return(0); + line.flag = c[0]; + line.line = c[1]; + line.comn = c[2]; + return(1); +} + +dfork(ap) +struct tab *ap; +{ + register i; + register char *tty; + register struct tab *p; + + p = ap; + i = fork(); + if(i == 0) { + signal(1, 0); + tty = "/dev/ttyx"; + tty[8] = p->line; + chown(tty, 0); + chmod(tty, 0622); + open(tty, 2); + dup(0); + execl("etc/getty", minus, p->coms, 0); + exit(); + } + p->pid = i; +} + +rmut(p) +struct tab *p; +{ + register i, f; + static char zero[16]; + + f = open(utmp, 1); + if(f >= 0) { + i = p->line; + if(i >= 'a') + i =+ '0' + 10 - 'a'; + seek(f, (i-'0')*16, 0); + write(f, zero, 16); + close(f); + } + f = open(wtmpf, 1); + if (f >= 0) { + wtmp.tty = p->line; + time(wtmp.time); + seek(f, 0, 2); + write(f, &wtmp, 16); + close(f); + } +} diff --git a/source/s1/kill.s b/source/s1/kill.s new file mode 100644 index 0000000..74bcaba --- /dev/null +++ b/source/s1/kill.s @@ -0,0 +1,74 @@ +/ kill process + + mov (sp)+,r4 + tst (sp)+ + +loop: + dec r4 + ble done + mov (sp)+,r5 + clr r3 + cmpb (r5),$'- + bne 1f + inc r5 + clr signo +1: + movb (r5)+,r0 + beq 1f + sub $'0,r0 + cmp r0,$9 + bhi error + mul $10.,r3 + add r0,r3 + br 1b +1: + tst signo + bne 1f + tst r3 + ble error + cmp r3,$12. + bgt error + mov r3,signo + br loop +1: + mov r3,r0 + sys 37.; signo: 9. / kill + bec loop + mov r3,r0 + jsr pc,decml + mov $1,r0 + sys write; m1; em1-m1 + br loop + +error: + mov $1,r0 + sys write; m2; em2-m2 + br loop + +done: + sys exit + +decml: + mov r0,r1 + clr r0 + div $10.,r0 + mov r1,-(sp) + tst r0 + beq 1f + jsr pc,decml +1: + mov (sp)+,r0 + add $'0,r0 + mov r0,ch + mov $1,r0 + sys write; ch; 1 + rts pc + +m1: + <: not found\n> +em1: +m2: + +em2: +.bss +ch: .=.+2 diff --git a/source/s1/ld.c b/source/s1/ld.c new file mode 100644 index 0000000..b1e5415 --- /dev/null +++ b/source/s1/ld.c @@ -0,0 +1,921 @@ +# +/* + * link editor + */ + +#define SIGINT 2 +#define ARCMAGIC 0177555 +#define FMAGIC 0407 +#define NMAGIC 0410 +#define IMAGIC 0411 + +#define EXTERN 040 +#define UNDEF 00 +#define ABS 01 +#define TEXT 02 +#define DATA 03 +#define BSS 04 +#define COMM 05 /* internal use only */ + +#define RABS 00 +#define RTEXT 02 +#define RDATA 04 +#define RBSS 06 +#define REXT 010 + +#define RELFLG 01 +#define NROUT 256 +#define NSYM 501 +#define NSYMPR 500 + +#define RONLY 0400 + +char premeof[] "Premature EOF on %s"; + +struct page { + int nuser; + int bno; + int nibuf; + int buff[256]; +} page[2]; + +struct { + int nuser; + int bno; +} fpage; + +struct stream { + int *ptr; + int bno; + int nibuf; + int size; + struct page *pno; +}; + +struct stream text; +struct stream reloc; + +struct archdr { + char aname[8]; + int atime[2]; + char auid, amode; + int asize; +} archdr; + +struct filhdr { + int fmagic; + int tsize; + int dsize; + int bsize; + int ssize; + int entry; + int pad; + int relflg; +} filhdr; + +struct liblist { + int off; + int bno; +}; + +struct liblist liblist[NROUT]; +struct liblist *libp { &liblist[0] }; + +struct symbol { + char sname[8]; + char stype; + char spad; + int svalue; +}; + +struct symbol cursym; +struct symbol symtab[NSYM]; +struct symbol *hshtab[NSYM+2]; +struct symbol *symp { symtab }; +struct symbol **local[NSYMPR]; +struct symbol *p_etext; +struct symbol *p_edata; +struct symbol *p_end; + +int xflag; /* discard local symbols */ +int Xflag; /* discard locals starting with 'L' */ +int rflag; /* preserve relocation bits, don't define common */ +int arflag; /* original copy of rflag */ +int sflag; /* discard all symbols */ +int nflag; /* pure procedure */ +int dflag; /* define common even with rflag */ +int iflag; /* I/D space separated */ + +int infil; +char *filname; + +int tsize; +int dsize; +int bsize; +int ssize; +int nsym; + +int torigin; +int dorigin; +int borigin; + +int ctrel; +int cdrel; +int cbrel; + +int errlev; +int delarg 4; +char tfname[] "/tmp/lxyyyyy"; +int toutb[259]; +int doutb[259]; +int troutb[259]; +int droutb[259]; +int soutb[259]; + +struct symbol **lookup(); +struct symbol **slookup(); + +main(argc, argv) +char **argv; +{ + extern int delexit(); + register c; + register char *ap, **p; + struct symbol **hp; + + if ((signal(SIGINT, 1) & 01) == 0) + signal(SIGINT, delexit); + if (argc == 1) + exit(4); + p = argv + 1; + for (c = 1; c= argc) + error(1, "Bad 'use'"); + if (*(hp = slookup(*p++)) == 0) { + *hp = symp; + enter(); + } + continue; + + case 'l': + break; + + case 'x': + xflag++; + continue; + + case 'X': + Xflag++; + continue; + + case 'r': + rflag++; + arflag++; + continue; + + case 's': + sflag++; + xflag++; + continue; + + case 'n': + nflag++; + continue; + + case 'd': + dflag++; + continue; + + case 'i': + iflag++; + continue; + } + load1arg(ap); + close(infil); + } + middle(); + setupout(); + p = argv+1; + libp = liblist; + for (c=1; cbno = -1; + libp++; + return; + } + mget(&archdr, sizeof archdr); + if (load1(1, nbno, noff + (sizeof archdr) / 2)) { + libp->bno = nbno; + libp->off = noff; + libp++; + } + noff =+ (archdr.asize + sizeof archdr)>>1; + nbno =+ (noff >> 8) & 0377; + noff =& 0377; + } +} + +load1(libflg, bno, off) +{ + register struct symbol *sp, **hp, ***cp; + struct symbol *ssymp; + int ndef, nloc; + + readhdr(bno, off); + ctrel = tsize; + cdrel =+ dsize; + cbrel =+ bsize; + ndef = 0; + nloc = sizeof cursym; + cp = local; + ssymp = symp; + if ((filhdr.relflg&RELFLG)==1) { + error(0, "No relocation bits"); + return(0); + } + off =+ (sizeof filhdr)/2 + filhdr.tsize + filhdr.dsize; + dseek(&text, bno, off, filhdr.ssize); + while (text.size > 0) { + mget(&cursym, sizeof cursym); + if ((cursym.stype&EXTERN)==0) { + if (Xflag==0 || cursym.sname[0]!='L') + nloc =+ sizeof cursym; + continue; + } + symreloc(); + hp = lookup(); + if ((sp = *hp) == 0) { + *hp = enter(); + *cp++ = hp; + continue; + } + if (sp->stype != EXTERN+UNDEF) + continue; + if (cursym.stype == EXTERN+UNDEF) { + if (cursym.svalue > sp->svalue) + sp->svalue = cursym.svalue; + continue; + } + if (sp->svalue != 0 && cursym.stype == EXTERN+TEXT) + continue; + ndef++; + sp->stype = cursym.stype; + sp->svalue = cursym.svalue; + } + if (libflg==0 || ndef) { + tsize =+ filhdr.tsize; + dsize =+ filhdr.dsize; + bsize =+ filhdr.bsize; + ssize =+ nloc; + return(1); + } +/* + * No symbols defined by this library member. + * Rip out the hash table entries and reset the symbol table. + */ + symp = ssymp; + while (cp > local) + **--cp = 0; + return(0); +} + +middle() +{ + register struct symbol *sp; + register t, csize; + int nund, corigin; + + p_etext = *slookup("_etext"); + p_edata = *slookup("_edata"); + p_end = *slookup("_end"); +/* + * If there are any undefined symbols, save the relocation bits. + */ + if (rflag==0) for (sp=symtab; spstype==EXTERN+UNDEF && sp->svalue==0 + && sp!=p_end && sp!=p_edata && sp!=p_etext) { + rflag++; + dflag = 0; + nflag = 0; + iflag = 0; + sflag = 0; + break; + } +/* + * Assign common locations. + */ + csize = 0; + if (dflag || rflag==0) { + for (sp=symtab; spstype==EXTERN+UNDEF && (t=sp->svalue)!=0) { + t = (t+1) & ~01; + sp->svalue = csize; + sp->stype = EXTERN+COMM; + csize =+ t; + } + if (p_etext && p_etext->stype==EXTERN+UNDEF) { + p_etext->stype = EXTERN+TEXT; + p_etext->svalue = tsize; + } + if (p_edata && p_edata->stype==EXTERN+UNDEF) { + p_edata->stype = EXTERN+DATA; + p_edata->svalue = dsize; + } + if (p_end && p_end->stype==EXTERN+UNDEF) { + p_end->stype = EXTERN+BSS; + p_end->svalue = bsize; + } + } +/* + * Now set symbols to their final value + */ + if (nflag || iflag) + tsize = (tsize + 077) & ~077; + dorigin = tsize; + if (nflag) + dorigin = (tsize+017777) & ~017777; + if (iflag) + dorigin = 0; + corigin = dorigin + dsize; + borigin = corigin + csize; + nund = 0; + for (sp=symtab; spstype) { + case EXTERN+UNDEF: + errlev =| 01; + if (arflag==0 && sp->svalue==0) { + if (nund==0) + printf("Undefined:\n"); + nund++; + printf("%.8s\n", sp->sname); + } + continue; + + case EXTERN+ABS: + default: + continue; + + case EXTERN+TEXT: + sp->svalue =+ torigin; + continue; + + case EXTERN+DATA: + sp->svalue =+ dorigin; + continue; + + case EXTERN+BSS: + sp->svalue =+ borigin; + continue; + + case EXTERN+COMM: + sp->stype = EXTERN+BSS; + sp->svalue =+ corigin; + continue; + } + if (sflag || xflag) + ssize = 0; + bsize =+ csize; + nsym = ssize / (sizeof cursym); +} + +setupout() +{ + register char *p; + register pid; + + if ((toutb[0] = creat("l.out", 0666)) < 0) + error(1, "Can't create l.out"); + pid = getpid(); + for (p = &tfname[12]; p > &tfname[7];) { + *--p = (pid&07) + '0'; + pid =>> 3; + } + tcreat(doutb, 'a'); + if (sflag==0 || xflag==0) + tcreat(soutb, 'b'); + if (rflag) { + tcreat(troutb, 'c'); + tcreat(droutb, 'd'); + } + filhdr.fmagic = FMAGIC; + if (nflag) + filhdr.fmagic = NMAGIC; + if (iflag) + filhdr.fmagic = IMAGIC; + filhdr.tsize = tsize; + filhdr.dsize = dsize; + filhdr.bsize = bsize; + filhdr.ssize = sflag? 0: (ssize + (sizeof cursym)*(symp-symtab)); + filhdr.entry = 0; + filhdr.pad = 0; + filhdr.relflg = (rflag==0); + mput(toutb, &filhdr, sizeof filhdr); + return; +} + +tcreat(buf, letter) +int *buf; +{ + tfname[6] = letter; + if ((buf[0] = creat(tfname, RONLY)) < 0) + error(1, "Can't create temp"); +} + +load2arg(acp) +char *acp; +{ + register char *cp; + register struct liblist *lp; + + cp = acp; + if (getfile(cp) == 0) { + while (*cp) + cp++; + while (cp >= acp && *--cp != '/'); + mkfsym(++cp); + load2(0, 0); + return; + } + for (lp = libp; lp->bno != -1; lp++) { + dseek(&text, lp->bno, lp->off, sizeof archdr); + mget(&archdr, sizeof archdr); + mkfsym(archdr.aname); + load2(lp->bno, lp->off + (sizeof archdr) / 2); + } + libp = ++lp; +} + +load2(bno, off) +{ + register struct symbol *sp; + register int *lp, symno; + + readhdr(bno, off); + ctrel = torigin; + cdrel =+ dorigin; + cbrel =+ borigin; +/* + * Reread the symbol table, recording the numbering + * of symbols for fixing external references. + */ + lp = local; + symno = -1; + off =+ (sizeof filhdr)/2; + dseek(&text, bno, off+filhdr.tsize+filhdr.dsize, filhdr.ssize); + while (text.size > 0) { + symno++; + mget(&cursym, sizeof cursym); + symreloc(); + if ((cursym.stype&EXTERN) == 0) { + if (!sflag&&!xflag&&(!Xflag||cursym.sname[0]!='L')) + mput(soutb, &cursym, sizeof cursym); + continue; + } + if ((sp = *lookup()) == 0) + error(1, "internal error: symbol not found"); + if (cursym.stype == EXTERN+UNDEF) { + if (lp >= &local[NSYMPR]) + error(1, "Local symbol overflow"); + *lp++ = symno; + *lp++ = sp; + continue; + } + if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) { + printf("%.8s: ", cursym.sname); + error(0, "Multiply defined"); + } + } + dseek(&text, bno, off, filhdr.tsize); + dseek(&reloc, bno, off+(filhdr.tsize+filhdr.dsize)/2, filhdr.tsize); + load2td(lp, ctrel, toutb, troutb); + dseek(&text, bno, off+(filhdr.tsize/2), filhdr.dsize); + dseek(&reloc, bno, off+filhdr.tsize+(filhdr.dsize/2), filhdr.dsize); + load2td(lp, cdrel, doutb, droutb); + torigin =+ filhdr.tsize; + dorigin =+ filhdr.dsize; + borigin =+ filhdr.bsize; +} + +load2td(lp, creloc, b1, b2) +int *lp; +{ + register r, t; + register struct symbol *sp; + + for (;;) { + /* + * The pickup code is copied from "get" for speed. + */ + if (--text.size <= 0) { + if (text.size < 0) + break; + text.size++; + t = get(&text); + } else if (--text.nibuf < 0) { + text.nibuf++; + text.size++; + t = get(&text); + } else + t = *text.ptr++; + if (--reloc.size <= 0) { + if (reloc.size < 0) + error(1, "Relocation error"); + reloc.size++; + r = get(&reloc); + } else if (--reloc.nibuf < 0) { + reloc.nibuf++; + reloc.size++; + r = get(&reloc); + } else + r = *reloc.ptr++; + switch (r&016) { + + case RTEXT: + t =+ ctrel; + break; + + case RDATA: + t =+ cdrel; + break; + + case RBSS: + t =+ cbrel; + break; + + case REXT: + sp = lookloc(lp, r); + if (sp->stype==EXTERN+UNDEF) { + r = (r&01) + ((nsym+(sp-symtab))<<4) + REXT; + break; + } + t =+ sp->svalue; + r = (r&01) + ((sp->stype-(EXTERN+ABS))<<1); + break; + } + if (r&01) + t =- creloc; + putw(t, b1); + if (rflag) + putw(r, b2); + } +} + +finishout() +{ + register n, *p; + + if (nflag||iflag) { + n = torigin; + while (n&077) { + n =+ 2; + putw(0, toutb); + if (rflag) + putw(0, troutb); + } + } + copy(doutb, 'a'); + if (rflag) { + copy(troutb, 'c'); + copy(droutb, 'd'); + } + if (sflag==0) { + if (xflag==0) + copy(soutb, 'b'); + for (p=symtab; p < symp;) + putw(*p++, toutb); + } + fflush(toutb); + close(toutb[0]); + unlink("a.out"); + link("l.out", "a.out"); + delarg = errlev; + delexit(); +} + +delexit() +{ + register c; + + unlink("l.out"); + for (c = 'a'; c <= 'd'; c++) { + tfname[6] = c; + unlink(tfname); + } + if (delarg==0) + chmod("a.out", 0777); + exit(delarg); +} + +copy(buf, c) +int *buf; +{ + register f, *p, n; + + fflush(buf); + close(buf[0]); + tfname[6] = c; + f = open(tfname, 0); + while ((n = read(f, doutb, 512)) > 1) { + n =>> 1; + p = doutb; + do + putw(*p++, toutb); + while (--n); + } + close(f); +} + +mkfsym(s) +char *s; +{ + + if (sflag || xflag) + return; + cp8c(s, cursym.sname); + cursym.stype = 037; + cursym.svalue = torigin; + mput(soutb, &cursym, sizeof cursym); +} + +mget(aloc, an) +int *aloc; +{ + register *loc, n; + register *p; + + n = an; + n =>> 1; + loc = aloc; + if ((text.nibuf =- n) >= 0) { + if ((text.size =- n) > 0) { + p = text.ptr; + do + *loc++ = *p++; + while (--n); + text.ptr = p; + return; + } else + text.size =+ n; + } + text.nibuf =+ n; + do { + *loc++ = get(&text); + } while (--n); +} + +mput(buf, aloc, an) +int *aloc; +{ + register *loc; + register n; + + loc = aloc; + n = an>>1; + do { + putw(*loc++, buf); + } while (--n); +} + +dseek(asp, ab, o, s) +{ + register struct stream *sp; + register struct page *p; + register b; + int n; + + sp = asp; + b = ab + ((o>>8) & 0377); + o =& 0377; + --sp->pno->nuser; + if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b) + if (p->nuser==0 || (p = &page[0])->nuser==0) { + if (page[0].nuser==0 && page[1].nuser==0) + if (page[0].bno < page[1].bno) + p = &page[0]; + p->bno = b; + seek(infil, b, 3); + if ((n = read(infil, p->buff, 512)>>1) < 0) + n = 0; + p->nibuf = n; + } else + error(1, "No pages"); + ++p->nuser; + sp->bno = b; + sp->pno = p; + sp->ptr = p->buff + o; + if (s != -1) + sp->size = (s>>1) & 077777; + if ((sp->nibuf = p->nibuf-o) <= 0) + sp->size = 0; +} + +get(asp) +struct stream *asp; +{ + register struct stream *sp; + + sp = asp; + if (--sp->nibuf < 0) { + dseek(sp, sp->bno+1, 0, -1); + --sp->nibuf; + } + if (--sp->size <= 0) { + if (sp->size < 0) + error(1, premeof); + ++fpage.nuser; + --sp->pno->nuser; + sp->pno = &fpage; + } + return(*sp->ptr++); +} + +getfile(acp) +char *acp; +{ + register char *cp; + register c; + + cp = acp; + archdr.aname[0] = '\0'; + if (cp[0]=='-' && cp[1]=='l') { + if ((c = cp[2]) == '\0') + c = 'a'; + cp = "/lib/lib?.a"; + cp[8] = c; + } + filname = cp; + if ((infil = open(cp, 0)) < 0) + error(1, "cannot open"); + page[0].bno = page[1].bno = -1; + page[0].nuser = page[1].nuser = 0; + text.pno = reloc.pno = &fpage; + fpage.nuser = 2; + dseek(&text, 0, 0, 2); + if (text.size <= 0) + error(1, premeof); + return(get(&text) == ARCMAGIC); +} + +struct symbol **lookup() +{ + int i; + register struct symbol **hp; + register char *cp, *cp1; + + i = 0; + for (cp=cursym.sname; cp < &cursym.sname[8];) + i = (i<<1) + *cp++; + for (hp = &hshtab[(i&077777)%NSYM+2]; *hp!=0;) { + cp1 = (*hp)->sname; + for (cp=cursym.sname; cp < &cursym.sname[8];) + if (*cp++ != *cp1++) + goto no; + break; + no: + if (++hp >= &hshtab[NSYM+2]) + hp = hshtab; + } + return(hp); +} + +struct symbol **slookup(s) +char *s; +{ + cp8c(s, cursym.sname); + cursym.stype = EXTERN+UNDEF; + cursym.svalue = 0; + return(lookup()); +} + +enter() +{ + register struct symbol *sp; + + if ((sp=symp) >= &symtab[NSYM]) + error(1, "Symbol table overflow"); + cp8c(cursym.sname, sp->sname); + sp->stype = cursym.stype; + sp->svalue = cursym.svalue; + symp++; + return(sp); +} + +symreloc() +{ + switch (cursym.stype) { + + case TEXT: + case EXTERN+TEXT: + cursym.svalue =+ ctrel; + return; + + case DATA: + case EXTERN+DATA: + cursym.svalue =+ cdrel; + return; + + case BSS: + case EXTERN+BSS: + cursym.svalue =+ cbrel; + return; + + case EXTERN+UNDEF: + return; + } + if (cursym.stype&EXTERN) + cursym.stype = EXTERN+ABS; +} + +error(n, s) +char *s; +{ + if (filname) { + printf("%s", filname); + if (archdr.aname[0]) + printf("(%.8s)", archdr.aname); + printf(": "); + } + printf("%s\n", s); + if (n) + delexit(); + errlev = 2; +} + +lookloc(alp, r) +{ + register int *clp, *lp; + register sn; + + lp = alp; + sn = (r>>4) & 07777; + for (clp=local; clpargv[1]); + np++; + argv[2] = np; + } + stat(argv[1], &statb); + if ((statb.iflags&FMT) == DIR) { + write(1, "No directory link\n", 18); + exit(1); + } + if (link(argv[1], argv[2])<0) { + write(1, "Can't link\n", 11); + exit(1); + } + exit(0); +} diff --git a/source/s1/login.c b/source/s1/login.c new file mode 100644 index 0000000..0efaaf5 --- /dev/null +++ b/source/s1/login.c @@ -0,0 +1,190 @@ +# +/* + * login [ name ] + */ + +struct { + char name[8]; + char tty; + char ifill; + int time[2]; + int ufill; +} utmp; + +struct { + int speeds; + char erase, kill; + int tflags; +} ttyb; + +struct { + int junk[5]; + int size; + int more[12]; +} statb; + +char *ttyx; + +#define ECHO 010 + +main(argc, argv) +char **argv; +{ + char pbuf[128]; + register char *namep, *np; + char pwbuf[9]; + int t, sflags, f, c, uid, gid; + + signal(3, 1); + signal(2, 1); + nice(0); + ttyx = "/dev/ttyx"; + if ((utmp.tty=ttyn(0)) == 'x') { + write(1, "Sorry.\n", 7); + exit(); + } + ttyx[8] = utmp.tty; + gtty(0, &ttyb); + ttyb.erase = '#'; + ttyb.kill = '@'; + stty(0, &ttyb); + loop: + namep = utmp.name; + if (argc>1) { + np = argv[1]; + while (namep= 0) { + t = utmp.tty; + if (t>='a') + t =- 'a' - (10+'0'); + seek(f, (t-'0')*16, 0); + write(f, &utmp, 16); + close(f); + } + if ((f = open("/usr/adm/wtmp", 1)) >= 0) { + seek(f, 0, 2); + write(f, &utmp, 16); + close(f); + } + if ((f = open("/etc/motd", 0)) >= 0) { + while(read(f, &t, 1) > 0) + write(1, &t, 1); + close(f); + } + if(stat(".mail", &statb) >= 0 && statb.size) + write(1, "You have mail.\n", 15); + chown(ttyx, uid); + setgid(gid); + setuid(uid); + if (*np == '\0') + np = "/bin/sh"; + execl(np, "-", 0); + write(1, "No shell.\n", 9); + exit(); +bad: + write(1, "Login incorrect.\n", 17); + goto loop; +} + +getpwentry(name, buf) +char *name, *buf; +{ + extern fin; + int fi, r, c; + register char *gnp, *rnp; + + fi = fin; + r = 1; + if((fin = open("/etc/passwd", 0)) < 0) + goto ret; +loop: + gnp = name; + rnp = buf; + while((c=getchar()) != '\n') { + if(c <= 0) + goto ret; + *rnp++ = c; + } + *rnp++ = '\0'; + rnp = buf; + while (*gnp++ == *rnp++); + if ((*--gnp!=' ' && gnp +lock: + +lpd: + + .even +.bss + +ch: .=.+2 +dfi: .=.+2 +dbuf: .=.+18. +print: .=.+518. +proto: .=.+518. +insert: .=.+518. +buf: .=.+400. +sleep = 35. +signal = 48. diff --git a/source/s1/lpr.c b/source/s1/lpr.c new file mode 100644 index 0000000..61da897 --- /dev/null +++ b/source/s1/lpr.c @@ -0,0 +1,244 @@ +/* + * dpr -- off line print via dataphone daemon to GCOS + * normally invoked through opr + */ + +char tfname[] "/usr/lpd/tfaXXXXX"; +char cfname[] "/usr/lpd/cfaXXXXX"; +char lfname[] "/usr/lpd/lfaXXXXX"; +char dfname[] "/usr/lpd/dfaXXXXX"; +int nact; +int tff; +int mailflg; +char person[10]; +int inchar; +int maxrec 1000; + +main(argc, argv) +int argc; +char *argv[]; +{ + register char *arg; + int c, f, flag; + int out(); + + pidfn(); + if((signal(1, 1) & 01) == 0) + signal(1, out); + if((signal(2, 1) & 01) == 0) + signal(2, out); + if((signal(3, 1) & 01) == 0) + signal(3, out); + flag = 0; + tff = nfile(tfname); + while (argc>1 && (arg = argv[1])[0]=='-') { + switch (arg[1]) { + + case 'c': + flag = '+'; + break; + + case 'r': + flag = '-'; + break; + + case 'm': + mailflg = 1; + break; + } + argc--; + argv++; + } + ident(); + + if(argc == 1) + copy(0); + while(--argc) { + arg = *++argv; + if(flag == '+') + goto cf; + if(*arg == '/' && flag != '-') { + card('F', arg); + nact++; + continue; + } + if(link(arg, lfname) < 0) + goto cf; + card('F', lfname); + card('U', lfname); + lfname[inchar]++; + nact++; + goto df; + + cf: + f = open(arg, 0); + if(f < 0) { + printf("Cannot open %s\n", arg); + continue; + } + copy(f); + close(f); + + df: + if(flag == '-') { + f = unlink(arg); + if(f < 0) + printf("Cannot remove %s\n", arg); + } + } + + if(nact) { + tfname[inchar]--; + f = link(tfname, dfname); + if(f < 0) { + printf("Cannot rename %s\n", dfname); + tfname[inchar]++; + out(); + } + unlink(tfname); + execl("/etc/lpd", "lpd", 0); + dfname[inchar]++; + } + out(); +} + +copy(f) +int f; +{ + int ff, i, nr, nc; + static int buf[256]; + + card('F', cfname); + card('U', cfname); + ff = nfile(cfname); + nc = 0; + nr = 0; + while((i = read(f, buf, 512)) > 0) { + write(ff, buf, i); + nc =+ i; + if(nc >= 512) { + nc =- 512; + nr++; + if(nr > maxrec) { + printf("Copy file is too large\n"); + break; + } + } + } + close(ff); + nact++; +} + +card(c, s) +int c; +char s[]; +{ + char *p1, *p2; + static char buf[512]; + int col; + + p1 = buf; + p2 = s; + col = 0; + *p1++ = c; + while((c = *p2++) != '\0') { + *p1++ = c; + col++; + } + *p1++ = '\n'; + write(tff, buf, col+2); +} + +ident() +{ + int c, n; + register char *b1p, *pp, *b2p; + static char b1[100], b2[100]; + + b1p = b1; + if(getpw(getuid(), b1p)) { + b1p = "pdp::::m0000,m000:"; + } + n = 0; + b2p = b2; + while(*b2p++ = "$ ident "[n++]); + b2p--; + n = 5; + while(--n) while(*b1p++ != ':'); + while((*b2p++ = *b1p++) != ':'); + b2p[-1] = ','; + b1p = b1; + pp = person; + while((c = *b1p++) != ':') { + *b2p++ = c; + *pp++ = c; + } + *b2p++ = 0; + *pp++ = 0; + card('L', b2); + if (mailflg) + card('M', person); +} + +pidfn() +{ + register i, j, c; + int p; + + p = getpid(); + i = 0; + while(tfname[i] != 'X') + i++; + i =+ 4; + for(j=0; j<5; j++) { + c = (p%10) + '0'; + p =/ 10; + tfname[i] = c; + cfname[i] = c; + lfname[i] = c; + dfname[i] = c; + i--; + } + inchar = i; +} + +nfile(name) +char *name; +{ + register f; + + f = creat(name, 0666); + if(f < 0) { + printf("Cannot create %s\n", name); + out(); + } + name[inchar]++; + return(f); +} + +out() +{ + register i; + + signal(1, 1); + signal(1, 2); + signal(1, 3); + i = inchar; + while(tfname[i] != 'a') { + tfname[i]--; + unlink(tfname); + } + while(cfname[i] != 'a') { + cfname[i]--; + unlink(cfname); + } + while(lfname[i] != 'a') { + lfname[i]--; + unlink(lfname); + } + while(dfname[i] != 'a') { + dfname[i]--; + unlink(dfname); + } + exit(); +} diff --git a/source/s1/ls.c b/source/s1/ls.c new file mode 100644 index 0000000..abb3335 --- /dev/null +++ b/source/s1/ls.c @@ -0,0 +1,461 @@ +# +/* + * list file or directory + */ + +struct { + int fdes; + int nleft; + char *nextc; + char buff[512]; +} inf; + +struct ibuf { + int idev; + int inum; + int iflags; + char inl; + char iuid; + char igid; + char isize0; + int isize; + int iaddr[8]; + char *iatime[2]; + char *imtime[2]; +}; + +struct lbuf { + char lname[15]; + int lnum; + int lflags; + char lnl; + char luid; + char lgid; + char lsize0; + int lsize; + char *lmtime[2]; +}; + +struct lbufx { + char *namep; +}; + +int aflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg; +int fout; +int rflg 1; +char *year; +int flags; +int uidfil -1; +int lastuid -1; +char tbuf[16]; +int tblocks; +int statreq; +struct lbuf *lastp &end; +struct lbuf *rlastp &end; +char *dotp "."; + +#define IFMT 060000 +#define DIR 0100000 +#define CHR 020000 +#define BLK 040000 +#define ISARG 01000 +#define LARGE 010000 +#define STXT 010000 +#define SUID 04000 +#define SGID 02000 +#define ROWN 0400 +#define WOWN 0200 +#define XOWN 0100 +#define RGRP 040 +#define WGRP 020 +#define XGRP 010 +#define ROTH 04 +#define WOTH 02 +#define XOTH 01 +#define RSTXT 01000 + +main(argc, argv) +char **argv; +{ + int i, j; + extern struct lbuf end; + register struct lbuf *ep, *ep1; + register struct lbuf *slastp; + struct lbuf lb; + int t; + int compar(); + + fout = dup(1); + time(lb.lmtime); + year = lb.lmtime[0] - 245; /* 6 months ago */ + if (--argc > 0 && *argv[1] == '-') { + argv++; + while (*++*argv) switch (**argv) { + case 'a': + aflg++; + continue; + + case 's': + sflg++; + statreq++; + continue; + + case 'd': + dflg++; + continue; + + case 'g': + gflg++; + continue; + + case 'l': + lflg++; + statreq++; + continue; + + case 'r': + rflg = -1; + continue; + + case 't': + tflg++; + statreq++; + continue; + + case 'u': + uflg++; + continue; + + case 'i': + iflg++; + continue; + + case 'f': + fflg++; + continue; + + default: + continue; + } + argc--; + } + if (fflg) { + aflg++; + lflg = 0; + sflg = 0; + tflg = 0; + statreq = 0; + } + if(lflg) { + t = "/etc/passwd"; + if(gflg) + t = "/etc/group"; + uidfil = open(t, 0); + } + if (argc==0) { + argc++; + argv = &dotp - 1; + } + for (i=0; i < argc; i++) { + if ((ep = gstat(*++argv, 1))==0) + continue; + ep->namep = *argv; + ep->lflags =| ISARG; + } + qsort(&end, lastp - &end, sizeof *lastp, compar); + slastp = lastp; + for (ep = &end; eplflags&DIR && dflg==0 || fflg) { + if (argc>1) + printf("\n%s:\n", ep->namep); + lastp = slastp; + readdir(ep->namep); + if (fflg==0) + qsort(slastp,lastp - slastp,sizeof *lastp,compar); + if (statreq) + printf("total %d\n", tblocks); + for (ep1=slastp; ep1lnum == -1) + return; + if (iflg) + printf("%5d ", p->lnum); + if (lflg) { + pmode(p->lflags); + printf("%2d ", p->lnl); + t = p->luid; + if(gflg) + t = p->lgid; + t =& 0377; + if (getname(t, tbuf)==0) + printf("%-6.6s", tbuf); + else + printf("%-6d", t); + if (p->lflags & (BLK|CHR)) + printf("%3d,%3d", p->lsize.dmajor&0377, + p->lsize.dminor&0377); + else + printf("%7s", locv(p->lsize0, p->lsize)); + cp = ctime(p->lmtime); + if(p->lmtime[0] < year) + printf(" %-7.7s %-4.4s ", cp+4, cp+20); else + printf(" %-12.12s ", cp+4); + } else if (sflg) + printf("%4d ", nblock(p->lsize0, p->lsize)); + if (p->lflags&ISARG) + printf("%s\n", p->namep); + else + printf("%.14s\n", p->lname); +} + +getname(uid, buf) +int uid; +char buf[]; +{ + int j, c, n, i; + + if (uid==lastuid) + return(0); + inf.fdes = uidfil; + seek(inf.fdes, 0, 0); + inf.nleft = 0; + lastuid = -1; + do { + i = 0; + j = 0; + n = 0; + while((c=getc(&inf)) != '\n') { + if (c<0) + return(-1); + if (c==':') { + j++; + c = '0'; + } + if (j==0) + buf[i++] = c; + if (j==2) + n = n*10 + c - '0'; + } + } while (n != uid); + buf[i++] = '\0'; + lastuid = uid; + return(0); +} + +nblock(size0, size) +char *size0, *size; +{ + register int n; + + n = ldiv(size0, size, 512); + if (size&0777) + n++; + if (n>8) + n =+ (n+255)/256; + return(n); +} + +int m0[] { 3, DIR, 'd', BLK, 'b', CHR, 'c', '-'}; +int m1[] { 1, ROWN, 'r', '-' }; +int m2[] { 1, WOWN, 'w', '-' }; +int m3[] { 2, SUID, 's', XOWN, 'x', '-' }; +int m4[] { 1, RGRP, 'r', '-' }; +int m5[] { 1, WGRP, 'w', '-' }; +int m6[] { 2, SGID, 's', XGRP, 'x', '-' }; +int m7[] { 1, ROTH, 'r', '-' }; +int m8[] { 1, WOTH, 'w', '-' }; +int m9[] { 1, XOTH, 'x', '-' }; +int m10[] { 1, STXT, 't', ' ' }; + +int *m[] { m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10}; + +pmode(aflag) +{ + register int **mp; + + flags = aflag; + for (mp = &m[0]; mp < &m[11];) + select(*mp++); +} + +select(pairp) +int *pairp; +{ + register int n, *ap; + + ap = pairp; + n = *ap++; + while (--n>=0 && (flags&*ap++)==0) + ap++; + putchar(*ap); +} + +makename(dir, file) +char *dir, *file; +{ + static char dfile[100]; + register char *dp, *fp; + register int i; + + dp = dfile; + fp = dir; + while (*fp) + *dp++ = *fp++; + *dp++ = '/'; + fp = file; + for (i=0; i<14; i++) + *dp++ = *fp++; + *dp = 0; + return(dfile); +} + +readdir(dir) +char *dir; +{ + static struct { + int dinode; + char dname[14]; + } dentry; + register char *p; + register int j; + register struct lbuf *ep; + + if (fopen(dir, &inf) < 0) { + printf("%s unreadable\n", dir); + return; + } + tblocks = 0; + for(;;) { + p = &dentry; + for (j=0; j<16; j++) + *p++ = getc(&inf); + if (dentry.dinode==0 + || aflg==0 && dentry.dname[0]=='.') + continue; + if (dentry.dinode == -1) + break; + ep = gstat(makename(dir, dentry.dname), 0); + if (ep->lnum != -1) + ep->lnum = dentry.dinode; + for (j=0; j<14; j++) + ep->lname[j] = dentry.dname[j]; + } + close(inf.fdes); +} + +gstat(file, argfl) +char *file; +{ + struct ibuf statb; + register struct lbuf *rep; + + if (lastp+1 >= rlastp) { + sbrk(512); + rlastp.idev =+ 512; + } + rep = lastp; + lastp++; + rep->lflags = 0; + rep->lnum = 0; + if (argfl || statreq) { + if (stat(file, &statb)<0) { + printf("%s not found\n", file); + statb.inum = -1; + statb.isize0 = 0; + statb.isize = 0; + statb.iflags = 0; + if (argfl) { + lastp--; + return(0); + } + } + rep->lnum = statb.inum; + statb.iflags =& ~DIR; + if ((statb.iflags&IFMT) == 060000) { + statb.iflags =& ~020000; + } else if ((statb.iflags&IFMT)==040000) { + statb.iflags =& ~IFMT; + statb.iflags =| DIR; + } + statb.iflags =& ~ LARGE; + if (statb.iflags & RSTXT) + statb.iflags =| STXT; + statb.iflags =& ~ RSTXT; + rep->lflags = statb.iflags; + rep->luid = statb.iuid; + rep->lgid = statb.igid; + rep->lnl = statb.inl; + rep->lsize0 = statb.isize0; + rep->lsize = statb.isize; + if (rep->lflags & (BLK|CHR) && lflg) + rep->lsize = statb.iaddr[0]; + rep->lmtime[0] = statb.imtime[0]; + rep->lmtime[1] = statb.imtime[1]; + if(uflg) { + rep->lmtime[0] = statb.iatime[0]; + rep->lmtime[1] = statb.iatime[1]; + } + tblocks =+ nblock(statb.isize0, statb.isize); + } + return(rep); +} + +compar(ap1, ap2) +struct lbuf *ap1, *ap2; +{ + register struct lbuf *p1, *p2; + register int i; + int j; + struct { char *charp;}; + + p1 = ap1; + p2 = ap2; + if (dflg==0) { + if ((p1->lflags&(DIR|ISARG)) == (DIR|ISARG)) { + if ((p2->lflags&(DIR|ISARG)) != (DIR|ISARG)) + return(1); + } else { + if ((p2->lflags&(DIR|ISARG)) == (DIR|ISARG)) + return(-1); + } + } + if (tflg) { + i = 0; + if (p2->lmtime[0] > p1->lmtime[0]) + i++; + else if (p2->lmtime[0] < p1->lmtime[0]) + i--; + else if (p2->lmtime[1] > p1->lmtime[1]) + i++; + else if (p2->lmtime[1] < p1->lmtime[1]) + i--; + return(i*rflg); + } + if (p1->lflags&ISARG) + p1 = p1->namep; + else + p1 = p1->lname; + if (p2->lflags&ISARG) + p2 = p2->namep; + else + p2 = p2->lname; + for (;;) + if ((j = *p1.charp++ - *p2.charp++) || p1.charp[-1]==0) + return(rflg*j); + return(0); +} diff --git a/source/s1/run b/source/s1/run new file mode 100644 index 0000000..49a275a --- /dev/null +++ b/source/s1/run @@ -0,0 +1,237 @@ +cc -s -f -O ac.c +cmp a.out /usr/bin/ac +cp a.out /usr/bin/ac + +as ar.s +strip a.out +cmp a.out /bin/ar +cp a.out /bin/ar + +cc -s -O banner.c +cmp a.out /usr/bin/banner +cp a.out /usr/bin/banner + +as bas.s +ld -s -n a.out -l +cmp a.out /bin/bas +cp a.out /bin/bas + +yacc bc.y +cc -s -O y.tab.c -ly +cmp a.out /usr/bin/bc +cp a.out /usr/bin/bc +rm y.tab.c + +cc -s -O bcd.c +cmp a.out /usr/bin/bcd +cp a.out /usr/bin/bcd + +cc -s -O cal.c +cmp a.out /usr/bin/cal +cp a.out /usr/bin/cal + +as cat.s +strip a.out +cmp a.out /bin/cat +cp a.out /bin/cat + +cc -s -n -O cc.c +cmp a.out /bin/cc +cp a.out /bin/cc + +cc -s -f -O cdb?.c +cmp a.out /bin/cdb +cp a.out /bin/cdb +rm cdb?.o + +as chgrp.s +ld -s a.out -l +cmp a.out /bin/chgrp +cp a.out /bin/chgrp + +cc -s -O chmod.c +cmp a.out /bin/chmod +cp a.out /bin/chmod + +as chown.s +ld -s a.out -l +cmp a.out /bin/chown +cp a.out /bin/chown + +as clri.s +strip a.out +cmp a.out /bin/clri +cp a.out /bin/clri + +cc -s -O cmp.c +cmp a.out /bin/cmp +cp a.out /bin/cmp + +cc -s -O col.c +cmp a.out /usr/bin/col +cp a.out /usr/bin/col + +cc -s -O comm.c +cmp a.out /usr/bin/comm +cp a.out /usr/bin/comm + +cc -s -O cp.c +cmp a.out /bin/cp +cp a.out /bin/cp + +cc -s -O cpall.c +cmp a.out /usr/bin/cpall +cp a.out /usr/bin/cpall + +cc -s -O cron.c +cmp a.out /etc/cron +cp a.out /etc/cron + +cc -s -O crypt.c +cmp a.out /usr/bin/crypt +cp a.out /usr/bin/crypt + +cc -s -O date.c +cmp a.out /bin/date +cp a.out /bin/date + +as db?.s +strip a.out +cmp a.out /bin/db +cp a.out /bin/db + +as dc?.s +strip a.out +cmp a.out /bin/dc +cp a.out /bin/dc + +cc -s -O dcheck.c +cmp a.out /bin/dcheck +cp a.out /bin/dcheck + +cc -s -O dd.c +cmp a.out /bin/dd +cp a.out /bin/dd + +cc -s -O df.c +cmp a.out /bin/df +cp a.out /bin/df + +cc -c -O diff1.c +as diff2.s +cc -s diff1.o a.out +cmp a.out /usr/bin/diff +cp a.out /usr/bin/diff +rm diff1.o + +as dsw.s +strip a.out +cmp a.out /bin/dsw +cp a.out /bin/dsw + +as du.s +ld -s a.out -l +cmp a.out /bin/du +cp a.out /bin/du + +cc -s -O dump.c +cmp a.out /bin/dump +cp a.out /bin/dump + +cc -s -O echo.c +cmp a.out /bin/echo +cp a.out /bin/echo + +cc -s -n -O ed.c +cmp a.out /bin/ed +cp a.out /bin/ed + +cc -s -O exit.c +cmp a.out /bin/exit +cp a.out /bin/exit + +cc -s -O fc.c +cmp a.out /bin/fc +cp a.out /bin/fc + +as fed?.s form[56].s +strip a.out +cmp a.out /usr/bin/fed +cp a.out /usr/bin/fed + +cc -s -O file.c +cmp a.out /bin/file +cp a.out /bin/file + +cc -s -O find.c +cmp a.out /usr/bin/find +cp a.out /usr/bin/find + +as form?.s +strip a.out +cmp a.out /usr/bin/form +cp a.out /usr/bin/form + +cc -s -n -O getty.c +cmp a.out /etc/getty +cp a.out /etc/getty + +cc -s -n -O glob.c +cmp a.out /etc/glob +cp a.out /etc/glob + +cc -s -O goto.c +cmp a.out /bin/goto +cp a.out /bin/goto + +cc -s -O grep.c +cmp a.out /usr/bin/grep +cp a.out /usr/bin/grep + +cc -s -O gsi.c +cmp a.out /usr/bin/gsi +cp a.out /usr/bin/gsi + +cc -s -O icheck.c +cmp a.out /bin/icheck +cp a.out /bin/icheck + +cc -s -O if.c +cmp a.out /bin/if +cp a.out /bin/if + +cc -s -n -O init.c +cmp a.out /etc/init +cp a.out /etc/init + +as kill.s +strip a.out +cmp a.out /bin/kill +cp a.out /bin/kill + +cc -s -n -O ld.c +cmp a.out /bin/ld +cp a.out /bin/ld + +cc -s -O ln.c +cmp a.out /bin/ln +cp a.out /bin/ln + +cc -s -O login.c +cmp a.out /bin/login +cp a.out /bin/login + +as lpd.s +ld -s a.out -l +cmp a.out /etc/lpd +cp a.out /etc/lpd + +cc -s -O lpr.c +cmp a.out /lib/lpr +cp a.out /lib/lpr + +cc -s -n -O ls.c +cmp a.out /bin/ls +cp a.out /bin/ls + +rm a.out diff --git a/source/s2/mail.c b/source/s2/mail.c new file mode 100644 index 0000000..b8a4648 --- /dev/null +++ b/source/s2/mail.c @@ -0,0 +1,281 @@ +# +/* mail command usage + mail + prints your mail + mail people + sends standard input to people + */ + +#define SIGINT 2 + +struct utmp { + char name[8]; + char tty; + char pad1; + int ltime[2]; + int pad2; +}; + +struct passwd { + char *pw_name; + char *pw_passwd; + int pw_uid; + int pw_gid; + char *pw_gecos; + char *pw_dir; + char *pw_shell; +}; + +char lettmp[] "/tmp/maxxxxx"; +char preptmp[] "/tmp/mbxxxxx"; +int pwfil; + +main(argc, argv) +char **argv; +{ + register me; + extern fout; + register struct passwd *p; + register char *cp; + static struct utmp ubuf; + int uf; + + maketemp(); + if (argc==1 || argc==2 && argv[1][0]=='-') { + printmail(argc, argv); + delexit(); + } + signal(SIGINT, delexit); + fout = creat(lettmp, 0600); + if (((me=ttyn(1))!='x' || (me=ttyn(2))!='x') + && (uf = open("/etc/utmp", 0)) > 0) { + while (read(uf, &ubuf, sizeof ubuf) == sizeof ubuf) + if (ubuf.tty == me) { + ubuf.name[8] = ' '; + close(uf); + for (cp=ubuf.name; *cp++!=' ';); + *--cp = 0; + bulkmail(argc, argv, ubuf.name); + } + } + me = getuid() & 0377; + setpw(); + for (;;) + if ((p = getpwent()) && p->pw_uid == me) + bulkmail(argc, argv, p->pw_name); + fout = 1; + printf("Who are you?\n"); + delexit(); +} + +printmail(argc, argv) +char **argv; +{ + extern fin, fout; + register n, c, f; + + if (fopen(".mail", &fin)>=0 && (c = getchar())) { + do { + putchar(c); + } while (c = getchar()); + close(fin); + c = 'y'; + if (argc<2) { + if (ttyn(0)!='x') { + printf("Save?"); + fin = 0; + c = getchar(); + } + } else + c = argv[1][1]; + if (c=='y') { + prepend(".mail", "mbox"); + printf("Saved mail in 'mbox'\n"); + } + close(creat(".mail")); + } else + printf("No mail.\n"); +} + +bulkmail(argc, argv, from) +char **argv, *from; +{ + extern fin, fout; + int tbuf[2]; + register c; + + fin = 0; + (&fin)[1] = 0; + time(tbuf); + printf("From %s %s", from, ctime(tbuf)); + while (c = getchar()) + putchar(c); + putchar('\n'); + flush(); + close(fout); + while (--argc > 0) + sendto(*++argv); + delexit(); +} + +sendto(person) +char *person; +{ + static saved; + extern fout; + extern fin; + register struct passwd *p; + + setpw(); + while (p = getpwent()) { + if (equal(p->pw_name, person)) { + if (prepend(lettmp, cat(p->pw_dir, "/.mail"))==0) + break; + return; + } + } + fout = 1; + flush(); + printf("Can't send to %s.\n", person); + if (ttyn(0)!='x' && saved==0) { + unlink("dead.letter"); + saved++; + printf("Letter saved in 'dead.letter'\n"); + prepend(lettmp, "dead.letter"); + } +} + +prepend(from, to) +char *from, *to; +{ + extern int fin, fout; + + fcreat(preptmp, &fout); + fopen(from, &fin); + while (putchar(getchar())); + close(fin); + fopen(to, &fin); + while (putchar(getchar())); + close(fin); + flush(); + close(fout); + if (fcreat(to, &fout) < 0) { + fout = 1; + return(0); + } + fopen(preptmp, &fin); + while(putchar(getchar())); + flush(); + close(fout); + close(fin); + fout = 1; + return(1); +} + +setpw() +{ + extern fin; + + if (pwfil == 0) { + fopen("/etc/passwd", &fin); + pwfil = fin; + } else + fin = pwfil; + (&fin)[1] = 0; + seek(fin, 0, 0); +} + +getpwent() +{ + register char *p; + register c; + static struct passwd passwd; + static char line[100]; + extern fin; + + p = line; + while((c=getchar()) != '\n') { + if(c <= 0) + return(0); + if(p < line+98) + *p++ = c; + } + *p = 0; + p = line; + passwd.pw_name = p; + p = pwskip(p); + passwd.pw_passwd = p; + p = pwskip(p); + passwd.pw_uid = atoi(p); + p = pwskip(p); + passwd.pw_gid = atoi(p); + p = pwskip(p); + passwd.pw_gecos = p; + p = pwskip(p); + passwd.pw_dir = p; + p = pwskip(p); + passwd.pw_shell = p; + return(&passwd); +} + +pwskip(ap) +char *ap; +{ + register char *p; + + p = ap; + while(*p != ':') { + if(*p == 0) + return(p); + p++; + } + *p++ = 0; + return(p); +} + +delexit() +{ + unlink(lettmp); + unlink(preptmp); + exit(0); +} + +maketemp() +{ + int i, pid, d; + + pid = getpid(); + for (i=11; i>=7; --i) { + d = (pid&07) + '0'; + lettmp[i] = d; + preptmp[i] = d; + pid =>> 3; + } +} + +equal(as1, as2) +{ + register char *s1, *s2; + + s1 = as1; + s2 = as2; + while (*s1++ == *s2) + if (*s2++ == 0) + return(1); + return(0); +} + +cat(ap1, ap2) +char *ap1, *ap2; +{ + register char *p1, *p2; + static char fn[32]; + + p1 = ap1; + p2 = fn; + while (*p2++ = *p1++); + p2--; + p1 = ap2; + while (*p2++ = *p1++); + return(fn); +} diff --git a/source/s2/mesg.c b/source/s2/mesg.c new file mode 100644 index 0000000..efde97e --- /dev/null +++ b/source/s2/mesg.c @@ -0,0 +1,49 @@ +/* + * mesg -- set current tty to accept or + * forbid write permission. + * + * mesg [y] [n] + * y allow messages + * n forbid messages + */ + +int sbuf[40]; + +main(argc, argv) +char *argv[]; +{ + register char *tty; + + tty = "/dev/ttyx"; + tty[8] = ttyn(1); + if(stat(tty, sbuf) < 0) { + write(2, "cannot stat\n", 12); + exit(1); + } + if(argc < 2) { + if(sbuf[2] & 02) + goto no; + goto yes; + } + if(*argv[1] == 'y') + goto yes; + +no: + if(chmod(tty, 0600) < 0) + goto bad; + goto was; + +yes: + if(chmod(tty, 0622) < 0) + goto bad; + +was: + if(sbuf[2] & 02) + write(2, "was y\n", 6); else + write(2, "was n\n", 6); + exit(0); + +bad: + write(2, "cannot change mode\n", 19); + exit(1); +} diff --git a/source/s2/mkdir.s b/source/s2/mkdir.s new file mode 100644 index 0000000..3fdf55b --- /dev/null +++ b/source/s2/mkdir.s @@ -0,0 +1,91 @@ +/ makdir -- make a directory + + sys getuid + mov r0,uid + mov sp,r5 + tst (r5)+ + +loop: + tst (r5)+ + dec (sp) + bgt 1f + sys exit +1: + mov (r5),r0 + mov $buf1,r1 + mov $buf2,r2 + clr r3 +1: + movb (r0)+,r4 + beq 2f + movb r4,(r1)+ + movb r4,(r2)+ + cmpb r4,$'/ + bne 1b + mov r2,r3 + br 1b +2: + movb $'/,(r1)+ + movb $'.,(r1)+ + clrb (r1) + mov $dot,dir + tst r3 + beq 1f + mov $buf2,dir + clrb (r3) + cmp r3,$buf2+1 + beq 1f + clrb -(r3) / ??? +1: + tstb uid + beq 2f + sys stat; dir:..; stbuf / status of parent dir + bes error + mov stbuf+4,r0 + cmpb uid,stbuf+7 + bne 1f + ash $-6,r0 +1: + ror r0 + ror r0 + bcc error / no write permission in parent +2: + mov (r5),0f + sys makdir; 0:..; 140777; 0 + bes error / prob already exists + mov (r5),0f + sys chown; 0:..; uid:.. + mov (r5),0f + sys link; 0:..; buf1 + bes error + movb $'.,(r1)+ + clrb (r1) + mov dir,0f + sys link; 0:..; buf1 + bec loop + +error: + mov (r5),r0 + mov r0,0f + clr 0f+2 +1: + tstb (r0)+ + beq 1f + inc 0f+2 + br 1b +1: + mov $1,r0 + sys write; 0:..; .. + mov $1,r0 + sys write; ques; 3 + br loop + +dot: <.\0> +ques: < ?\n> + .even + +.bss +buf1: .=.+100. +buf2: .=.+100. +stbuf: .=.+40. + diff --git a/source/s2/mkfs.c b/source/s2/mkfs.c new file mode 100644 index 0000000..f0c1fd4 --- /dev/null +++ b/source/s2/mkfs.c @@ -0,0 +1,504 @@ +# +struct +{ + char *s_isize; + char *s_fsize; + int s_nfree; + int s_free[100]; + int s_ninode; + int s_inode[100]; + char s_flock; + char s_ilock; + char s_fmod; + int s_time[2]; +} filsys; + +struct inode +{ + int i_number; + int i_mode; + char i_nlink; + char i_uid; + char i_gid; + char i_size0; + char *i_size1; + int i_addr[8]; + int i_time[4]; +}; + +/* modes */ +#define IALLOC 0100000 +#define IFMT 060000 +#define IFDIR 040000 +#define IFCHR 020000 +#define IFBLK 060000 +#define ILARG 010000 +#define ISUID 04000 +#define ISGID 02000 +#define IREAD 0400 +#define IWRITE 0200 +#define IEXEC 0100 + +int utime[2]; +int fin; +int fsi; +int fso; +char *charp; +int buf[256]; +char string[50]; +char *fsys; +char *proto; +int f_n 1; +int f_m 1; + +main(argc, argv) +char **argv; +{ + int f, n; + + /* + * open relevent files + */ + + time(utime); + if(argc != 3) { + printf("arg count\n"); + exit(); + } + fsys = argv[1]; + for(n=0; f=fsys[n+1]; n++) + if(fsys[n] == 'r') { + if(f == 'k') { + f_n = 24; + f_m = 3; + } + if(f == 'p') { + f_n = 10; + f_m = 4; + } + } + proto = argv[2]; + fso = creat(fsys, 0666); + if(fso < 0) { + printf("%s: cannot create\n", fsys); + exit(); + } + fsi = open(fsys, 0); + if(fsi < 0) { + printf("%s: cannot open\n", fsys); + exit(); + } + fin = open(proto, 0); + if(fin < 0) { + n = 0; + for(f=0; proto[f]; f++) { + if(proto[f]<'0' || proto[f]>'9') { + printf("%s: cannot open\n", proto); + exit(); + } + n = n*10 + proto[f]-'0'; + } + filsys.s_fsize = n; + filsys.s_isize = ldiv(0, n, 43+ldiv(0, n, 1000)); + printf("isize = %d\n", filsys.s_isize); + if(f_n != 1) + printf("free list %d/%d\n", f_m, f_n); + charp = "d--777 0 0 $ "; + goto f3; + } + + /* + * get name of boot load program + * and read onto block 0 + */ + + getstr(); + f = open(string, 0); + if(f < 0) { + printf("%s: cannot open init\n", string); + goto f2; + } + read(f, buf, 020); + if(buf[0] != 0407) { + printf("%s: bad format\n", string); + goto f1; + } + n = buf[1]+buf[2]; + if(n > 512) { + printf("%s: too big\n", string); + goto f1; + } + read(f, buf, n); + wtfs(0, buf); + +f1: + close(f); + + /* + * get total disk size + * and inode block size + */ + +f2: + filsys.s_fsize = getnum(); + filsys.s_isize = getnum(); + +f3: + if(filsys.s_isize > filsys.s_fsize || + filsys.s_fsize-filsys.s_isize-2 < filsys.s_isize) { + printf("%l/%l: bad ratio\n", filsys.s_fsize, filsys.s_isize); + exit(); + } + bflist(); + + /* + * initialize files + */ + + for(n=0; n<256; n++) + buf[n] = 0; + for(n=0; n!=filsys.s_isize; n++) + wtfs(n+2, buf); + cfile(0); + + /* + * write out super block + */ + + for(n=0; n<256; n++) + buf[n] = 0; + filsys.s_time[0] = utime[0]; + filsys.s_time[1] = utime[1]; + wtfs(1, &filsys); +} + +cfile(par) +struct inode *par; +{ + struct inode in; + int db[256], ib[256]; + int dbc, ibc; + static ino; + int i, f, *p1, *p2; + + /* + * get mode, uid and gid + */ + + getstr(); + in.i_mode = IALLOC; + in.i_mode =| gmode(string[0], "bcd", IFBLK, IFCHR, IFDIR); + in.i_mode =| gmode(string[1], "u", ISUID); + in.i_mode =| gmode(string[2], "g", ISGID); + for(i=3; i<6; i++) { + if(string[i]<'0' || string[i]>'7') { + printf("%c/%s: bad digit\n", string[i], string); + exit(); + } + in.i_mode =| (string[i]-'0')<<(15-3*i); + } + in.i_uid = getnum(); + in.i_gid = getnum(); + + /* + * general initialization prior to + * switching on format + */ + + ino++; + in.i_number = ino; + if(ldiv(0, ino, 16) > filsys.s_isize) { + printf("too many inodes\n"); + exit(); + } + in.i_nlink = 1; + in.i_size0 = 0; + in.i_size1 = 0; + for(i=0; i<8; i++) + in.i_addr[i] = 0; + for(i=0; i<256; i++) { + db[i] = 0; + ib[i] = 0; + } + if(par == 0) { + par = ∈ + in.i_nlink--; + } + dbc = 0; + ibc = 0; + switch(in.i_mode&IFMT) { + + case 0: + /* + * regular file + * contents is a file name + */ + + getstr(); + f = open(string, 0); + if(f < 0) { + printf("%s: cannot open\n", string); + break; + } + while((i=read(f, db, 512)) > 0) { + in.i_size1 =+ i; + newblk(&dbc, db, &ibc, ib); + } + close(f); + break; + + case IFBLK: + case IFCHR: + /* + * special file + * content is maj/min types + */ + + in.i_addr[0] = getnum()<<8; + in.i_addr[0] =| getnum(); + break; + + case IFDIR: + /* + * directory + * put in extra links + * call recursively until + * name of "$" found + */ + + par->i_nlink++; + entry(par->i_number, "..", &dbc, db, &ibc, ib); + in.i_nlink++; + entry(in.i_number, ".", &dbc, db, &ibc, ib); + in.i_size1 = 32; + for(;;) { + getstr(); + if(string[0]=='$' && string[1]=='\0') + break; + entry(ino+1, string, &dbc, db, &ibc, ib); + in.i_size1 =+ 16; + cfile(&in); + } + break; + } + if(dbc != 0) + newblk(&dbc, db, &ibc, ib); + if(ibc > 8) { + in.i_mode =| ILARG; + dbc = alloc(); + wtfs(dbc, ib); + in.i_addr[0] = dbc; + } else + for(i=0; i'9') { + printf("%s: bad number\n", string); + exit(); + } + n = n*10 + string[i] - '0'; + } + return(n); +} + +getstr() +{ + int i, c; + +loop: + switch(c=getch()) { + + case ' ': + case '\t': + case '\n': + goto loop; + + case '\0': + printf("EOF\n"); + exit(); + + case ':': + while(getch() != '\n'); + goto loop; + + } + i = 0; + + do { + string[i++] = c; + c = getch(); + } while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0'); + string[i] = '\0'; +} + +rdfs(bno, bf) +{ + int n; + + seek(fsi, bno, 3); + n = read(fsi, bf, 512); + if(n != 512) { + printf("read error: %l\n", bno); + exit(); + } +} + +wtfs(bno, bf) +{ + int n; + + seek(fso, bno, 3); + n = write(fso, bf, 512); + if(n != 512) { + printf("write error: %l\n", bno); + exit(); + } +} + +alloc() +{ + int bno, i; + + filsys.s_nfree--; + bno = filsys.s_free[filsys.s_nfree]; + filsys.s_free[filsys.s_nfree] = 0; + if(bno == 0) { + printf("out of free space\n"); + exit(); + } + if(filsys.s_nfree <= 0) { + rdfs(bno, buf); + filsys.s_nfree = buf[0]; + for(i=0; i<100; i++) + filsys.s_free[i] = buf[i+1]; + } + return(bno); +} + +free(bno) +{ + int i; + + if(filsys.s_nfree >= 100) { + buf[0] = filsys.s_nfree; + for(i=0; i<100; i++) + buf[i+1] = filsys.s_free[i]; + wtfs(bno, buf); + filsys.s_nfree = 0; + } + filsys.s_free[filsys.s_nfree] = bno; + filsys.s_nfree++; +} + +entry(ino, str, adbc, db, aibc, ib) +char *str; +int *adbc, *db, *aibc, *ib; +{ + char *s; + int i; + + db[*adbc] = ino; + (*adbc)++; + s = &db[*adbc]; + for(i=0; i<14; i++) { + *s++ = *str; + if(*str != '\0') + str++; + } + *adbc =+ 7; + if(*adbc >= 256) + newblk(adbc, db, aibc, ib); +} + +newblk(adbc, db, aibc, ib) +int *adbc, *db, *aibc, *ib; +{ + int bno, i; + + bno = alloc(); + wtfs(bno, db); + for(i=0; i<256; i++) + db[i] = 0; + *adbc = 0; + ib[*aibc] = bno; + (*aibc)++; + if(*aibc >= 256) { + printf("indirect block full\n"); + exit(); + } +} + +getch() +{ + + if(charp) + return(*charp++); + return(getchar()); +} + +bflist() +{ + char flg[100], adr[100]; + register i, j; + char *low, *high; + + if(f_n > 100) + f_n = 100; + for(i=0; i= low+f_n; i =- f_n) + for(j=0; j= low; i--) + free(i); +} diff --git a/source/s2/mknod.c b/source/s2/mknod.c new file mode 100644 index 0000000..0c9d859 --- /dev/null +++ b/source/s2/mknod.c @@ -0,0 +1,42 @@ +main(argc, argv) +int argc; +char **argv; +{ + int m, a, b; + + if(argc != 5) { + printf("arg count\n"); + goto usage; + } + if(*argv[2] == 'b') + m = 0160666; else + if(*argv[2] == 'c') + m = 0120666; else + goto usage; + a = number(argv[3]); + if(a < 0) + goto usage; + b = number(argv[4]); + if(b < 0) + goto usage; + if(mknod(argv[1], m, (a<<8)|b) < 0) + perror("mknod"); + exit(); + +usage: + printf("usage: mknod name b/c major minor\n"); +} + +number(s) +char *s; +{ + int n, c; + + n = 0; + while(c = *s++) { + if(c<'0' || c>'9') + return(-1); + n = n*10 + c-'0'; + } + return(n); +} diff --git a/source/s2/mount.c b/source/s2/mount.c new file mode 100644 index 0000000..f147e75 --- /dev/null +++ b/source/s2/mount.c @@ -0,0 +1,62 @@ +#define NMOUNT 16 +#define NAMSIZ 32 + +struct mtab { + char file[NAMSIZ]; + char spec[NAMSIZ]; +} mtab[NMOUNT]; + +main(argc, argv) +char **argv; +{ + register int ro; + register struct mtab *mp; + register char *np; + int n, mf; + + mf = open("/etc/mtab", 0); + read(mf, mtab, NMOUNT*2*NAMSIZ); + if (argc==1) { + for (mp = mtab; mp < &mtab[NMOUNT]; mp++) + if (mp->file[0]) + printf("%s on %s\n", mp->spec, mp->file); + return; + } + if(argc < 3) { + printf("arg count\n"); + return; + } + ro = 0; + if(argc > 3) + ro++; + if(mount(argv[1], argv[2], ro) < 0) { + perror("mount"); + return; + } + np = argv[1]; + while(*np++) + ; + np--; + while(*--np == '/') + *np = '\0'; + while(np > argv[1] && *--np != '/') + ; + if(*np == '/') + np++; + argv[1] = np; + for (mp = mtab; mp < &mtab[NMOUNT]; mp++) { + if (mp->file[0] == 0) { + for (np = mp->spec; np < &mp->spec[NAMSIZ-1];) + if ((*np++ = *argv[1]++) == 0) + argv[1]--; + for (np = mp->file; np < &mp->file[NAMSIZ-1];) + if ((*np++ = *argv[2]++) == 0) + argv[2]--; + mp = &mtab[NMOUNT]; + while ((--mp)->file[0] == 0); + mf = creat("/etc/mtab", 0644); + write(mf, mtab, (mp-mtab+1)*2*NAMSIZ); + return; + } + } +} diff --git a/source/s2/mv.c b/source/s2/mv.c new file mode 100644 index 0000000..f559844 --- /dev/null +++ b/source/s2/mv.c @@ -0,0 +1,177 @@ +/* +mv [-d] file1 file2 + +unlink file2 +link file1 file2 +unlink file1 +*/ +int stbuf[42]; +struct sbuf { +int dev; +int inum; +int imode; +char nlink; +char uid; +char gid; +char siz0; +char siz1; +int addr[8]; +int adate[2]; +int mdate[2]; +}; +char strbuf[70]; + +main(argc,argv) +int argc; +char *argv[]; +{ +char **argp; +char *argp1, *argp2, *argp3, *argp4; +char *p, *p1, *p2; +char place[100]; +int i; +int status; +int b; +argp = argv; +/* + check for correct number + of arguments +*/ +if(argc != 3){ + write(1,"Usage: mv name1 name2\n",22); + exit(); +} +/* + is there anything to do? +*/ +argp3 = argp[1]; +argp4 = argp[2]; +if(stat(argp[1], stbuf) < 0){ + write(1,"Source file non-existent\n",25); + exit(); +} +/* + yes, there is a source. + check whether file or directory +*/ +if((stbuf[0].imode & 060000) == 040000){ +/* + The source is a directory, so + we do lots of checking and + messing around so as not to get + into trouble. This patch of + code contains administrative + policies rather than system + restrictions. +*/ + if(stat(argp[2], stbuf) >= 0){ + write(1,"Directory target exists.\n",25); + exit(); + } + argp1 = argp[1]; + argp2 = argp[2]; + while(*argp1 == *argp2){ + argp1++; + if(*argp2++ == 0){ + write(1,"???\n",4); + exit(); + } + } + while(*argp1)if(*argp1++ == '/'){ + write(1,"Directory rename only\n",22); + exit(); + } + while(*argp2)if(*argp2++ == '/'){ + write(1,"Directory rename only\n",22); + exit(); + } + if(*--argp1 == '.'){ + write(1,"values of B will give rise to dom!\n",37); + exit(); + } +}else{ +/* + the source is a file. +*/ + setuid(getuid()); + if(stat(argp4, &stbuf[2]) >= 0){ + if((stbuf[2].imode & 060000) == 040000){ + argp2 = strbuf; + while(*argp2++ = *argp4++); + argp2[-1] = '/'; + argp4 = argp[1]; + argp1 = argp[1]; + while(*argp4) + if(*argp4++ == '/') + argp1 = argp4; + while(*argp2++ = *argp1++); + argp4 = strbuf; + } + if(stat(argp4, &stbuf[2]) >= 0){ + if((stbuf[0]==stbuf[2]) && (stbuf[1]==stbuf[3])){ + write(1,"Files are identical.\n",21); + exit(); + } + if((getuid()&0377) == stbuf[2].uid) + b = 0200; else + if((getgid()&0377) == stbuf[2].gid) + b = 020; else + b = 02; + if((stbuf[2].imode & b) == 0) { + printf("%s: %o mode ", argp4, + stbuf[2].imode & 07777); + i = b = getchar(); + while(b != '\n' && b != '\0') + b = getchar(); + if(i != 'y') + exit(); + } + if(unlink(argp4) < 0){ + write(1,"Cannot remove target file.\n",27); + exit(); + } + } + } +} +if(link(argp3, argp4) < 0){ + i = fork(); + if(i == -1){ + write(1,"Try again.\n",11); + exit(); + } + if(i){ + while(wait(&status) != i); + }else{ + p = place; + p1 = p; + while(*p++ = *argp3++); + p2 = p; + while(*p++ = *argp4++); + execl("/bin/cp","cp", p1, p2, 0); + write(1, "no cp\n", 6); + exit(1); + } + if((status & 0377) != 0){ + write(1,"?\n", 2); + exit(); + } + if(status != 0) exit(); +} +if(unlink(argp3) < 0){ + write(1,"Cannot unlink source file.\n",27); + exit(); +} +} + +putchar(c) +{ + write(1, &c, 1); +} + +getchar() +{ + char c; + + if(read(0, &c, 1) != 1) return(0); + return(c); +} diff --git a/source/s2/ncheck.c b/source/s2/ncheck.c new file mode 100644 index 0000000..4ccc60d --- /dev/null +++ b/source/s2/ncheck.c @@ -0,0 +1,299 @@ +# + +char *dargv[] +{ + "/dev/rrk2", + "/dev/rrp0", + 0 +}; + +#define NINODE 16*16 +#include "/usr/sys/ino.h" +#include "/usr/sys/filsys.h" + +struct filsys sblock; +struct inode inode[NINODE]; + +int sflg; +int aflg; +#define NI 20 +#define NDIRS 787 + +int ilist[NI] { -1}; +int fi; +struct htab { + int hino; + int hpino; + char hname[14]; +} htab[NDIRS]; +int nhent 10; +int (*pass[])() { pass1, pass2, pass3 }; +char *lasts; +int ino; +int nerror; +int nffil; +int fout; +int nfiles; +struct dir { + int ino; + char name[14]; +}; + +main(argc, argv) +char **argv; +{ + register char **p; + register int n, *lp; + + nffil = dup(1); + if (argc == 1) { + for (p = dargv; *p;) + check(*p++); + return(nerror); + } + while (--argc) { + argv++; + if (**argv=='-') switch ((*argv)[1]) { + case 's': + sflg++; + continue; + + case 'a': + aflg++; + continue; + + case 'i': + lp = ilist; + while (lp < &ilist[NI-1] && (n = number(argv[1]))) { + *lp++ = n; + argv++; + argc--; + } + *lp++ = -1; + continue; + + default: + printf2("Bad flag\n"); + } + check(*argv); + } + return(nerror); +} + +check(file) +char *file; +{ + register i, j, pno; + + fi = open(file, 0); + if (fi < 0) { + printf2("cannot open %s\n", file); + return; + } + printf2("%s:\n", file); + sync(); + bread(1, &sblock, 512); + nfiles = sblock.s_isize*16; + for (i=0; ii_mode&IALLOC)==0 || (ip->i_mode&IFMT)!=IFDIR) + return; + lookup(ino, 1); +} + +pass2(ip) +struct inode *ip; +{ + register doff; + register struct htab *hp; + register struct dir *dp; + int i; + + if ((ip->i_mode&IALLOC)==0 || (ip->i_mode&IFMT)!=IFDIR) + return; + doff = 0; + while (dp = dread(ip, doff)) { + doff =+ 16; + if (dp->ino==0) + continue; + if ((hp = lookup(dp->ino, 0)) == 0) + continue; + if (dotname(dp)) + continue; + hp->hpino = ino; + for (i=0; i<14; i++) + hp->hname[i] = dp->name[i]; + } +} + +pass3(ip) +struct inode *ip; +{ + register doff; + register struct dir *dp; + register int *ilp; + + if ((ip->i_mode&IALLOC)==0 || (ip->i_mode&IFMT)!=IFDIR) + return; + doff = 0; + while (dp = dread(ip, doff)) { + doff =+ 16; + if (dp->ino==0) + continue; + if (aflg==0 && dotname(dp)) + continue; + for (ilp=ilist; *ilp >= 0; ilp++) + if (*ilp == dp->ino) + break; + if (ilp > ilist && *ilp!=dp->ino) + continue; + printf("%d ", dp->ino); + pname(ino, 0); + printf("/%.14s\n", dp->name); + } +} + +dotname(adp) +{ + register struct dir *dp; + + dp = adp; + if (dp->name[0]=='.') + if (dp->name[1]==0 || dp->name[1]=='.' && dp->name[2]==0) + return(1); + return(0); +} + +pname(i, lev) +{ + register struct htab *hp; + + if (i==1) + return; + if ((hp = lookup(i, 0)) == 0) { + printf("???"); + return; + } + if (lev > 10) { + printf("..."); + return; + } + pname(hp->hpino, ++lev); + printf("/%.14s", hp->hname); +} + +lookup(i, ef) +{ + register struct htab *hp; + + for (hp = &htab[i%NDIRS]; hp->hino;) { + if (hp->hino==i) + return(hp); + if (++hp >= &htab[NDIRS]) + hp = htab; + } + if (ef==0) + return(0); + if (++nhent >= NDIRS) { + printf2("Out of core-- increase NDIRS\n"); + flush(); + exit(1); + } + hp->hino = i; + return(hp); +} + +dread(aip, aoff) +{ + register b, off; + register struct inode *ip; + static ibuf[256]; + static char buf[512]; + + off = aoff; + ip = aip; + if ((off&0777)==0) { + if (off==0177000) { + printf2("Monstrous directory %l\n", ino); + return(0); + } + if ((ip->i_mode&ILARG)==0) { + if (off>=010000 || (b = ip->i_addr[off>>9])==0) + return(0); + bread(b, buf, 512); + } else { + if (off==0) { + if (ip->i_addr[0]==0) + return(0); + bread(ip->i_addr[0], ibuf, 512); + } + if ((b = ibuf[(off>>9)&0177])==0) + return(0); + bread(b, buf, 512); + } + } + return(&buf[off&0777]); +} + +bread(bno, buf, cnt) +{ + + seek(fi, bno, 3); + if (read(fi, buf, cnt) != cnt) { + printf2("read error %d\n", bno); + exit(); + } +} + +bwrite(bno, buf) +{ + + seek(fi, bno, 3); + if (write(fi, buf, 512) != 512) { + printf2("write error %d\n", bno); + exit(); + } +} + +number(as) +char *as; +{ + register n, c; + register char *s; + + s = as; + n = 0; + while ((c = *s++) >= '0' && c <= '9') { + n = n*10+c-'0'; + } + return(n); +} + +printf2(s, a1, a2) +{ + extern fout; + + flush(); + fout = 2; + printf(s, a1, a2); + fout = nffil; + flush(); +} diff --git a/source/s2/newgrp.c b/source/s2/newgrp.c new file mode 100644 index 0000000..14ad552 --- /dev/null +++ b/source/s2/newgrp.c @@ -0,0 +1,156 @@ +int gbuf[259]; +int pbuf[259]; +int ttyb[3]; +char name[10]; +char passwd[10]; +char space[1000]; +int peek; +int pwdflg; + +main(argc, argv) +char *argv[]; +{ + register id; + register char *p, *q; + + if(argc < 2) { + printf("usage: newgrp groupname\n"); + done(); + } + if(fopen("/etc/group", gbuf) < 0) { + printf("cannot open group file\n"); + done(); + } + do { + field(name, gbuf); + p = name; + q = argv[1]; + while(*p == *q++) + if(*p++ == 0 || p >= name+8) + goto l1; + } while(skip(gbuf)); + printf("%s: not a valid group name\n", argv[1]); + done(); + +l1: + if(fopen("/etc/passwd", pbuf) < 0) { + printf("cannot open password file\n"); + done(); + } + p = space; + id = getuid() & 0377; + do { + field(p, pbuf); + field(name, pbuf); + if(value(pbuf) == id) { + if(name[0] == 0) + pwdflg++; + while(*p++) ; + } + } while(skip(pbuf)); + *p = 0; + + field(passwd, gbuf); + id = value(gbuf); + if(id == 1) { + pwdflg = 0; + goto l2; + } + do { + p = space; + field(name, gbuf); + while(*p) { + q = name; + while(*p == *q++) { + if(*p++ == 0) + goto l2; + } + while(*p++) ; + } + } while(peek == ','); + goto no; + +l2: + if(pwdflg && passwd[0]) { + printf("password: "); + gtty(0, pbuf); + pbuf[3] = pbuf[2]; + pbuf[2] =& ~010; + stty(0, pbuf); + read(0, gbuf, 512); + pbuf[2] = pbuf[3]; + stty(0, pbuf); + printf("\n"); + p = name; + q = gbuf; + while(p < name+8) { + if(*q == '\n') + break; + *p++ = *q++; + } + *p = 0; + p = crypt(name); + q = passwd; + while(q < passwd+8) + if(*p++ != *q++) + goto no; + } + if(setgid(id) < 0) { + perror("setgid"); + goto no; + } + done(); + +no: + printf("Sorry\n"); + done(); +} + +skip(buf) +{ + + while(peek > 0) { + if(peek == '\n') { + peek = 1; + return(1); + } + peek = getc(buf); + } + return(0); +} + +field(cp, buf) +{ + register c; + register char *p, *q; + + p = cp; + q = p+8; + while((c = getc(buf)) != '\n') { + if(c == ',' || c == ':' || c <= 0) + break; + if(p < q) + *p++ = c; + } + *p = 0; + peek = c; +} + +value(buf) +{ + register n, c; + + n = 0; + while((c = getc(buf)) >= '0' && c <= '9') + n = n*10 + c-'0'; + peek = c; + return(n); +} + +done() +{ + + setuid(getuid()); + execl("/bin/sh", "-", 0); + exit(); +} diff --git a/source/s2/nice.c b/source/s2/nice.c new file mode 100644 index 0000000..055fd05 --- /dev/null +++ b/source/s2/nice.c @@ -0,0 +1,40 @@ +/* nice */ +int nicarg 4; +char *args[100]; +char string[10000]; + +main(argc, argv) +int argc; +char *argv[]; +{ + int i; + register char **argp, *strp, *p; + + if(argc > 1 && argv[1][0] == '-') { + nicarg = atoi(&argv[1][1]); + argc--; + argv++; + } + if(argc < 2) { + printf("usage: nice [ -n ] command\n"); + exit(1); + } + argc--; + argv++; + argp = args; + strp = string; + for (i=0; i<9; i++) + *strp++ = "/usr/bin/"[i]; + for(i=0; i 0 && *argv[1] == '-') { + argv++; + while (*++*argv) switch (**argv) { + case 'n': + nflg++; + continue; + + case 'c': + cflg++; + continue; + + case 'g': + gflg++; + continue; + + case 'u': + uflg++; + continue; + + case 'r': + rflg = -1; + continue; + + case 'p': + pflg ++; + continue; + + default: + continue; + } + argc--; + } + if (argc==0) + fi = open("a.out", 0); else + fi = open(*++argv, 0); + if(fi < 0) { + printf("cannot open input\n"); + exit(); + } + read(fi, buf, 020); + if(buf[0]!=0407 && buf[0]!=0410 && buf[0]!=0411) { + printf("bad format\n"); + exit(); + } + seek(fi, buf[1], 1); /* text */ + seek(fi, buf[2], 1); /* data */ + if(buf[7] != 1) { + seek(fi, buf[1], 1); + seek(fi, buf[2], 1); /* reloc */ + } + n = ldiv(0, buf[4], 12); + if(n == 0) { + printf("no name list\n"); + exit(); + } + nlp = sbrk(12*n); + read(fi, nlp, n*12); + if (pflg==0) + qsort(nlp, n, 12, compare); + fout = dup(1); + close(1); + for(i=0; ityp&040)==0) + goto out; + if(cflg) { + if(nlp->name[0] != '_') + goto out; + for(j=0; j<7; j++) + nlp->name[j] = nlp->name[j+1]; + nlp->name[7] = '\0'; + } + j = nlp->typ&037; + if(j > 4) + j = 1; + if(j==0 && nlp->val) + j = 5; + if(uflg && j!=0) + goto out; + if(!uflg) { + if(j==0) + printf(" "); else + printo(nlp->val); + printf("%c ", (nlp->typ&040? "UATDBC":"uatdbc")[j]); + } + printf("%.8s\n", nlp); + out: + nlp++; + } + flush(); +} + +compare(p1, p2) +struct nl *p1, *p2; +{ + int a, i; + + a = 0; + if(nflg) { + if(p1->val > p2->val) { + a = 1; + goto out; + } + if(p1->val < p2->val) { + a = -1; + goto out; + } + } + for(i=0; i<8; i++) + if(p1->name[i] != p2->name[i]) { + if(p1->name[i] > p2->name[i]) + a = 1; else + a = -1; + goto out; + } +out: + return(a*rflg); +} + +printo(v) +{ + int i; + + printf("%c", v<0?'1':'0'); + for(i=0; i<5; i++) { + printf("%c", ((v>>12)&7)+'0'); + v =<<3; + } +} diff --git a/source/s2/nohup.c b/source/s2/nohup.c new file mode 100644 index 0000000..16db5fc --- /dev/null +++ b/source/s2/nohup.c @@ -0,0 +1,35 @@ +/* nohup */ +char *args[100]; +char string[10000]; + +main(argc, argv) +int argc; +char *argv[]; +{ + int i; + char **argp, *strp, *p; + + if(argc < 2) { + printf("arg count\n"); + exit(); + } + argc--; + argv++; + argp = args; + strp = string; + for (i=0; i<9; i++) + *strp++ = "/usr/bin/"[i]; + for(i=0; i 1) { + p = *argv; + if(*p == '-') { + while((i = *p++) != '\0') { + switch(i) { + case 'o': + conv =| 001; + f = 6; + break; + case 'd': + conv =| 002; + f = 5; + break; + case 'a': + conv =| 004; + f = 4; + break; + case 'h': + conv =| 010; + f = 4; + break; + case 'c': + conv =| 020; + f = 5; + break; + case 'b': + conv =| 040; + f = 7; + break; + } + if(f > max) + max = f; + } + argc--; + argv++; + } + } + if(!conv) { + max = 6; + conv = 1; + } + if(argc > 1) + if(**argv != '+') { + fi = open(*argv, 0); + if(fi < 0) { + printf("cannot open %s\n", *argv); + goto done; + } + argv++; + argc--; + } + if(argc > 1) + offset(*argv); + +loop: + f = 1; + a[0] = addr[0]; + a[1] = addr[1]; + for(i=0; i>8); + break; + case 040: + pre(7); + putn(n&0377, 8, 3); + putchar(' '); + putn((n>>8)&0377, 8, 3); + break; + } +} + +getw() +{ + int b1, b2; + + b1 = getc(); + if(b1 == -1) { + eof = 1; + return(0); + } + b2 = getc(); + if(b2 == -1) + b2 = 0; + return(b1|(b2<<8)); +} + +getc() +{ + + if(gidx >= gcnt) { + gcnt = read(fi, gbuf, 512); + if(gcnt <= 0) + return(-1); + gidx = 0; + } + if(++addr[1] >= basem) { + addr[0]++; + addr[1] = 0; + } + return(gbuf[gidx++]&0377); +} + +putc(c) +{ + c =& 0377; + if(c>037 && c<0177 && c!='\\') { + putchar(' '); + putchar(c); + return; + } + putchar('\\'); + switch(c) { + case '\0': + putchar('0'); + break; + case '\n': + putchar('n'); + break; + case '\\': + putchar('\\'); + break; + case '\t': + putchar('t'); + break; + default: + putchar('?'); + } +} + +putn(n, b, c) +{ + + if(!c) + return; + putn(ldiv(0,n,b),b,c-1); + if((n=lrem(0,n,b)) > 9) + putchar(n-10+'a'); else + putchar(n+'0'); +} + +pre(n) +{ + int i; + + for(i=n; i 0) + if(p[-2] == 'b') { + i--; + b++; + p--; + } + if(i > 0) + if(p[-2] == '.') { + i--; + base = 10; + basem = 1000; + } + a[0] = 0; + for(j=0; i-j>3; j++) { + d = s[j]; + if(d>='0' && d<='9') + a[0] = a[0]*base + d-'0'; + } + a[1] = 0; + for(; i-j>0; j++) { + d = s[j]; + if(d>='0' && d<='9') + a[1] = a[1]*base + d-'0'; + } + if(b) { + i = a[0]*basem+a[1]; + a[0] = 0; + a[1] = 0; + while(i--) { + a[1] =+ 512; + while(a[1] >= basem) { + a[1] =- basem; + a[0]++; + } + } + } + i = 0; + while(a[0] > addr[0]+1) { + addr[1] =+ 512; + while(addr[1] >= basem) { + addr[1] =- basem; + addr[0]++; + } + i++; + } + seek(fi, i, 3); + while(a[0]!=addr[0] || a[1]!=addr[1]) + if(getc() == -1) + break; +} + +putop(n) +{ + char *p; + int i, c; + + p = getop(n); + for(i=0; (c = *p++) != '\0'; i++) + putchar(c); + for(; i<4; i++) + putchar(' '); +} + +getop(n) +{ + + switch(n&0170000) + { + case 0000000: + switch(n&0177000) + { + case 0004000: + return("jsr"); + + case 0077000: + return("sob"); + } + switch(n&0177400) + { + case 0000400: + return("br"); + + case 0001000: + return("bne"); + + case 0001400: + return("beq"); + + case 0002000: + return("bge"); + + case 0002400: + return("blt"); + + case 0003000: + return("bgt"); + + case 0003400: + return("ble"); + } + switch(n&0177700) + { + case 0000100: + return("jmp"); + + case 0000300: + return("swab"); + + case 0005000: + return("clr"); + + case 0005100: + return("com"); + + case 0005200: + return("inc"); + + case 0005300: + return("dec"); + + case 0005400: + return("neg"); + + case 0005500: + return("adc"); + + case 0005600: + return("sbc"); + + case 0005700: + return("tst"); + + case 0006000: + return("ror"); + + case 0006100: + return("rol"); + + case 0006200: + return("asr"); + + case 0006300: + return("asl"); + + case 0006400: + return("mark"); + + case 0006500: + return("mfpi"); + + case 0006600: + return("mtpi"); + + case 0006700: + return("sxt"); + } + switch(n&0177740) + { + case 0000240: + return("flag"); + } + switch(n&0177770) + { + case 0000200: + return("rts"); + + case 0000230: + return("spl"); + } + switch(n&0177777) + { + case 0000000: + return("halt"); + + case 0000001: + return("wait"); + + case 0000002: + return("rti"); + + case 0000003: + return("bpt"); + + case 0000004: + return("iot"); + + case 0000005: + return("rset"); + + case 0000006: + return("rtt"); + } + break; + + case 0010000: + return("mov "); + + case 0020000: + return("cmp"); + + case 0030000: + return("bit"); + + case 0040000: + return("bic"); + + case 0050000: + return("bis"); + + case 0060000: + return("add"); + + case 0070000: + switch(n&0177000) + { + case 0070000: + return("mul"); + + case 0071000: + return("div"); + + case 0072000: + return("ash"); + + case 0073000: + return("ashc"); + + case 0074000: + return("xor"); + } + break; + + case 0100000: + switch(n&0177400) + { + case 0100000: + return("bpl"); + + case 0100400: + return("bmi"); + + case 0101000: + return("bhi"); + + case 0101400: + return("blos"); + + case 0102000: + return("bvc"); + + case 0102400: + return("bvs"); + + case 0103000: + return("bhis"); + + case 0103400: + return("blo"); + + case 0104000: + return("emt"); + + case 0104400: + return("sys"); + } + switch(n&0177700) + { + case 0105000: + return("clrb"); + + case 0105100: + return("comb"); + + case 0105200: + return("incb"); + + case 0105300: + return("decb"); + + case 0105400: + return("negb"); + + case 0105500: + return("adcb"); + + case 0105600: + return("sbcb"); + + case 0105700: + return("tstb"); + + case 0106000: + return("rorb"); + + case 0106100: + return("rolb"); + + case 0106200: + return("asrb"); + + case 0106300: + return("aslb"); + + case 0106500: + return("mfpd"); + + case 0106600: + return("mfpd"); + } + break; + + case 0110000: + return("movb"); + + case 0120000: + return("cmpb"); + + case 0130000: + return("bitb"); + + case 0140000: + return("bicb"); + + case 0150000: + return("bisb"); + + case 0160000: + return("sub"); + + case 0170000: + switch(n&01777000) + { + case 0:0; + } + break; + } + return("???"); +} diff --git a/source/s2/opr.c b/source/s2/opr.c new file mode 100644 index 0000000..47f368a --- /dev/null +++ b/source/s2/opr.c @@ -0,0 +1,27 @@ +/* + * opr -- off line print dispatcher + * chooses spooling routine appropriate + * to destination + * + * last entry in table isdefault + */ + +char *code[] { + "-lp", "/lib/lpr", /* line printer */ + 0 +}; + +main(argc, argv) +char **argv; +{ + int i, j; + + argv[argc] = 0; + for(i=0; code[i]; i=+2) + if(argc > 1) + for(j=0; code[i][j]==argv[1][j]; j++) + if(code[i][j] == 0) + execv(code[i+1], &argv[1]); + execv(code[i-1], argv); + write(2, "can't start daemon\n", 19); +} diff --git a/source/s2/passwd.c b/source/s2/passwd.c new file mode 100644 index 0000000..c6b20cf --- /dev/null +++ b/source/s2/passwd.c @@ -0,0 +1,151 @@ +/* + * enter a password in the password file + * this program should be suid with owner + * with an owner with write permission on /etc/passwd + */ +char *tfile { "/tmp/ptmp" }; +char *pfile { "/etc/passwd" }; +int tbuf[259]; +int pbuf[259]; + +main(argc, argv) +char *argv[]; +{ + register u, c; + register char *p; + + if(argc != 3) { + write(2, "Usage: passwd user password\n", 28); + goto bex; + } + signal(1, 1); + signal(2, 1); + signal(3, 1); + + if(stat(tfile, tbuf+20) >= 0) { + write(2, "Temporary file busy -- try again\n", 33); + goto bex; + } + tbuf[0] = creat(tfile, 0600); + if(tbuf[0] < 0) { + write(2, "Cannot create temporary file\n", 29); + goto bex; + } + pbuf[0] = open(pfile, 0); + if(pbuf[0] < 0) { + write(2, "Cannot open /etc/passwd\n", 24); + goto out; + } + goto l1; + +/* + * skip to beginning of next line + */ + +skip: + while(c != '\n') { + if(c < 0) + goto ill; + c = getc(pbuf); + putc(c, tbuf); + } + +/* + * compare user names + */ + +l1: + c = getc(pbuf); + putc(c, tbuf); + if(c < 0) { + write(2, "User name not found in password file\n", 37); + goto out; + } + p = argv[1]; + while(c != ':') { + if(*p++ != c) + goto skip; + c = getc(pbuf); + putc(c, tbuf); + } + if(*p) + goto skip; +/* + * skip old password + */ + do { + c = getc(pbuf); + if(c < 0) + goto ill; + } while(c != ':'); + +/* + * copy in new password + */ + p = argv[2]; + for(c=0; c<9; c++) + if(*p++ == 0) + break; + *--p = 0; + if(p != argv[2]) + p = crypt(argv[2]); + while(*p) + putc(*p++, tbuf); + putc(':', tbuf); + +/* + * validate uid + */ + + u = 0; + do { + c = getc(pbuf); + putc(c, tbuf); + if(c >= '0' && c <= '9') + u = u*10 + c-'0'; + if(c < 0) + goto ill; + } while(c != ':'); + c = getuid() & 0377; + if(c != 0 && c != u) { + write(2, "Permission denied\n", 18); + goto out; + } + +/* + * copy out and back + */ + + for(;;) { + c = getc(pbuf); + if(c < 0) { + fflush(tbuf); + close(pbuf[0]); + close(tbuf[0]); + tbuf[0] = open(tfile, 0); + if(tbuf[0] < 0) { + write(2, "Urk\n", 4); + goto out; + } + pbuf[0] = creat(pfile, 0644); + if(pbuf[0] < 0) { + write(2, "Cannot create /etc/passwd\n", 26); + goto out; + } + while((c = read(tbuf[0], tbuf+1, 512)) > 0) + write(pbuf[0], tbuf+1, c); + unlink(tfile); + exit(0); + } + putc(c, tbuf); + } + +ill: + write(2, "Password file illformed\n", 24); + +out: + unlink(tfile); + +bex: + exit(1); +} diff --git a/source/s2/pfe.s b/source/s2/pfe.s new file mode 100644 index 0000000..0af6d36 --- /dev/null +++ b/source/s2/pfe.s @@ -0,0 +1,44 @@ +/ print last floating error + +stst = 170300^tst + + stst r1 + cmp r1,$14 + blos 1f + clr r1 +1: + bic $1,r1 + mov mesg(r1),r1 +1: + movb (r1)+,ch + beq 1f + mov $1,r0 + sys write; ch; 1 + br 1b +1: + sys exit + +mesg: + 1f + 2f + 3f + 4f + 5f + 6f + 7f + 8f + +1: +2: +3: +4: +5: +6: +7: +8: + + .even + + .bss +ch: .=.+2 + diff --git a/source/s2/pr.c b/source/s2/pr.c new file mode 100644 index 0000000..ad5348d --- /dev/null +++ b/source/s2/pr.c @@ -0,0 +1,449 @@ +# +/* + * print file with headings + * 2+head+2+page[56]+5 + */ + +int ncol 1; +char *header; +int col; +int icol; +int file; +char *bufp; +#define BUFS 5120 +char buffer[BUFS]; +#define FF 014 +int line; +char *colp[72]; +int nofile; +char isclosed[10]; +int peekc; +int fpage; +int page; +int colw; +int nspace; +int width 72; +int length 66; +int plength 61; +int margin 10; +int ntflg; +int mflg; +int tabc; +char *tty; +int mode; + +struct inode { + int dev; + int inum; + int flags; + char nlink; + char uid; + char gid; + char siz0; + int size; + int ptr[8]; + int atime[2]; + int mtime[2]; +}; + +main(argc, argv) +char **argv; +{ + int nfdone; + int onintr(); + extern fout; + + tty = "/dev/ttyx"; + fout = dup(1); + close(1); + if ((signal(2, 1) & 01) == 0) + signal(2, onintr); + fixtty(); + for (nfdone=0; argc>1; argc--) { + argv++; + if (**argv == '-') { + switch (*++*argv) { + case 'h': + if (argc>=2) { + header = *++argv; + argc--; + } + continue; + + case 't': + ntflg++; + continue; + + case 'l': + length = getn(++*argv); + continue; + + case 'w': + width = getn(++*argv); + continue; + + case 's': + if (*++*argv) + tabc = **argv; + else + tabc = '\t'; + continue; + + case 'm': + mflg++; + continue; + + default: + ncol = getn(*argv); + continue; + } + } else if (**argv == '+') { + fpage = getn(++*argv); + } else { + print(*argv, argv); + nfdone++; + if (mflg) + break; + } + } + if (nfdone==0) + print(0); + flush(); + onintr(); +} + +onintr() +{ + + chmod(tty, mode); + exit(0); +} + +fixtty() +{ + struct inode sbuf; + extern fout; + + tty[8] = ttyn(fout); + fstat(fout, &sbuf); + mode = sbuf.flags&0777; + chmod(tty, 0600); +} + +print(fp, argp) +char *fp; +char **argp; +{ + struct inode sbuf; + register int sncol, sheader; + register char *cbuf; + extern fout; + + if (ntflg) + margin = 0; + else + margin = 10; + if (length <= margin) + length = 66; + if (width <= 0) + width = 72; + if (ncol>72 || ncol>width) { + write(2, "Very funny.\n", 12); + exit(); + } + if (mflg) { + mopen(argp); + ncol = nofile; + } + colw = width/ncol; + sncol = ncol; + sheader = header; + plength = length-5; + if (ntflg) + plength = length; + if (--ncol<0) + ncol = 0; + if (mflg) + fp = 0; + if (fp) { + file = open(fp, 0); + if (file<0) + return; + fstat(file, &sbuf); + } else { + file = 0; + time(sbuf.mtime); + } + if (header == 0) + header = fp; + cbuf = ctime(sbuf.mtime); + cbuf[16] = '\0'; + cbuf[24] = '\0'; + page = 1; + icol = 0; + colp[ncol] = bufp = buffer; + if (mflg==0) + nexbuf(); + while (mflg&&nofile || (!mflg)&&tpgetc(ncol)>0) { + if (mflg==0) { + colp[ncol]--; + if (colp[ncol] < buffer) + colp[ncol] = &buffer[BUFS]; + } + line = 0; + if (ntflg==0) { + puts("\n\n"); + puts(cbuf+4); + puts(" "); + puts(cbuf+20); + puts(" "); + puts(header); + puts(" Page "); + putd(page); + puts("\n\n\n"); + } + putpage(); + if (ntflg==0) + while(line=10) { + write(2, "Too many args.\n", 15); + exit(); + } + } +} + +putpage() +{ + register int lastcol, i, c; + int j; + + if (ncol==0) { + while (line512) + n = 512; + if ((n = read(file, rbufp, n)) <= 0) + *rbufp = 0376; + else { + rbufp =+ n; + if (rbufp >= &buffer[BUFS]) + rbufp = buffer; + *rbufp = 0375; + } + bufp = rbufp; +} + +tpgetc(ai) +{ + register char **p; + register int c, i; + + i = ai; + if (mflg) { + if ((c = getc(&buffer[2*259*i])) < 0) { + if (isclosed[i]==0) { + isclosed[i] = 1; + if (--nofile <= 0) + return(0); + } + return('\n'); + } + if (c==FF && ncol>0) + c = '\n'; + return(c); + } +loop: + c = **(p = &colp[i]) & 0377; + if (c == 0375) { + nexbuf(); + c = **p & 0377; + } + if (c == 0376) + return(0); + (*p)++; + if (*p >= &buffer[BUFS]) + *p = buffer; + if (c==0) + goto loop; + return(c); +} + +pgetc(i) +{ + register int c; + + if (peekc) { + c = peekc; + peekc = 0; + } else + c = tpgetc(i); + if (tabc) + return(c); + switch (c) { + + case '\t': + icol++; + if ((icol&07) != 0) + peekc = '\t'; + return(' '); + + case '\n': + icol = 0; + break; + + case 010: + case 033: + icol--; + break; + } + if (c >= ' ') + icol++; + return(c); +} + +puts(as) +char *as; +{ + register int c; + register char *s; + + if ((s=as)==0) + return; + while (c = *s++) + put(c); +} + +putd(an) +{ + register int a, n; + + n = an; + if (a = n/10) + putd(a); + put(n%10 + '0'); +} + +put(ac) +{ + register int ns, c; + + c = ac; + if (tabc) { + putcp(c); + if (c=='\n') + line++; + return; + } + switch (c) { + + case ' ': + nspace++; + col++; + return; + + case '\n': + col = 0; + nspace = 0; + line++; + break; + + case 010: + case 033: + if (--col<0) + col = 0; + if (--nspace<0) + nspace = 0; + + } + while(nspace) { + if (nspace>2 && col > (ns=((col-nspace)|07))) { + nspace = col-ns-1; + putcp('\t'); + } else { + nspace--; + putcp(' '); + } + } + if (c >= ' ') + col++; + putcp(c); +} + +getn(ap) +char *ap; +{ + register int n, c; + register char *p; + + p = ap; + n = 0; + while ((c = *p++) >= '0' && c <= '9') + n = n*10 + c - '0'; + return(n); +} + +putcp(c) +{ + if (page >= fpage) + putchar(c); +} diff --git a/source/s2/prof.c b/source/s2/prof.c new file mode 100644 index 0000000..490076b --- /dev/null +++ b/source/s2/prof.c @@ -0,0 +1,350 @@ +/* + * Print execution profile + */ + +struct nl { + char name[8]; + int value; + float time; + int ncall[2]; +}; + +struct nl nl[600]; + +struct fnl { + char fname[8]; + int flag; + int fvalue; +}; + +struct cnt { + int cvalue; + int cncall[2]; +} cbuf[200]; + +struct inode { + int idev; + int inum; + int flags; + char nlink; + char uid; + char gid; + char size0; + int size; + int ptr[8]; + int ctime[2]; + int mtime[2]; + int fill; +}; + +int ibuf[259]; +int obuf[259]; +int buf[17]; +int i; +int j; +int highpc; +int lowpc; +int ccnt; +int pcl; +int pch; +int bufs; +int nname; +double time; +double totime; +double maxtime; +double scale; +double lastx; +double lasty; +struct nl *np; +struct nl *npe; +int aflg; +int vflg; +int lflg; +int symoff; +int symsiz; +int vf; +int etext; +int ncount; + +main(argc, argv) +char **argv; +{ + char *namfil; + int timcmp(), valcmp(); + int nf, pf, overlap; + double fnc, ltod(), lastsx; + struct cnt *cp; + + obuf[0] = 1; + argv++; + namfil = "a.out"; + while (argc>1) { + if (**argv == '-') { + if (*++*argv == 'l') + lflg++; + if (**argv == 'a') + aflg = 040; + if(**argv == 'v') + vflg++; + } else + namfil = *argv; + argc--; + argv++; + } + if ((nf = open(namfil, 0)) < 0) { + printf("Can't find %s\n", namfil); + done(); + } + read(nf, buf, 020); + if (buf[0] != 0407 && buf[0] != 0410 && buf[0] != 0411) { /* a.out magic */ + printf("Bad format: %s\n", namfil); + done(); + } + symsiz = buf[4]; + symoff = buf[1] + buf[2]; + if (buf[7] != 1) + symoff =<< 1; + seek(nf, symoff+020, 0); + if ((pf = open("mon.out", 0)) < 0) { + printf("No mon.out\n"); + done(); + } + fstat(pf, buf); + read(pf, &lowpc, 2); + read(pf, &highpc, 2); + read(pf, &ncount, 2); + bufs = buf->size/2 - 3*(ncount+1); + read(pf, cbuf, ncount*6); + lowpc = (lowpc>>1) & 077777; + highpc = (highpc>>1) & 077777; + npe = nl; + initf(nf); + for (nname = 0; symsiz > 0; symsiz =- 12) { + for(i=0; i<12; i++) + buf->fname[i] = getc(ibuf); + if ((buf->flag | aflg) != 042) + continue; + buf->fvalue = (buf->fvalue>>1) & 077777; + npe->value = buf->fvalue; + for (i=0; i<8; i++) + npe->name[i] = buf->fname[i]; + npe++; + nname++; + } + if (nname == 0) { + printf("No symbols: %s\n", namfil); + done(); + } + npe->value = 077777; + npe++; + for (cp = cbuf; cp < &cbuf[ncount]; cp++) + for (np = nl; np < npe; np++) + if (cp->cvalue-8 == np->value<<1) { + np->ncall[0] = cp->cncall[0]; + np->ncall[1] = cp->cncall[1]; + break; + } + qsort(nl, nname, 18, &valcmp); + scale = (highpc-lowpc)/(bufs+0.0); + initf(pf); + for (i=0; (j = getc(ibuf)) != -1; i++) { + ccnt.fname[0] = j; + ccnt.fname[1] = getc(ibuf); + if (ccnt == 0) + continue; + time = ccnt; + if (ccnt<0) + time =+ 65536.; + totime =+ time; + if(time > maxtime) + maxtime = time; + pcl = lowpc + scale*i - 1; + pch = lowpc + scale*(i+1) - 1; + for (j=0; j= nl[j+1].value) + continue; + overlap=(min(pch,nl[j+1].value)-max(pcl,nl[j].value)); + nl[j].time =+ overlap*time/scale; + } + } + if (totime==0.0) { + printf("No time accumulated\n"); + done(); + } + if(!vflg) + goto print; + vf = open("/dev/vt0", 1); + if(vf < 0) { + printf("Cannot open vt\n"); + done(); + } + obuf[0] = vf; + vtch(1); + vtch(1); + vtch(3); + point(-2048., -2048.); + point(-2048., 2048.); + vtch(3); + point(0., -2048.); + point(0., 2048.); + for(j=0; j<9; j++) { + vtch(3); + point(-2048., 2048. - j*512.); + point(0., 2048. - j*512.); + } + lastx = 0.; + lasty = 2048.; + scale = 4096./(i+2); + seek(pf, 6*(ncount+1), 0); + initf(pf); + lastsx = 0.0; + while((j = getc(ibuf)) != -1) { + ccnt.fname[0] = j; + ccnt.fname[1] = getc(ibuf); + time = ccnt; + if(ccnt < 0) + time =+ 65536.; + vtch(3); + point(lastsx, lasty); + lastsx =- 2000.*time/totime; + point(lastsx, lasty-scale); + if (ccnt!=0 || lastx!=0.0) { + vtch(3); + point(lastx, lasty); + lastx = -time*2000./maxtime; + point(lastx, lasty); + } + lasty =- scale; + } + scale = 4096./(highpc-lowpc); + lastx = 50.; + for(np = nl; npvalue < lowpc) + continue; + if(np->value >= highpc) + continue; + time = np->time/totime; + lasty = 2048. - (np->value - lowpc)*scale; + vtch(3); + point(0., lasty); + point(50., lasty); + vtch(3); + point(lastx-50., lasty); + point(lastx, lasty); + vtch(9); + point(lastx+10., lasty+60.); + vtch(1); + vtch(3); + for(j=0; j<8; j++) + if(np->name[j] != '_') + vtch(np->name[j]); + vtch(0); + lastx =+ 500.; + if(lastx > 2000.) + lastx = 50.; + } + done(); + +print: + printf(" name %%time #call ms/call\n"); + if (!lflg) + qsort(nl, nname, 18, &timcmp); + for (np = nl; nptime/totime; + printf("%8.8s%6.1f", np->name, 100*time); + fnc = ltod(np->ncall); + if (fnc != 0.0) { + printf("%6s", locv(np->ncall[0], np->ncall[1])); + printf(" %7.2f\n", np->time/(fnc*.06)); + } else + printf("\n"); + } + done(); +} + +min(a, b) +{ + if (ab) + return(a); + return(b); +} + +valcmp(p1, p2) +struct nl *p1, *p2; +{ + return(p1->value - p2->value); +} + +timcmp(p1, p2) +struct nl *p1, *p2; +{ + float d; + + d = p2->time - p1->time; + if (d > 0.0) + return(1); + if (d < 0.0) + return(-1); + return(0); +} + +vtch(c) +int c; +{ + + putchar(c&0377); +} + +point(x, y) +float x, y; +{ + + point1(x); + point1(y); +} + +putchar(c) +{ + + putc(c, obuf); +} + +point1(xy) +float xy; +{ + int ixy; + struct { char b1; char b2;}; + + if(xy > 2047.) + xy = 2047.; + if(xy < -2048.) + xy = -2048.; + ixy = xy; + vtch(ixy.b1); + vtch(ixy.b2); +} + +done() +{ + + fflush(obuf); + exit(); +} + +initf(f) +{ + + ibuf[0] = f; + ibuf[1] = 0; + ibuf[2] = 0; + ibuf[3] = 0; +} diff --git a/source/s2/ps.c b/source/s2/ps.c new file mode 100644 index 0000000..3825cb4 --- /dev/null +++ b/source/s2/ps.c @@ -0,0 +1,292 @@ +# + +/* + * ps - process status + * examine and print certain things about processes + */ + +#include "/usr/sys/param.h" +#include "/usr/sys/proc.h" +#include "/usr/sys/tty.h" +#include "/usr/sys/user.h" + +struct { + char name[8]; + int type; + char *value; +} nl[3]; + +struct proc proc[NPROC]; +struct tty tty; +struct user u; +int lflg; +int kflg; +int xflg; +int tflg; +int aflg; +int mem; +int swap; + +int stbuf[257]; +int ndev; +char devc[65]; +int devl[65]; +int devt[65]; +char *coref; +struct ibuf { + char idevmin, idevmaj; + int inum; + int iflags; + char inl; + char iuid; + char igid; + char isize0; + int isize; + int iaddr[8]; + char *ictime[2]; + char *imtime[2]; + int fill; +}; +int obuf[259]; + + +main(argc, argv) +char **argv; +{ + struct proc *p; + int n, b; + int i, c, mtty; + char *ap; + int uid, puid; + + obuf[0] = 1; + if (argc>1) { + ap = argv[1]; + while (*ap) switch (*ap++) { + case 'a': + aflg++; + break; + + case 't': + tflg++; + break; + + case 'x': + xflg++; + break; + + case 'l': + lflg++; + break; + + case 'k': + kflg++; + break; + + } + } + + if(chdir("/dev") < 0) { + printf("cannot change to /dev\n"); + done(); + } + setup(&nl[0], "_proc"); + setup(&nl[1], "_swapdev"); + nlist(argc>2? argv[2]:"/unix", nl); + if (nl[0].type==0) { + printf("No namelist\n"); + return; + } + coref = "/dev/mem"; + if(kflg) + coref = "/usr/sys/core"; + if ((mem = open(coref, 0)) < 0) { + printf("No mem\n"); + done(); + } + seek(mem, nl[1].value, 0); + read(mem, &nl[1].value, 2); + seek(mem, nl[0].value, 0); + read(mem, proc, sizeof proc); + getdev(); + mtty = ttyn(0); + uid = getuid() & 0377; + if(lflg) + printf("TTY F S UID PID PRI ADDR SZ WCHAN COMMAND\n"); else + printf("TTY PID COMMAND\n"); + for (i=0; i>3); + if (proc[i].p_wchan) + printf("%7o", proc[i].p_wchan); else + printf(" "); + } + if (proc[i].p_stat==5) + printf(" "); + else + prcom(i); + printf("\n"); + } + done(); +} + +getdev() +{ + register struct { int dir_ino; char dir_n[14]; } *p; + register i, c; + int f; + char dbuf[512]; + int sbuf[20]; + + f = open("/dev"); + if(f < 0) { + printf("cannot open /dev\n"); + done(); + } + swap = -1; + c = 0; + +loop: + i = read(f, dbuf, 512); + if(i <= 0) { + close(f); + if(swap < 0) { + printf("no swap device\n"); + done(); + } + ndev = c; + return; + } + while(i < 512) + dbuf[i++] = 0; + for(p = dbuf; p < dbuf+512; p++) { + if(p->dir_ino == 0) + continue; + if(p->dir_n[0] == 't' && + p->dir_n[1] == 't' && + p->dir_n[2] == 'y' && + p->dir_n[4] == 0 && + p->dir_n[3] != 0) { + if(stat(p->dir_n, sbuf) < 0) + continue; + devc[c] = p->dir_n[3]; + devl[c] = sbuf->iaddr[0]; + c++; + continue; + } + if(swap >= 0) + continue; + if(stat(p->dir_n, sbuf) < 0) + continue; + if((sbuf->iflags & 060000) != 060000) + continue; + if(sbuf->iaddr[0] == nl[1].value) + swap = open(p->dir_n, 0); + } + goto loop; +} + +setup(p, s) +char *p, *s; +{ + while (*p++ = *s++); +} + +prcom(i) +{ + int baddr, laddr, mf; + register int *ip; + register char *cp, *cp1; + int c, nbad; + + baddr = 0; + laddr = 0; + if (proc[i].p_flag&SLOAD) { + laddr = proc[i].p_addr; + mf = mem; + } else { + baddr = proc[i].p_addr; + mf = swap; + } + laddr =+ proc[i].p_size - 8; + baddr =+ laddr>>3; + laddr = (laddr&07)<<6; + seek(mf, baddr, 3); + seek(mf, laddr, 1); + if (read(mf, stbuf, 512) != 512) + return(0); + for (ip = &stbuf[256]; ip > &stbuf[0];) { + if (*--ip == -1) { + cp = ip+1; + if (*cp==0) + cp++; + nbad = 0; + for (cp1 = cp; cp1 < &stbuf[256]; cp1++) { + c = *cp1; + if (c==0) + *cp1 = ' '; + else if (c < ' ' || c > 0176) { + if (++nbad >= 5) { + *cp1++ = ' '; + break; + } + *cp1 = '?'; + } + } + while (*--cp1==' ') + *cp1 = 0; + printf(lflg?" %.16s":" %.64s", cp); + return(1); + } + } + return(0); +} + +done() +{ + + fflush(obuf); + exit(); +} + +putchar(c) +{ + + putc(c, obuf); +} diff --git a/source/s2/ptx.c b/source/s2/ptx.c new file mode 100644 index 0000000..87cd0cd --- /dev/null +++ b/source/s2/ptx.c @@ -0,0 +1,222 @@ +/* permuted title index */ + +char *tfil "/tmp/p.tmp"; +char *sw[] { + "a", + "an", + "and", + "as", + "for", + "is", + "of", + "on", + "or", + "the", + "to", + "up", + 0}; +char line[200]; +int ch; +int ptflg; +int llen 72; + +main(argc, argv) +int argc; +char *argv[]; +{ + extern fin, fout; + extern onintr(); + int f; + + if(argc>1 && *argv[1]=='-') { + llen = 100; + ptflg++; + argc--; + argv++; + } + if(argc<2) { + printf("arg count\n"); + exit(); + } + fin = open(argv[1]); + if(fin < 0) { + printf("%s: cannot open\n", argv[1]); + exit(); + } + f = creat(tfil, 0600); + if(f < 0) { + printf("cannot create %s\n", tfil); + exit(); + } + fout = f; + if ((signal(2, 1) & 01) ==0) + signal(2, onintr); + pass1(); + flush(); + close(fin); + fin = 0; + close(fout); + fout = 1; + f = fork(); + if(f < 0) { + printf("try again\n"); + exit(); + } + if(f == 0) { + execl("/bin/sort", "sort", "-d", "-o", tfil, tfil, 0); + execl("/usr/bin/sort", "sort", "-d", "-o", tfil, tfil, 0); + printf("someone moved sort\n"); + exit(); + } + while(wait() != f); + fin = open(tfil, 0); + if(fin < 0) { + printf("cannot reopen %s\n", tfil); + exit(); + } + if (argc>=3) + f = creat(argv[2], 0666); + else + f = dup(1); + if(f < 0) { + printf("%s: cannot open\n", argv[2]); + exit(); + } + fout = f; + pass2(); + flush(); + onintr(); +} + +onintr() +{ + unlink(tfil); + exit(); +} + +pass1() +{ + int n, c, i, ll, j, k, cc, ccc; + +loop: + if ((c=getchar())=='\0') + return; + n = 0; + i = 0; + while(c!='\n' && c!='\0') { + if(c == '(') + c = 0177; + if(c==' ' || c=='\t') { + i++; + c = getchar(); + continue; + } + if(i) { + i = 0; + if(n<=llen) line[n++] = ' '; + } + if (n<=llen) line[n++] = c; + c = getchar(); + } + ll = n; + line[n++] = 0; + i = -1; +l1: + while((cc=line[++i])==' '); + n = i; + j = 0; + while(sw[j]) { + i = n; + k = 0; + while ((cc=sw[j][k++])==line[i++]); + if(cc==0 && ((ccc=line[--i])==' '||ccc==0)) + goto l1; + j++; + } + i = n; + while (c=line[n++]) putchar(c); + putchar('~'); + n = 0; + while (n=0) nafter++; else nbfore++; + n++; + c = getchar(); + } + if (tilde<0) + tilde = n++; + nafter--; + if (nbfore>llen2) { + i = tilde; + while (nbfore > llen2) + while(line[--i]!=' ' && i>=0) nbfore--; + if (i<0) goto l1; + line[tilde] = 0200; + nafter =+ (tilde-i+2); + tilde = i; + } + if (nafter >= llen-llen2) { + i = tilde; + while(nafter-- >= llen-llen2) + while(line[++i]!=' ' && i=n) goto l1; + line[tilde] = 0200; + nafter++; + tilde = i; + } +l1: + if(!ptflg) { + for(i=llen-llen2-nafter; i>=8; i =- 8) + putchar('\t'); + while(--i>=0) + putchar(' '); + } else + printf(".xx \""); + i = tilde; + while (++i 511) prname(); + for(j=off+1; j>=0; --j) name[j+i+1] = name[j]; + off=i+off+1; + name[i] = root[0]; + for(--i; i>=0; --i) name[i] = y.name[i]; +} diff --git a/source/s2/quiz.c b/source/s2/quiz.c new file mode 100644 index 0000000..6c4119b --- /dev/null +++ b/source/s2/quiz.c @@ -0,0 +1,460 @@ +#define NF 10 +#define NL 200 +#define NC 200 +#define SL 100 +#define NA 10 + +int tflag; +int xx[NL]; +char score[NL]; +int rights; +int wrongs; +int guesses; +int buf[259]; +int nl 0; +int na NA; +int inc; +int ptr 0; +int nc 0; +char line[150]; +char response[100]; +char *tmp[NF]; +int select[NF]; + +readline() +{ + char *t; +loop: + for(t=line;(*t=getc(buf))!=-1;t++) { + nc++; + if(*t==' '&&(t==line||t[-1]==' ')) + t--; + if(*t=='\n') { + if(t[-1]=='\\') /*inexact test*/ + continue; + while(t>line&&t[-1]==' ') + *--t = '\n'; + *++t = 0; + return(1); + } + if(t-line>=NC) { + printf("Too hard for me\n"); + do { + *line = getc(buf); + if(*line==0377) + return(0); + } while(*line!='\n'); + goto loop; + } + } + return(0); +} + +char *eu; +char *ev; +cmp(u,v) +{ + int x; + eu = u; + ev = v; + x = disj(1); + if(x!=1) + return(x); + return(eat(1,0)); +} + +disj(s) +{ + int t, x; + char *u; + u = eu; + t = 0; + for(;;) { + x = string(s); + if(x>1) + return(x); + switch(*ev) { + case 0: + case ']': + case '}': + return(t|x&s); + case '|': + ev++; + t =| s; + s = 0; + continue; + } + if(s) eu = u; + if(string(0)>1) + return(2); + switch(*ev) { + case 0: + case ']': + return(0); + case '}': + return(1); + case '|': + ev++; + continue; + default: + return(2); + } + } +} + +string(s) +{ + int x; + for(;;) { + switch(*ev) { + case 0: + case '|': + case ']': + case '}': + return(1); + case '\\': + ev++; + if(*ev==0) + return(2); + if(*ev=='\n') { + ev++; + continue; + } + default: + if(eat(s,*ev)==1) + continue; + return(0); + case '[': + ev++; + x = disj(s); + if(*ev!=']' || x>1) + return(2); + ev++; + if(s==0) + continue; + if(x==0) + return(0); + continue; + case '{': + ev++; + x = disj(s); + if(*ev!='}'||x>1) + return(2); + ev++; + continue; + } + } +} + +eat(s,c) +char c; +{ + if(*ev!=c) + return(2); + if(s==0) { + ev++; + return(1); + } + if(fold(*eu)!=fold(c)) + return(0); + eu++; + ev++; + return(1); +} + +fold(c) +char c; +{ + if(c<'A'||c>'Z') + return(c); + return(c|040); +} + +publish(t) +char *t; +{ + ev = t; + pub1(1); +} + +pub1(s) +{ + for(;;ev++){ + switch(*ev) { + case '|': + s = 0; + ev; + continue; + case ']': + case '}': + case 0: + return; + case '[': + case '{': + ev++; + pub1(s); + ev; + continue; + case '\\': + if(*++ev=='\n') + continue; + default: + if(s) + putchar(*ev); + } + } +} + +segment(u,w) +char *u, *w[]; +{ + char *s; + int i; + char *t; + s = u; + for(i=0;i1) badinfo(); + if(x==0) + continue; + p[i] = j; + goto uloop; + } + return(0); +uloop: ; + } + return(1); +} + +find(u,m) +char *u[]; +{ + int n; + while(readline()){ + n = segment(line,tmp); + if(perm(u,m,tmp+1,n-1,select)) + return(1); + } + return(0); +} + +readindex() +{ + xx[0] = nc = 0; + while(readline()) { + xx[++nl] = nc; + if(nl>=NL) { + printf("I've forgotten some of it\n"); + break; + } + } +} + +talloc() +{ + int i; + for(i=0;i1&&*argv[1]=='-') { + switch(argv[1][1]) { + case 'i': + if(argc>2) + info = argv[2]; + argc =- 2; + argv =+ 2; + goto loop; + case 't': + tflag = 1; + argc--; + argv++; + goto loop; + } + } + if(fopen(info,buf)== -1) { + printf("No info\n"); + exit(); + } + talloc(); + if(argc<=2) + instruct(info); + signal(2,done); + argv[argc] = 0; + if(find(&argv[1],argc-1)==0) + dunno(); + close(buf[0]); + if(fopen(tmp[0],buf)== -1) + dunno(); + readindex(); + if(!tflag || na>nl) + na = nl; + for(;;) { + i = next(); + seek(buf[0],xx[i],0); + read(buf[0],line,xx[i+1]-xx[i]); + segment(line,tmp); + if(*tmp[select[0]] == '\0' || *tmp[select[1]] == '\0') { + score[i] = 1; + continue; + } + publish(tmp[select[0]]); + printf("\n"); + for(count=0;;count++) { + if(query(response)==0) { + publish(tmp[select[1]]); + printf("\n"); + if(count==0) wrongs++; + score[i] = tflag?-1:1; + break; + } + x = cmp(response,tmp[select[1]]); + if(x>1) badinfo(); + if(x==1) { + printf("Right!\n"); + if(count==0) rights++; + if(++score[i]>=1 && nar&&t[-1]==' ') + *--t = '\n'; + break; + } + } + *t = 0; + return(t-r); +} + +next() +{ + int flag; + inc = inc*3125&077777; + ptr = (inc>>2)%na; + flag = 0; + while(score[ptr]>0) + if(++ptr>=na) { + ptr = 0; + if(flag) done(); + flag = 1; + } + return(ptr); +} + +done() +{ + printf("\nRights %d, wrongs %d, ", rights, wrongs); + if(guesses) + printf("extra guesses %d, ", guesses); + printf("score %d%%\n",100*rights/(rights+wrongs)); + exit(); +} +instruct(info) +{ + char *t; + int i, n; + printf("Subjects:\n\n"); + while(readline()) { + printf("-"); + n = segment(line,tmp); + for(i=1;i>8) & 0377; + if( t ) + return(++cflag); + splitup(); + nerr=0; + for(i=0; i2 && *s++=='.') + return(*s); + return(0); +} + +setsuf(s, ch) +char s[]; +{ + char *os; + + os = s; + while(*s++); + s[-2] = ch; + return(os); +} + +move(s,t) char *s, *t; { + cunlink(t); + if(link(s, t) || cunlink(s)) { + printf("move failed: %s\n", t); + return(1); + } + return(0); +} + +callsys(f, v) +char f[], *v[]; { + int i, t, status; + + if(dflag){ + for(i=0; v[i]; i++) + printf("%s ", v[i]); + putchar('\n'); + } + if ((t=fork())==0) { + execv(f, v); + printf("Can't find %s\n", f); + exit(1); + } else + if (t == -1) { + printf("Try again\n"); + return(1); + } + while(t!=wait(&status)); + if ((t=(status&0377)) != 0 && t!=14) { + if (t!=2) /* interrupt */ + printf("Fatal error in %s\n", f); + dexit(); + } + t = (status>>8) & 0377; + if(dflag && status != 0) + printf("status = %d\n", t); + return(t); +} + +copy(s) +char s[]; { + char *otsp; + + otsp = tsp; + while(*tsp++ = *s++); + return(otsp); +} + +nodup(l, s) +char **l, s[]; { + char *t, *os, c; + + if (getsuf(s) != 'o') + return(1); + os = s; + while(t = *l++) { + s = os; + while(c = *s++) + if (c != *t++) + break; + if (*t++ == '\0') + return(0); + } + return(1); +} + +llenter(t) char *t; { + if (nodup(llist, t)) { + llist[nl++] = t; + if (getsuf(t)=='o') + nxo++; + } +} + +cunlink(f) +char *f; +{ + if( dflag ) + printf("unlink %s\n", f); + if (f==0) + return(0); + return(unlink(f)); +} + +splitup(){ + char in[200], fname[20]; + int buf[259]; + int i,fd,c; + if( (fin=open("ratjunk", 0)) < 0) + error("can't open ratjunk\n"); + while( gets(in) ){ + getname(in, fname); + savename(fname); + if( (fd = fcreat(fname, buf)) < 0) + error("can't open %s", fname); + puts(in,buf); + while( ! endcard(in) ){ + gets(in); + puts(in,buf); + } + fflush(buf); + close(fd); + } + close(fin); +} + +gets(s) char *s; { + int c; + while( (*s++=c=getchar()) != '\n' && c != '\0' ); + *s = '\0'; + return(c); +} + +puts(s,b) char *s; int *b; { + while( *s ) + putc(*s++, b); +} + +savename(s) char *s; { + rlist[nr++] = copy(s); +} + +getname(s,f) char *s,*f; { + int i,j,c; + loop: + while( *s == ' ' || *s == '\t' ) + s++; + if( compar(s,"subroutine") ){ s =+ 10; goto bot; } + else if( compar( s,"function") ){ s =+ 8; goto bot; } + else if( compar(s,"real") ){ s =+ 4; goto loop; } + else if( compar(s,"integer") ){ s =+ 7; goto loop; } + else if( compar(s,"logical") ){ s =+ 7; goto loop; } + else if( compar(s,"double") ){ s =+ 6; goto loop; } + else if( compar(s,"precision") ){ s =+ 9; goto loop; } + else if( compar(s,"complex") ){ s =+ 7; goto loop; } + else if( compar(s,"block") ){ + s = "blockdata "; + s[9] = (bdcount++) + '0'; + goto bot; + } + else { + for(i=0; f[i]="MAIN.f"[i]; i++); + return; + } + bot: + while( *s == ' ' || *s == '\t' ) + s++; + for(i=0; alphanum(s[i]); i++) + f[i] = s[i]; + f[i++] = '.'; + f[i++] = 'f'; + f[i++] = '\0'; +} + +compar(s,t) char *s,*t; { + while( *t ) + if( *s++ != *t++ ) + return(0); + return(1); +} + +alphanum(c) int c; { + return( (c>='a' && c<='z') + || (c>='A' && c<='Z') + || (c>='0' && c<='9') ); +} + +endcard(s) char *s; { + if( *s==0 ) + return(1); + while( *s==' ' || *s=='\t' ) + s++; + if( *s!='e' || *(s+1)!='n' || *(s+2)!='d' || *(s+3)!='\n' ) + return(0); + return(1); +} + +error(s1, s2){ + fout = 1; + printf(s1,s2); + putchar('\n'); + flush(1); + cflag++; +} diff --git a/source/s2/restor.c b/source/s2/restor.c new file mode 100644 index 0000000..6e9febe --- /dev/null +++ b/source/s2/restor.c @@ -0,0 +1,552 @@ +# + +/* + * restore from incremental dumps + */ + +char *dargv[] +{ + 0, + "t", + 0 +}; +char *ifile; +char *ofile; +#include "/usr/sys/ino.h" +#include "/usr/sys/filsys.h" + +struct filsys sblock; +int isize; +int *talist; +int fi; +int buf[256]; +int dbuf[256]; +int cbuf[256]; +char *date[2]; +char *ddate[2]; +int fo; +int pher; +char *tsize 15000; +int iflg; +int wflg; +int cflg; +char file[10]; +int ilist[100]; + +main(argc, argv) +char **argv; +{ + char *key; + register *tap, *p; + register struct inode *ip; + int i, com, sz, *q, l; + + ifile = "/dev/mt0"; + if(argc == 1) { + argv = dargv; + for(argc = 1; dargv[argc]; argc++); + } + + argc--; + argv++; + key = *argv; + while(*key) + switch(*key++) { + default: + printf("bad character in key\n"); + exit(); + + case 't': + case 'r': + case 'x': + com = key[-1]; + continue; + + case 'i': + iflg++; + continue; + + case '-': + continue; + + case 'c': + cflg++; + continue; + + case 'f': + argv++; + argc--; + ifile = *argv; + continue; + + case 'w': + wflg++; + continue; + + } + otape(); + sread(buf, 0); + tap = buf; + isize = *tap++; + *tap++; /* fsize */ + date[0] = *tap++; + date[1] = *tap++; + ddate[0] = *tap++; + ddate[1] = *tap++; + tsize = *tap++; + i = size(0, isize*32); + talist = sbrk(i*512); + tap = talist; + while(i--) { + tread(tap, 0); + tap =+ 256; + } + switch(com) { + +case 't': + l = 0; + com = 0; + pdate(ddate); + pdate(date); + tap = talist; + for(i=0; i 60) { + printf("\n"); + l = 0; + } else + printf(","); + com = 0; + } else + if(com == 0) + com = i+1; + } + if(com) + printf("%l-\n", com); + printf("\n"); + exit(); + +case 'r': + if(argc <= 1) { + printf("no filesystem name\n"); + exit(); + } + ofile = argv[1]; + fo = open(ofile, 2); + if(fo < 0) { + printf("can not open %s\n", ofile); + exit(); + } + printf("last chance before scribbling on %s\n", ofile); + getchar(); + dread(1, &sblock); + tap = talist; + for(i=0; i= isize) + break; + dread(i+2, buf); + for(ip = &buf[0]; ip < &buf[256]; ip++) { + sz = *tap++; + if(sz == 0) + continue; + dealoc(ip); + if(sz == -1) { + for(p = ip; p < &ip->i_mtime[2]; ) + *p++ = 0; + continue; + } + sread(dbuf, 0); + q = dbuf; + for(p = ip; p < &ip->i_mtime[2]; ) + *p++ = *q++; + restor(ip, sz-1); + } + dwrite(i+2, buf); + } + dwrite(1, &sblock); + com = 0; + for(; i < isize; i++) + for(l = 0; l < 16; l++) { + sz = *tap++; + if(sz != 0 && sz != -1) + com++; + } + if(com) + printf("%l files not restored - small ilist\n", com); + exit(); + +case 'x': + i = 0; + tap = ilist; + while(argc > 1) { + i++; + sz = number(argv[1]); + argv++; + argc--; + if(sz <= 0 || sz >=isize*16) { + printf("%l not in range\n", sz); + continue; + } + if(talist[sz-1] == 0) { + printf("%l not dumped\n", sz); + continue; + } + if(talist[sz-1] == -1) { + printf("%l does not exist\n", sz); + continue; + } + *tap++ = sz; + } + if(i != 0 && ilist[0] == 0) + exit(); + tap = talist; + for(i=1; i<=isize*16; i++) { + if(ilist[0] != 0) { + for(sz=0; ilist[sz]; sz++) + if(ilist[sz] == i) + goto yes; + sz = *tap++; + no: + if(sz == -1) + sz = 0; + while(sz--) + tread(dbuf, 1); + continue; + } + yes: + sz = *tap++; + if(sz == 0 || sz == -1) + continue; + fo = dwait(i); + if(fo < 0) + goto no; + sz--; + sread(buf, 0); + ip = buf; + while(sz--) { + tread(dbuf, 0); + com = 512; + if(ip->i_size0 == 0 && ip->i_size1 < 512) + com = ip->i_size1; + write(fo, dbuf, com); + if(com > ip->i_size1) + ip->i_size0--; + ip->i_size1 =- com; + } + close(fo); + chmod(file, ip->i_mode); + chown(file, ip->i_uid); + } + exit(); + + } +} + +dealoc(p) +struct inode *p; +{ + register struct inode *ip; + register i, j; + int k; + int xbuf[256], ybuf[256]; + + ip = p; + if(ip->i_mode & (IFCHR&IFBLK)) + return; + for(i=7; i>=0; i--) + if(ip->i_addr[i]) { + if(ip->i_mode&ILARG) { + dread(ip->i_addr[i], xbuf); + for(j=255; j>=0; j--) + if(xbuf[j]) { + if(i == 7) { + dread(xbuf[j], ybuf); + for(k=255; k>=0; k--) + if(ybuf[k]) + free(ybuf[k]); + } + free(xbuf[j]); + } + } + free(ip->i_addr[i]); + } +} + +restor(p, sz) +struct inode *p; +{ + register struct inode *ip; + register i, j; + int xbuf[256]; + + ip = p; + if(ip->i_mode & (IFCHR&IFBLK)) + return; + for(i=0; i<8; i++) + ip->i_addr[i] = 0; + if(sz <= 8) { + for(i=0; ii_addr[i] = rcop(); + ip->i_mode =& ~ILARG; + return; + } + for(i=0; i<256; i++) + xbuf[i] = 0; + for(j=0; sz >= 256; j++) { + if(j <= 7) + ip->i_addr[j] = alloc(); + if(j >= 7) + xbuf[j-7] = alloc(); + for(i=0; i<256; i++) + dbuf[i] = rcop(); + if(j < 7) + dwrite(ip->i_addr[j], dbuf); else + dwrite(xbuf[j-7], dbuf); + sz =- 256; + } + if(sz) { + if(j <= 7) + ip->i_addr[j] = alloc(); + if(j >= 7) + xbuf[j-7] = alloc(); + for(i=0; ii_addr[j], dbuf); else + dwrite(xbuf[j-7], dbuf); + } + if(j >= 7) + dwrite(ip->i_addr[7], xbuf); + ip->i_mode =| ILARG; +} + +rcop() +{ + register b; + + b = alloc(); + tread(cbuf, 0); + dwrite(b, cbuf); + return(b); +} + +pdate(d) +int *d; +{ + + if(d[0] == 0 && d[1] == 0) + printf("the epoch\n"); else + printf(ctime(d)); +} + +dread(bno, b) +{ + + seek(fo, bno, 3); + if(read(fo, b, 512) != 512) { + printf("disk read error %l\n", bno); + exit(); + } +} + +dwrite(bno, b) +{ + + seek(fo, bno, 3); + if(write(fo, b, 512) != 512) { + printf("disk write error %l\n", bno); + exit(); + } +} + +sread(b, flag) +int *b; +{ + register i, s, *p; + + tread(b, flag); + if(flag) + return; + i = 256; + s = 0; + p = b; + while(i--) + s =+ *p++; + if(s != 031415) { + printf("checksum error\n"); + if(!iflg) + exit(); + } +} + +tread(b, flag) +int *b; +{ + register c; + static char *pta, *ata, ctflg; + + if(pta++ >= tsize) { + pta = 1; + ata = 0; + close(fi); + otape(); + ctflg++; + } + if(flag) + return; + if(ctflg) { + printf("change tapes\n"); + if(ctflg > 1) + printf("skip %d tapes\n", ctflg-1); + while((c = getchar()) != '\n') + if(c == 0) + exit(); + ctflg = 0; + } + ata++; + if(iflg) + for(; pta != ata; ata++) + read(fi, b, 512); + if(pta != ata) { + seek(fi, pta-ata, 4); + ata = pta; + } + if(read(fi, b, 512) != 512) { + printf("tape read error %l\n", ata-1); + if(!iflg) + exit(); + for(c=0; c<256; c++) + b[c] = 0; + } +} + +number(s) +char *s; +{ + register n, c; + + n = 0; + while(c = *s++) { + if(c<'0' || c>'9') + continue; + n = n*10+c-'0'; + } + return(n); +} + +size(s0, s1) +{ + register s; + extern ldivr; + + s = ldiv(s0&0377, s1, 512); + if(ldivr) + s++; + return(s); +} + +otape() +{ + register char *p; + + fi = open(ifile, 0); + if(fi < 0) { + printf("can not open %s\n", ifile); + exit(); + } + if(!cflg) + return; + p = ifile; + while(*p++) + ; + p[-2]++; +} + +dwait(ino) +{ + register i; + + dconv(ino, file); +loop: + if(wflg) { + printf("%s ", file); + i = getchar(); + if(i == 'x') + exit(); + if(i == '\n') + return(-1); + if(i != 'y') + goto flush; + i = getchar(); + if(i != '\n') { + flush: + while((i=getchar()) != '\n') + if(i == '\0') + exit(); + goto loop; + } + } + i = creat(file, 0666); + return(i); +} + +dconv(n, p) +char *p; +{ + register i; + + if(i = ldiv(0, n, 10)) + p = dconv(i, p); + *p++ = lrem(0, n, 10) + '0'; + *p = '\0'; + return(p); +} + +alloc() +{ + register b, i; + + i = --sblock.s_nfree; + if(i<0 || i>=100) { + printf("bad freeblock\n"); + exit(); + } + b = sblock.s_free[i]; + if(b == 0) { + printf("out of freelist\n"); + exit(); + } + if(sblock.s_nfree <= 0) { + dread(b, cbuf); + sblock.s_nfree = cbuf[0]; + for(i=0; i<100; i++) + sblock.s_free[i] = cbuf[i+1]; + } + return(b); +} + +free(in) +{ + register i; + + if(sblock.s_nfree >= 100) { + cbuf[0] = sblock.s_nfree; + for(i=0; i<100; i++) + cbuf[i+1] = sblock.s_free[i]; + sblock.s_nfree = 0; + dwrite(in, cbuf); + } + sblock.s_free[sblock.s_nfree++] = in; +} diff --git a/source/s2/rew.s b/source/s2/rew.s new file mode 100644 index 0000000..efeedd2 --- /dev/null +++ b/source/s2/rew.s @@ -0,0 +1,47 @@ +/ rew -- rewind dec/mag tape + + cmp (sp)+,$2 + blt 1f + tst (sp)+ + mov (sp)+,r0 + movb (r0)+,r1 + cmp r1,$'m + beq rewm + movb r1,tapx+8 + tstb (r0) + bne error +1: + sys open; tapx; 0 + br rew + +rewm: + movb (r0)+,r1 + beq 1f + movb r1,mtx+7 + tstb (r0) + bne error +1: + sys open; mtx; 0 + +rew: + bes error + sys read; word; 2 + bes error + sys exit + +error: + mov $1,r0 + sys write; 0f; 2 + sys exit +0: + + +tapx: + +mtx: + + .even + +.bss +word: .=.+2 + diff --git a/source/s2/rm.c b/source/s2/rm.c new file mode 100644 index 0000000..d4447a1 --- /dev/null +++ b/source/s2/rm.c @@ -0,0 +1,107 @@ +main(argc, argv) +char *argv[]; +{ + char *arg; + int fflg, rflg; + + fflg = 0; + rflg = 0; + while(--argc > 0) { + + arg = *++argv; + if(arg[0] == '-') { + if(arg[1] == 'f') { + fflg++; + continue; + } + if(arg[1] == 'r') { + rflg++; + continue; + } + } + + rm(arg, fflg, rflg); + } +} + +struct stbuf { + int dev; + int inum; + int mode; + char nlink; + char uid; + char gid; + char siz0; + char siz1; + int addr[8]; + int adate[2]; + int mdate[2]; + }; + +rm(arg, fflg, rflg) +char arg[]; +{ + char *p; + int buf[20]; + int i, b; + + if(stat(arg, buf)) { + printf("%s: non existent\n", arg); + return; + } + if((buf->mode & 060000) == 040000) { + if(rflg) { + i = fork(); + if(i == -1) { + printf("%s: try again\n", arg); + return; + } + if(i) { + while(wait() != i); + return; + } + if(chdir(arg)) { + printf("%s: cannot chdir\n", arg); + exit(); + } + p = 0; + execl("/etc/glob", "glob", "rm", "-r", + fflg? "-f": "*", fflg? "*": p, 0); + printf("%s: no glob\n", arg); + exit(); + } + printf("%s: directory\n", arg); + return; + } + + if(!fflg) { + + if((getuid()&0377) == buf->uid) + b = 0200; else + b = 2; + if((buf->mode & b) == 0 && ttyn(0) != 'x') { + printf("%s: %o mode ", arg, buf->mode); + i = b = getchar(); + i = b; + while(b != '\n' && b != '\0') + b = getchar(); + if(i != 'y') + return; + } + } + if(unlink(arg)) + printf("%s: not removed\n", arg); +} + +putchar(c) +{ + write(1, &c, 1); +} + +getchar() +{ + char c; + + if(read(0, &c, 1) != 1) return(0); + return(c); +} diff --git a/source/s2/rmdir.s b/source/s2/rmdir.s new file mode 100644 index 0000000..75180d3 --- /dev/null +++ b/source/s2/rmdir.s @@ -0,0 +1,106 @@ +/ rmdir -- unlink directory + + mov (sp)+,r5 + tst (sp)+ + +loop: + dec r5 + ble done + mov (sp)+,r1 + mov $name,r2 + clr r0 +1: + inc r0 + movb (r1)+,(r2)+ + bne 1b + dec r2 + dec r0 + mov r0,size + cmp r2,$name + beq error + sys stat; name; stbuf + bes error + bic $!60000,stbuf+4 + cmp $40000,stbuf+4 + bne error + cmpb -1(r2),$'. + bne 1f + cmp r2,$name+1 + beq error + cmpb -2(r2),$'/ + beq error + cmpb -2(r2),$'. + bne 1f + cmp r2,$name+2 + beq error + cmpb -3(r2),$'/ + beq error +1: + sys open; name; 0 + bes error + mov r0,r1 +1: + mov r1,r0 + sys read; stbuf; 16. + bes 1f + tst r0 + beq 1f + tst stbuf + beq 1b + cmpb stbuf+2,$'. + bne error1 + tstb stbuf+3 + beq 1b + cmpb stbuf+3,$'. + bne error1 + tstb stbuf+4 + beq 1b + +error1: + jsr pc,prname + mov r1,r0 + sys close + mov $1,r0 + sys write; mes1; emes1-mes1 + br loop + +1: + mov r1,r0 + sys close + movb $'/,(r2)+ + movb $'.,(r2)+ + movb $'.,(r2)+ + clrb (r2) + sys unlink; name + clrb -(r2) + sys unlink; name + clrb -2(r2) + sys unlink; name + br loop + +error: + jsr pc,prname + mov $1,r0 + sys write; mes2; emes2-mes2 + br loop + +prname: + mov $1,r0 + sys write; name; size:.. + rts pc + +done: + sys exit + +mes1: + < -- directory not empty\n> +emes1: +mes2: + < ?\n> +emes2: + .even + +.bss +name: .=.+40. +stbuf: .=.+40. + diff --git a/source/s2/run b/source/s2/run new file mode 100644 index 0000000..5b56bd2 --- /dev/null +++ b/source/s2/run @@ -0,0 +1,228 @@ +cc -s -O mail.c +cmp a.out /bin/mail +cp a.out /bin/mail + +cc -s -O mesg.c +cmp a.out /usr/bin/mesg +cp a.out /usr/bin/mesg + +as mkdir.s +strip a.out +cmp a.out /bin/mkdir +cp a.out /bin/mkdir + +cc -s -O mkfs.c +cmp a.out /etc/mkfs +cp a.out /etc/mkfs + +cc -s -O mknod.c +cmp a.out /etc/mknod +cp a.out /etc/mknod + +cc -s -O mount.c +cmp a.out /etc/mount +cp a.out /etc/mount + +cc -s -O mv.c +cmp a.out /bin/mv +cp a.out /bin/mv + +cc -s -O ncheck.c +cmp a.out /bin/ncheck +cp a.out /bin/ncheck + +cc -s -O newgrp.c +cmp a.out /bin/newgrp +cp a.out /bin/newgrp + +cc -s -O nice.c +cmp a.out /usr/bin/nice +cp a.out /usr/bin/nice + +cc -s -O nm.c +cmp a.out /bin/nm +cp a.out /bin/nm + +cc -s -O nohup.c +cmp a.out /usr/bin/nohup +cp a.out /usr/bin/nohup + +cc -s -O od.c +cmp a.out /bin/od +cp a.out /bin/od + +cc -s -O opr.c +cmp a.out /bin/opr +cp a.out /bin/opr + +cc -s -O passwd.c +cmp a.out /bin/passwd +cp a.out /bin/passwd + +as pfe.s +strip a.out +cmp a.out /usr/bin/pfe +cp a.out /usr/bin/pfe + +cc -s -O pr.c +cmp a.out /bin/pr +cp a.out /bin/pr + +cc -s -f -O prof.c +cmp a.out /usr/bin/prof +cp a.out /usr/bin/prof + +cc -s -O ps.c +cmp a.out /bin/ps +cp a.out /bin/ps + +cc -s -O ptx.c +cmp a.out /usr/bin/ptx +cp a.out /usr/bin/ptx + +cc -s -O pwd.c +cmp a.out /usr/bin/pwd +cp a.out /usr/bin/pwd + +cc -s -O quiz.c +cmp a.out /usr/bin/quiz +cp a.out /usr/bin/quiz + +cc -s -O rc.c +cmp a.out /usr/bin/rc +cp a.out /usr/bin/rc + +cc -s -O restor.c +cmp a.out /bin/restor +cp a.out /bin/restor + +as rew.s +strip a.out +cmp a.out /bin/rew +cp a.out /bin/rew + +cc -s -O rm.c +cmp a.out /bin/rm +cp a.out /bin/rm + +as rmdir.s +strip a.out +cmp a.out /bin/rmdir +cp a.out /bin/rmdir + +cc -s -f -O sa.c +cmp a.out /usr/bin/sa +cp a.out /usr/bin/sa + +cc -s -n -O sh.c +cmp a.out /bin/sh +cp a.out /bin/sh + +cc -s -O size.c +cmp a.out /bin/size +cp a.out /bin/size + +cc -s -O sleep.c +cmp a.out /usr/bin/sleep +cp a.out /usr/bin/sleep + +cc -s -O sort.c +cmp a.out /bin/sort +cp a.out /bin/sort + +cc -s -O split.c +cmp a.out /usr/bin/split +cp a.out /usr/bin/split + +as strip.s +strip a.out +cmp a.out /bin/strip +cp a.out /bin/strip + +cc -s -O stty.c +cmp a.out /bin/stty +cp a.out /bin/stty + +cc -s -O su.c +cmp a.out /bin/su +cp a.out /bin/su + +as sum.s +strip a.out +cmp a.out /bin/sum +cp a.out /bin/sum + +cc -s -O sync.c +cmp a.out /bin/sync +cp a.out /bin/sync + +cc -s -O tbl.c -lp +cmp a.out /usr/bin/tbl +cp a.out /usr/bin/tbl + +cc -s -O tee.c +cmp a.out /usr/bin/tee +cp a.out /usr/bin/tee + +as time.s +strip a.out +cmp a.out /bin/time +cp a.out /bin/time + +as tp?.s +ld a.out -lc -l +cmp a.out /bin/tp +cp a.out /bin/tp + +cc -s -O tr.c +cmp a.out /usr/bin/tr +cp a.out /usr/bin/tr + +as tty.s +ld -s a.out -l +cmp a.out /bin/tty +cp a.out /bin/tty + +cc -s -f -O typo.c +cmp a.out /usr/bin/typo +cp a.out /usr/bin/typo + +cc -s -O umount.c +cmp a.out /etc/umount +cp a.out /etc/umount + +cc -s -O uniq.c +cmp a.out /bin/uniq +cp a.out /bin/uniq + +cc -s -f -O units.c +cmp a.out /usr/bin/units +cp a.out /usr/bin/units + +as update.s +strip a.out +cmp a.out /etc/update +cp a.out /etc/update + +cc -s -O usort.c +cmp a.out /usr/bin/usort +cp a.out /usr/bin/usort + +cc -s -O wall.c +cmp a.out /etc/wall +cp a.out /etc/wall + +cc -s -O wc.c +cmp a.out /usr/bin/wc +cp a.out /usr/bin/wc + +cc -s -O who.c +cmp a.out /bin/who +cp a.out /bin/who + +as write.s +ld -s a.out -l +cmp a.out /bin/write +cp a.out /bin/write + +rm a.out diff --git a/source/s2/sa.c b/source/s2/sa.c new file mode 100644 index 0000000..c18508b --- /dev/null +++ b/source/s2/sa.c @@ -0,0 +1,470 @@ +#define size 2000 +/* interpret command time accounting */ + +int lflg; +int cflg; +int jflg; +int nflg; +int aflg; +int rflg; +int tflg; +int vflg; +int uflg; +int thres 1; +int sflg; +int bflg; +int mflg; +int fout; + +struct user { + int ncomm; + int fill; + float fctime; +} user[256]; +struct tab { + char name[8]; + int count; + float realt; + float cput; + float syst; +} tab[size]; + +struct ftab { + char fname[14]; + char shf; + char uid; + int fdatet[2]; + int frealt[2]; + int fcput[2]; + int fsyst[2]; +}; +float treal; +float tcpu; +float tsys; +int junkp -1; +char *sname; +float ncom; + +main(argc, argv) +char **argv; +{ + int i, j, k; + extern tcmp(), ncmp(), bcmp(); + extern float sum(); + float ft; + + init(); + if (argc>1) + if (argv[1][0]=='-') { + argv++; + argc--; + for(i=1; argv[0][i]; i++) + switch(argv[0][i]) { + + case 'b': + bflg++; + break; + + case 'l': + lflg++; + break; + + case 'c': + cflg++; + break; + + case 'j': + jflg++; + break; + + case 'n': + nflg++; + break; + + case 'a': + aflg++; + break; + + case 'r': + rflg++; + break; + + case 't': + tflg++; + break; + + case 's': + sflg++; + aflg++; + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + thres = argv[0][i]-'0'; + break; + + case 'v': + vflg++; + break; + + case 'u': + uflg++; + break; + + case 'm': + mflg++; + break; + } + } + fout = dup(1); + if (argc<2) + acct("/usr/adm/sha"); + else while (--argc) + acct(*++argv); + if (uflg) { + flush(); + return; + } + +/* + * cleanup pass + * put junk together + */ + + if (vflg) + strip(); + if(!aflg) + for (i=0; i= 0200)) + *cp = '?'; + } + if (uflg) { + printdate(fbuf.fdatet); + printf(" %3d %.8s\n", fbuf.uid, fbuf.name); + continue; + } + if (fbuf.shf==0) { + c = fbuf.uid&0377; + user[c].ncomm++; + user[c].fctime =+ (ltod(fbuf.fcput)+ltod(fbuf.fsyst))/60; + } + ncom =+ 1.0; + i = enter(&fbuf); + tab[i].count++; + x = ltod(fbuf.frealt); + x =* 60.; + tab[i].realt =+ x; + treal =+ x; + x = ltod(fbuf.fcput); + tab[i].cput =+ x; + tcpu =+ x; + x = ltod(fbuf.fsyst); + tab[i].syst =+ x; + tsys =+ x; + } + close(ff); +} + +ncmp(p1, p2) +struct tab *p1, *p2; +{ + + if(p1->count == p2->count) + return(tcmp(p1, p2)); + if(rflg) + return(p1->count - p2->count); + return(p2->count - p1->count); +} + +bcmp(p1, p2) +struct tab *p1, *p2; +{ + float f1, f2; + float sum(); + + f1 = sum(p1)/p1->count; + f2 = sum(p2)/p2->count; + if(f1 < f2) { + if(rflg) + return(-1); + return(1); + } + if(f1 > f2) { + if(rflg) + return(1); + return(-1); + } + return(0); +} +tcmp(p1, p2) +struct tab *p1, *p2; +{ + extern float sum(); + float f1, f2; + + f1 = sum(p1); + f2 = sum(p2); + if(f1 < f2) { + if(rflg) + return(-1); + return(1); + } + if(f1 > f2) { + if(rflg) + return(1); + return(-1); + } + return(0); +} + +float sum(p) +struct tab *p; +{ + + if(p->name[0] == 0) + return(0.0); + return( + p->cput+ + p->syst); +} + +init() +{ + struct tab tbuf; + int i, j, f; + + if ((f=open("/usr/adm/sht", 0))<0) + goto gshm; + while (read(f, &tbuf, sizeof(tbuf)) == sizeof(tbuf)) { + i = enter(&tbuf); + ncom =+ tbuf.count; + tab[i].count = tbuf.count; + treal =+ tbuf.realt; + tab[i].realt = tbuf.realt; + tcpu =+ tbuf.cput; + tab[i].cput = tbuf.cput; + tsys =+ tbuf.syst; + tab[i].syst = tbuf.syst; + } + close(f); + gshm: + if ((f=open("/usr/adm/shm", 0)) < 0) + return; + read(f, user, sizeof(user)); + close(f); +} + +enter(fbuf) +struct ftab *fbuf; +{ + int i, j; + + i = 0; + for (j=0; j<8; j++) { + i = i*7 + fbuf->fname[j]; + } + if(i < 0) + i = -i; + for (i=%size; tab[i].name[0]; i = (i+1)%size) { + for (j=0; j<8; j++) + if (tab[i].name[j]!=fbuf->fname[j]) + goto no; + goto yes; + no:; + } + for (j=0; j<8; j++) + tab[i].name[j] = fbuf->fname[j]; +yes: + return(i); +} + +strip() +{ + int i, j, k, c; + + j = enter("**junk**"); + for (i = 0; i=0; f--) { + dolc = ldiv(0, dolc, 10); + pidp[f] = ldivr+'0'; + } + v = av; + acname = "/usr/adm/sha"; + promp = "% "; + if(((uid = getuid())&0377) == 0) + promp = "# "; + acctf = open(acname, 1); + if(c > 1) { + promp = 0; + if (*v[1]=='-') { + **v = '-'; + if (v[1][1]=='c' && c>2) + arginp = v[2]; + else if (v[1][1]=='t') + onelflg = 2; + } else { + close(0); + f = open(v[1], 0); + if(f < 0) { + prs(v[1]); + err(": cannot open"); + } + } + } + if(**v == '-') { + setintr++; + signal(QUIT, 1); + signal(INTR, 1); + } + dolv = v+1; + dolc = c-1; + +loop: + if(promp != 0) + prs(promp); + peekc = getc(); + main1(); + goto loop; +} + +main1() +{ + register char c, *cp; + register *t; + + argp = args; + eargp = args+ARGSIZ-5; + linep = line; + elinep = line+LINSIZ-5; + error = 0; + gflg = 0; + do { + cp = linep; + word(); + } while(*cp != '\n'); + treep = trebuf; + treeend = &trebuf[TRESIZ]; + if(gflg == 0) { + if(error == 0) { + setexit(); + if (error) + return; + t = syntax(args, argp); + } + if(error != 0) + err("syntax error"); else + execute(t); + } +} + +word() +{ + register char c, c1; + + *argp++ = linep; + +loop: + switch(c = getc()) { + + case ' ': + case '\t': + goto loop; + + case '\'': + case '"': + c1 = c; + while((c=readc()) != c1) { + if(c == '\n') { + error++; + peekc = c; + return; + } + *linep++ = c|QUOTE; + } + goto pack; + + case '&': + case ';': + case '<': + case '>': + case '(': + case ')': + case '|': + case '^': + case '\n': + *linep++ = c; + *linep++ = '\0'; + return; + } + + peekc = c; + +pack: + for(;;) { + c = getc(); + if(any(c, " '\"\t;&<>()|^\n")) { + peekc = c; + if(any(c, "\"'")) + goto loop; + *linep++ = '\0'; + return; + } + *linep++ = c; + } +} + +tree(n) +int n; +{ + register *t; + + t = treep; + treep =+ n; + if (treep>treeend) { + prs("Command line overflow\n"); + error++; + reset(); + } + return(t); +} + +getc() +{ + register char c; + + if(peekc) { + c = peekc; + peekc = 0; + return(c); + } + if(argp > eargp) { + argp =- 10; + while((c=getc()) != '\n'); + argp =+ 10; + err("Too many args"); + gflg++; + return(c); + } + if(linep > elinep) { + linep =- 10; + while((c=getc()) != '\n'); + linep =+ 10; + err("Too many characters"); + gflg++; + return(c); + } +getd: + if(dolp) { + c = *dolp++; + if(c != '\0') + return(c); + dolp = 0; + } + c = readc(); + if(c == '\\') { + c = readc(); + if(c == '\n') + return(' '); + return(c|QUOTE); + } + if(c == '$') { + c = readc(); + if(c>='0' && c<='9') { + if(c-'0' < dolc) + dolp = dolv[c-'0']; + goto getd; + } + if(c == '$') { + dolp = pidp; + goto getd; + } + } + return(c&0177); +} + +readc() +{ + char cc; + register c; + + if (arginp) { + if (arginp == 1) + exit(); + if ((c = *arginp++) == 0) { + arginp = 1; + c = '\n'; + } + return(c); + } + if (onelflg==1) + exit(); + if(read(0, &cc, 1) != 1) + exit(); + if (cc=='\n' && onelflg) + onelflg--; + return(cc); +} + +/* + * syntax + * empty + * syn1 + */ + +syntax(p1, p2) +char **p1, **p2; +{ + + while(p1 != p2) { + if(any(**p1, ";&\n")) + p1++; else + return(syn1(p1, p2)); + } + return(0); +} + +/* + * syn1 + * syn2 + * syn2 & syntax + * syn2 ; syntax + */ + +syn1(p1, p2) +char **p1, **p2; +{ + register char **p; + register *t, *t1; + int l; + + l = 0; + for(p=p1; p!=p2; p++) + switch(**p) { + + case '(': + l++; + continue; + + case ')': + l--; + if(l < 0) + error++; + continue; + + case '&': + case ';': + case '\n': + if(l == 0) { + l = **p; + t = tree(4); + t[DTYP] = TLST; + t[DLEF] = syn2(p1, p); + t[DFLG] = 0; + if(l == '&') { + t1 = t[DLEF]; + t1[DFLG] =| FAND|FPRS|FINT; + } + t[DRIT] = syntax(p+1, p2); + return(t); + } + } + if(l == 0) + return(syn2(p1, p2)); + error++; +} + +/* + * syn2 + * syn3 + * syn3 | syn2 + */ + +syn2(p1, p2) +char **p1, **p2; +{ + register char **p; + register int l, *t; + + l = 0; + for(p=p1; p!=p2; p++) + switch(**p) { + + case '(': + l++; + continue; + + case ')': + l--; + continue; + + case '|': + case '^': + if(l == 0) { + t = tree(4); + t[DTYP] = TFIL; + t[DLEF] = syn3(p1, p); + t[DRIT] = syn2(p+1, p2); + t[DFLG] = 0; + return(t); + } + } + return(syn3(p1, p2)); +} + +/* + * syn3 + * ( syn1 ) [ < in ] [ > out ] + * word word* [ < in ] [ > out ] + */ + +syn3(p1, p2) +char **p1, **p2; +{ + register char **p; + char **lp, **rp; + register *t; + int n, l, i, o, c, flg; + + flg = 0; + if(**p2 == ')') + flg =| FPAR; + lp = 0; + rp = 0; + i = 0; + o = 0; + n = 0; + l = 0; + for(p=p1; p!=p2; p++) + switch(c = **p) { + + case '(': + if(l == 0) { + if(lp != 0) + error++; + lp = p+1; + } + l++; + continue; + + case ')': + l--; + if(l == 0) + rp = p; + continue; + + case '>': + p++; + if(p!=p2 && **p=='>') + flg =| FCAT; else + p--; + + case '<': + if(l == 0) { + p++; + if(p == p2) { + error++; + p--; + } + if(any(**p, "<>(")) + error++; + if(c == '<') { + if(i != 0) + error++; + i = *p; + continue; + } + if(o != 0) + error++; + o = *p; + } + continue; + + default: + if(l == 0) + p1[n++] = *p; + } + if(lp != 0) { + if(n != 0) + error++; + t = tree(5); + t[DTYP] = TPAR; + t[DSPR] = syn1(lp, rp); + goto out; + } + if(n == 0) + error++; + p1[n++] = 0; + t = tree(n+5); + t[DTYP] = TCOM; + for(l=0; l= 0) { + seek(i, 0, 2); + goto f1; + } + } + i = creat(t[DRIT], 0666); + if(i < 0) { + prs(t[DRIT]); + err(": cannot create"); + exit(); + } + f1: + close(1); + dup(i); + close(i); + } + if((f&FPIN) != 0) { + close(0); + dup(pf1[0]); + close(pf1[0]); + close(pf1[1]); + } + if((f&FPOU) != 0) { + close(1); + dup(pf2[1]); + close(pf2[0]); + close(pf2[1]); + } + if((f&FINT)!=0 && t[DLEF]==0 && (f&FPIN)==0) { + close(0); + open("/dev/null", 0); + } + if((f&FINT) == 0 && setintr) { + signal(INTR, 0); + signal(QUIT, 0); + } + if(t[DTYP] == TPAR) { + if(t1 = t[DSPR]) + t1[DFLG] =| f&FINT; + execute(t1); + exit(); + } + close(acctf); + gflg = 0; + scan(t, &tglob); + if(gflg) { + t[DSPR] = "/etc/glob"; + execv(t[DSPR], t+DSPR); + prs("glob: cannot execute\n"); + exit(); + } + scan(t, &trim); + *linep = 0; + texec(t[DCOM], t); + cp1 = linep; + cp2 = "/usr/bin/"; + while(*cp1 = *cp2++) + cp1++; + cp2 = t[DCOM]; + while(*cp1++ = *cp2++); + texec(linep+4, t); + texec(linep, t); + prs(t[DCOM]); + err(": not found"); + exit(); + + case TFIL: + f = t[DFLG]; + pipe(pv); + t1 = t[DLEF]; + t1[DFLG] =| FPOU | (f&(FPIN|FINT|FPRS)); + execute(t1, pf1, pv); + t1 = t[DRIT]; + t1[DFLG] =| FPIN | (f&(FPOU|FINT|FAND|FPRS)); + execute(t1, pv, pf2); + return; + + case TLST: + f = t[DFLG]&FINT; + if(t1 = t[DLEF]) + t1[DFLG] =| f; + execute(t1); + if(t1 = t[DRIT]) + t1[DFLG] =| f; + execute(t1); + return; + + } +} + +texec(f, at) +int *at; +{ + extern errno; + register int *t; + + t = at; + execv(f, t+DCOM); + if (errno==ENOEXEC) { + if (*linep) + t[DCOM] = linep; + t[DSPR] = "/bin/sh"; + execv(t[DSPR], t+DSPR); + prs("No shell!\n"); + exit(); + } + if (errno==ENOMEM) { + prs(t[DCOM]); + err(": too large"); + exit(); + } +} + +err(s) +char *s; +{ + + prs(s); + prs("\n"); + if(promp == 0) { + seek(0, 0, 2); + exit(); + } +} + +prs(as) +char *as; +{ + register char *s; + + s = as; + while(*s) + putc(*s++); +} + +putc(c) +{ + + write(2, &c, 1); +} + +prn(n) +int n; +{ + register a; + + if(a=ldiv(0,n,10)) + prn(a); + putc(lrem(0,n,10)+'0'); +} + +any(c, as) +int c; +char *as; +{ + register char *s; + + s = as; + while(*s) + if(*s++ == c) + return(1); + return(0); +} + +equal(as1, as2) +char *as1, *as2; +{ + register char *s1, *s2; + + s1 = as1; + s2 = as2; + while(*s1++ == *s2) + if(*s2++ == '\0') + return(1); + return(0); +} + +pwait(i, t) +int i, *t; +{ + register p, e; + int s; + + if(i != 0) + for(;;) { + times(&timeb); + time(timeb.proct); + p = wait(&s); + if(p == -1) + break; + e = s&0177; + if(mesg[e] != 0) { + if(p != i) { + prn(p); + prs(": "); + } + prs(mesg[e]); + if(s&0200) + prs(" -- Core dumped"); + } + if(e != 0) + err(""); + if(i == p) { + acct(t); + break; + } else + acct(0); + } +} + +acct(t) +int *t; +{ + if(t == 0) + enacct("**gok"); else + if(*t == TPAR) + enacct("()"); else + enacct(t[DCOM]); +} + +enacct(as) +char *as; +{ + struct stime timbuf; + struct { + char cname[14]; + char shf; + char uid; + int datet[2]; + int realt[2]; + int bcput[2]; + int bsyst[2]; + } tbuf; + register i; + register char *np, *s; + + s = as; + times(&timbuf); + time(timbuf.proct); + lsub(tbuf.realt, timbuf.proct, timeb.proct); + lsub(tbuf.bcput, timbuf.cputim, timeb.cputim); + lsub(tbuf.bsyst, timbuf.systim, timeb.systim); + do { + np = s; + while (*s != '\0' && *s != '/') + s++; + } while (*s++ != '\0'); + for (i=0; i<14; i++) { + tbuf.cname[i] = *np; + if (*np) + np++; + } + tbuf.datet[0] = timbuf.proct[0]; + tbuf.datet[1] = timbuf.proct[1]; + tbuf.uid = uid; + tbuf.shf = 0; + if (promp==0) + tbuf.shf = 1; + seek(acctf, 0, 2); + write(acctf, &tbuf, sizeof(tbuf)); +} diff --git a/source/s2/size.c b/source/s2/size.c new file mode 100644 index 0000000..c49b3e1 --- /dev/null +++ b/source/s2/size.c @@ -0,0 +1,36 @@ +/* + size -- determine object size + +*/ + +main(argc, argv) +char **argv; +{ + int buf[010], f, ac, sum; + + ac = argc; + if (ac==1) { + *argv = "a.out"; + ac++; + --argv; + } + while(--ac) { + ++argv; + if((f=open(*argv, 0))<0) { + printf("%s not found\n", *argv); + continue; + } + read(f, buf, 0020); + if(buf[0]!=0411 && buf[0]!=0410 && buf[0]!=0407) { + printf("Bad format: %s\n", *argv); + close(f); + continue; + } + if (argc>2) + printf("%s: ", *argv); + printf("%l+%l+%l=", buf[1],buf[2],buf[3]); + sum = buf[1]+buf[2]+buf[3]; + printf("%l (%o)\n", sum, sum); + close(f); + } +} diff --git a/source/s2/sleep.c b/source/s2/sleep.c new file mode 100644 index 0000000..54b77ff --- /dev/null +++ b/source/s2/sleep.c @@ -0,0 +1,21 @@ +main(argc, argv) +char **argv; +{ + int c, n; + char *s; + + n = 0; + if(argc < 2) { + printf("arg count\n"); + exit(); + } + s = argv[1]; + while(c = *s++) { + if(c<'0' || c>'9') { + printf("bad character\n"); + exit(); + } + n = n*10 + c - '0'; + } + sleep(n); +} diff --git a/source/s2/sort.c b/source/s2/sort.c new file mode 100644 index 0000000..8652945 --- /dev/null +++ b/source/s2/sort.c @@ -0,0 +1,592 @@ +#define L 512 +#define N 7 +#define C 20 +#define MEM (16*2048) +#define NF 10 + +int ibuf[259]; +int obuf[259]; +char *file; +char *filep; +int nfiles; +int nlines; +int ntext; +int *lspace; +char *tspace; +int cmp(); +int term(); +int mflg; +char *outfil; +char tabchar; +int eargc; +char **eargv; + +char fold[128] { + 0000,0001,0002,0003,0004,0005,0006,0007, + 0010,0011,0012,0013,0014,0015,0016,0017, + 0020,0021,0022,0023,0024,0025,0026,0027, + 0030,0031,0032,0033,0034,0035,0036,0037, + 0040,0041,0042,0043,0044,0045,0046,0047, + 0050,0051,0052,0053,0054,0055,0056,0057, + 0060,0061,0062,0063,0064,0065,0066,0067, + 0070,0071,0072,0073,0074,0075,0076,0077, + 0100,0101,0102,0103,0104,0105,0106,0107, + 0110,0111,0112,0113,0114,0115,0116,0117, + 0120,0121,0122,0123,0124,0125,0126,0127, + 0130,0131,0132,0133,0134,0134,0136,0137, + 0140,0101,0102,0103,0104,0105,0106,0107, + 0110,0111,0112,0113,0114,0115,0116,0117, + 0120,0121,0122,0123,0124,0125,0126,0127, + 0130,0131,0132,0173,0174,0175,0176,0177 +}; +char nofold[128]; +char dict[128] { + 1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1 +}; +char nodict[128] { 1 }; + +struct field { + char *code; + char *ignore; + int nflg; + int rflg; + int bflg; + char *m[2]; + char *n[2]; +} fields[NF]; +int proto[9] { + &fold, + &nodict, + 0, + 1, + 0, + 0,-1, + 0,0 +}; +int nfields; +int error 1; + +main(argc, argv) +char **argv; +{ + register a, i; + char *arg; + register int *p; + int *q; + + for(a=0; a<128; a++) + nofold[a] = a; + nodict[127] = 1; + copyproto(); + eargv = argv; + while (--argc > 0) { + if(**++argv == '-') for(arg = *argv;;) { + switch(*++arg) { + case '\0': + if(arg[-1] == '-') + eargv[eargc++] = "-"; + break; + + case 'm': + mflg++; + continue; + + case 'o': + if(--argc > 0) + outfil = *++argv; + continue; + + default: + field(++*argv,1); + break; + } + break; + } else if (**argv == '+') { + if(++nfields>=NF) { + mess("Too many keys\n"); + exit(1); + } + copyproto(); + field(++*argv,0); + } else + eargv[eargc++] = *argv; + } + q = &fields[0]; + for(a=1; a<=nfields; a++) { + p = &fields[a]; + for(i=0; i<5; i++) /*sensitive to sizeof(proto)*/ + if(p[i] != proto[i]) + goto next; + for(i=0; i<5; i++) + p[i] = q[i]; +next: ; + } + if(eargc == 0) + eargv[eargc++] = "-"; + + a = MEM; + i = lspace = sbrk(0); + while(brk(a) == -1) + a =- 512; + brk(a =- 512); /* for recursion */ + a =- i; + nlines = ((a-L)>>1) & 077777; + nlines =/ 5; + ntext = nlines*8; + tspace = lspace+nlines; + file = "/usr/tmp/stmXaa"; +loop: + filep = file; + while(*filep != 'X') + filep++; + for(*filep = 'a';;(*filep)++) { + if(stat(file, lspace) < 0) { + a = creat(file, 0600); + if(a >= 0) + break; + } + if(*filep == 'z') { + if(file[1] != 't') { + file = "/tmp/stmXaa"; + goto loop; + } + mess("Cannot locate temp\n"); + exit(1); + } + } + close(a); + filep++; + if ((signal(2, 1) & 01) == 0) + signal(2, term); + nfiles = eargc; + if(!mflg) { + ibuf[0] = -1; + sort(); + close(0); + } + for(a = mflg?0:eargc; a+N < nfiles; a=+N) { + newfile(); + merge(a, a+N); + } + if(a != nfiles) { + oldfile(); + merge(a, nfiles); + } + error = 0; + term(); +} + +sort() +{ + register char *cp; + register *lp, c; + int done; + int i; + int f; + + done = 0; + i = 0; + do { + cp = tspace; + lp = lspace; + while(lp < lspace+nlines && cp < tspace+ntext) { + *lp++ = cp; + while((*cp++ = c = getc(ibuf)) != '\n') { + if(c >= 0) continue; + cp--; + close(ibuf[0]); + if(i < eargc) { + if((f = setfil(i++)) == 0) + ibuf[0] = 0; + else if(fopen(f, ibuf) < 0) + cant(f); + } else + break; + } + if(c < 0) { + done++; + lp--; + break; + } + } + qsort(lspace, lp-lspace, 2, cmp); + if(done == 0 || nfiles != eargc) + newfile(); else + oldfile(); + while(lp > lspace) { + cp = *--lp; + do + putc(*cp, obuf); + while(*cp++ != '\n'); + } + fflush(obuf); + close(obuf[0]); + } while(done == 0); +} + +struct merg +{ + char l[L]; + int b[259]; +}; + +merge(a, b) +{ + register struct merg *p; + register char *cp; + register i; + struct { int *ip;}; + int f; + int j; + + p = lspace; + j = 0; + for(i=a; ib[0] = dup(0); + else if(fopen(f, p->b) < 0) + cant(f); + ibuf[j] = p; + if(!rline(p)) j++; + p++; + } + i = j; + qsort(ibuf, i, 2, cmp); + if(i > 0) for(;;) { + cp = ibuf[i-1]; + do + putc(*cp, obuf); + while(*cp++ != '\n'); + if(rline(ibuf[i-1])) { + i--; + if(i == 0) + break; + } + cp = &ibuf[i]; + while (--cp.ip > ibuf && cmp(cp.ip, cp.ip-1) < 0) { + p = *cp.ip; + *cp.ip = *(cp.ip-1); + *(cp.ip-1) = p; + } + } + p = lspace; + for(i=a; ib[0]); + p++; + if(i >= eargc) + close(creat(setfil(i))); + } + fflush(obuf); + close(obuf[0]); +} + +rline(mp) +struct merg *mp; +{ + register char *cp; + register *bp, c; + + bp = mp->b; + cp = mp->l; + do { + c = getc(bp); + if(c < 0) + return(1); + *cp++ = c; + } while(c != '\n'); + return(0); +} + +newfile() +{ + + if(fcreat(setfil(nfiles), obuf) < 0) { + mess("Can't create temp\n"); + term(); + } + nfiles++; +} + +char * +setfil(i) +{ + + if(i < eargc) + if(eargv[i][0] == '-' && eargv[i][1] == '\0') + return(0); + else + return(eargv[i]); + i =- eargc; + filep[0] = i/26 + 'a'; + filep[1] = i%26 + 'a'; + return(file); +} + +oldfile() +{ + + if(outfil) { + if(fcreat(outfil, obuf) < 0) { + mess("Can't create output\n"); + term(); + } + } else + obuf[0] = 1; +} + +cant(f) +{ + mess("Can't open "); + mess(f); + mess("\n"); + term(); +} + +term() +{ + register i; + + if(nfiles == eargc) + nfiles++; + for(i=eargc; i0; k<=nfields; k++) { + fp = &fields[k]; + pa = *i; + pb = *j; + if(k) { + la = skip(pa, fp, 1); + pa = skip(pa, fp, 0); + lb = skip(pb, fp, 1); + pb = skip(pb, fp, 0); + } else { + la = -1; + lb = -1; + } + if(fp->nflg) { + while(blank(*pa)) + pa++; + while(blank(*pb)) + pb++; + sa = sb = fp->rflg; + if(*pa == '-') { + pa++; + sa = -sa; + } + if(*pb == '-') { + pb++; + sb = -sb; + } + if(sa != sb) + sa = 0; + for(ipa = pa; ipa pa && ipb > pb) + if(b = *--ipb - *--ipa) + a = b; + while(ipa > pa) + if(*--ipa != '0') + return(sa ? -sa : sb); + while(ipb > pb) + if(*--ipb != '0') + return(sa ? sa : sb); + if(a) return(a*sa); + if(*(pa=jpa) == '.') + pa++; + if(*(pb=jpb) == '.') + pb++; + while(pacode; + ignore = fp->ignore; +loop: + while(*pa<0 || ignore[*pa]) + pa++; + while(*pb<0 || ignore[*pb]) + pb++; + if(pa>=la || *pa=='\n') + if(pbrflg); + else continue; + if(pb>=lb || *pb=='\n') + return(-fp->rflg); + if((sa = code[*pb++]-code[*pa++]) == 0) + goto loop; + return(sa*fp->rflg); + } + pa = *i; + pb = *j; + while(*pa != '\n') { + if(*pa == *pb) { + pa++; + pb++; + continue; + } + if(*pb == '\n') + return(-1); + return(*pb - *pa); + } + return(*pb != '\n'); +} + +skip(pp, fp, j) +struct field *fp; +char *pp; +{ + register i; + register char *p; + + p = pp; + if( (i=fp->m[j]) < 0) + return(-1); + while(i-- > 0) { + if(tabchar != 0) { + while(*p != tabchar) + if(*p != '\n') + p++; + else goto ret; + p++; + } else { + while(blank(*p)) + p++; + while(!blank(*p)) + if(*p != '\n') + p++; + else goto ret; + } + } + if(fp->bflg) + while(blank(*p)) + p++; + i = fp->n[j]; + while(i-- > 0) { + if(*p != '\n') + p++; + else goto ret; + } +ret: + return(p); +} + +digit(c) +{ + + return(c <= '9' && c >= '0'); +} + +mess(s) +char *s; +{ + while(*s) + write(2, s++, 1); +} + +copyproto() +{ + register int i, *p, *q; + + p = proto; + q = &fields[nfields]; + for(i=0; icode = nofold; + break; + + case 'b': + p->bflg++; + break; + + case 'd': + p->ignore = dict; + break; + + case 'n': + p->nflg++; + break; + case 't': + tabchar = *++s; + if(tabchar == 0) s--; + break; + + case 'r': + p->rflg = -1; + break; + + default: + p->m[k] = number(&s); + if(*s == '.') + s++; + p->n[k] = number(&s); + s--; + } + } +} + +number(ppa) +char **ppa; +{ + int n; + register char *pa; + pa = *ppa; + n = 0; + while(digit(*pa)) + n = n*10 + *pa++ - '0'; + *ppa = pa; + return(n); +} + +blank(c) +{ + if(c==' ' || c=='\t') + return(1); + return(0); +} diff --git a/source/s2/split.c b/source/s2/split.c new file mode 100644 index 0000000..f8398f7 --- /dev/null +++ b/source/s2/split.c @@ -0,0 +1,88 @@ +int count 1000; +int fnumber; +int ibuf[259]; +int obuf[259]; +char fname[100]; +char *ifil; +char *ofil; + +main(argc, argv) +char *argv[]; +{ + register i, c, f; + + for(i=1; i='0' && *s<='9') + n = n*10 + *s-'0'; + return(n); +} diff --git a/source/s2/strip.s b/source/s2/strip.s new file mode 100644 index 0000000..2aa8d90 --- /dev/null +++ b/source/s2/strip.s @@ -0,0 +1,141 @@ +/ strip -- strip relocation and symbols + + mov (sp)+,argc + tst (sp)+ + br loop +unloop: + sys unlink; s.tmp +loop: + dec argc + bgt 1f + sys exit +1: + mov (sp)+,r4 + mov r4,0f + sys open; 0:..; 0 + bec 1f + jsr r5,mesg; ; .even + br loop +1: + mov r0,fi + mov $'a,r1 +1: + movb r1,s.tmp+8 + sys stat; s.tmp; buf + bec 2f + sys creat; s.tmp; 400 + bec 1f +2: + inc r1 + cmp r1,$'z + blos 1b + jsr r5,mesg; ; .even + sys exit +1: + mov r0,fo + clr buf + mov fi,r0 + sys read; buf; 512. + mov r0,r3 + cmp buf,magic + beq 1f + cmp buf,magic1 + beq 1f + cmp buf,magic2 + beq 1f + jsr r5,mesg; ; .even + br unloop +1: + mov buf+2,r2 + add buf+4,r2 + add $20,r2 + clr r1 + clr buf+10 + mov $1,buf+16 / no reloc bits flag +1: + mov r2,0f + sub r1,0f + cmp 0f,r3 + blos 2f + mov r3,0f +2: + mov fo,r0 + sys write; buf; 0:.. + add 0b,r1 + cmp r1,r2 + bhis 1f + mov fi,r0 + sys read; buf; 512. + mov r0,r3 + bne 1b + jsr r5,mesg; ; .even +1: + mov fo,r0 + sys close + mov fi,r0 + sys close + mov r4,0f + sys creat; 0:..; 0 / same mode as before + bec 1f + jsr r5,mesg; ; .even + jmp unloop +1: + mov r0,fo + sys open; s.tmp; 0 + bec 1f + jsr r5,mesg; ; .even + sys exit +1: + mov r0,fi +1: + mov fi,r0 + sys read; buf; 512. + mov r0,0f + beq 1f + mov fo,r0 + sys write; buf; 0:.. + br 1b +1: + mov fi,r0 + sys close + mov fo,r0 + sys close + jmp unloop + +mesg: + movb (r5)+,ch + beq 1f + mov $1,r0 + sys write; ch; 1 + br mesg +1: + inc r5 + bic $1,r5 + mov r4,r1 +1: + movb (r1)+,ch + beq 1f + mov $1,r0 + sys write; ch; 1 + br 1b +1: + mov $1,r0 + sys write; qnl; 1 + rts r5 + +s.tmp: + +qnl: + <\n> + .even +magic: 407 +magic1: 410 +magic2: 411 + +.bss +fi: .=.+2 +fo: .=.+2 +argc: .=.+2 +buf: .=.+512. +ch: .=.+2 + diff --git a/source/s2/stty.c b/source/s2/stty.c new file mode 100644 index 0000000..f4f520e --- /dev/null +++ b/source/s2/stty.c @@ -0,0 +1,322 @@ +# +/* + * set teletype modes + */ + +/* + * tty flags + */ +#define HUPCL 01 +#define XTABS 02 +#define LCASE 04 +#define ECHO 010 +#define CRMOD 020 +#define RAW 040 +#define ODDP 0100 +#define EVENP 0200 +#define ANYP 0300 + +/* + * Delay algorithms + */ +#define CR0 0 +#define CR1 010000 +#define CR2 020000 +#define CR3 030000 +#define NL0 0 +#define NL1 000400 +#define NL2 001000 +#define NL3 001400 +#define TAB0 0 +#define TAB1 002000 +#define TAB2 004000 +#define TAB3 006000 +#define FF0 0 +#define FF1 040000 +#define BS0 0 +#define BS1 0100000 +#define ALL 0177400 + +struct +{ + char *string; + int speed; +} speeds[] +{ + "0", (0<<8)|0, + "50", (1<<8)|1, + "75", (2<<8)|2, + "110", (3<<8)|3, + "134", (4<<8)|4, + "134.5",(4<<8)|4, + "150", (5<<8)|5, + "200", (6<<8)|6, + "300", (7<<8)|7, + "600", (8<<8)|8, + "1200", (9<<8)|9, + "1800", (10<<8)|10, + "2400", (11<<8)|11, + "4800", (12<<8)|12, + "9600", (13<<8)|13, + "exta", (14<<8)|14, + "extb", (15<<8)|15, + 0, +}; +struct +{ + char *string; + int set; + int reset; +} modes[] +{ + "even", + EVENP, 0, + + "-even", + 0, EVENP, + + "odd", + ODDP, 0, + + "-odd", + 0, ODDP, + + "raw", + RAW, 0, + + "-raw", + 0, RAW, + + "cooked", + 0, RAW, + + "-nl", + CRMOD, 0, + + "nl", + 0, CRMOD, + + "echo", + ECHO, 0, + + "-echo", + 0, ECHO, + + "LCASE", + LCASE, 0, + + "lcase", + LCASE, 0, + + "-LCASE", + 0, LCASE, + + "-lcase", + 0, LCASE, + + "-tabs", + XTABS, 0, + + "tabs", + 0, XTABS, + + "hup", + HUPCL, 0, + + "-hup", + 0, HUPCL, + + "cr0", + CR0, CR3, + + "cr1", + CR1, CR3, + + "cr2", + CR2, CR3, + + "cr3", + CR3, CR3, + + "tab0", + TAB0, TAB3, + + "tab1", + TAB1, TAB3, + + "tab2", + TAB2, TAB3, + + "tab3", + TAB3, TAB3, + + "nl0", + NL0, NL3, + + "nl1", + NL1, NL3, + + "nl2", + NL2, NL3, + + "nl3", + NL3, NL3, + + "ff0", + FF0, FF1, + + "ff1", + FF1, FF1, + + "bs0", + BS0, BS1, + + "bs1", + BS1, BS1, + + "33", + CR1, ALL, + + "tty33", + CR1, ALL, + + "37", + FF1+CR2+TAB1+NL1, ALL, + + "tty37", + FF1+CR2+TAB1+NL1, ALL, + + "05", + NL2, ALL, + + "vt05", + NL2, ALL, + + "tn", + CR1, ALL, + + "tn300", + CR1, ALL, + + "ti", + CR2, ALL, + + "ti700", + CR2, ALL, + + "tek", + FF1, ALL, + + 0, + }; + +char *arg; +int mode[3]; + +struct { char lobyte, hibyte; }; + +main(argc, argv) +char *argv[]; +{ + int i; + + gtty(1, mode); + if(argc == 1) { + prmodes(); + exit(0); + } + while(--argc > 0) { + + arg = *++argv; + if (eq("ek")) + mode[1] = '#@'; + if (eq("erase")) { + mode[1].lobyte = **++argv; + argc--; + } + if (eq("kill")) { + mode[1].hibyte = **++argv; + argc--; + } + for(i=0; speeds[i].string; i++) + if(eq(speeds[i].string)) + mode[0] = speeds[i].speed; + for(i=0; modes[i].string; i++) + if(eq(modes[i].string)) { + mode[2] =& ~modes[i].reset; + mode[2] =| modes[i].set; + } + if(arg) + printf("unknown mode: %s\n", arg); + } + stty(1,mode); +} + +eq(string) +char *string; +{ + int i; + + if(!arg) + return(0); + i = 0; +loop: + if(arg[i] != string[i]) + return(0); + if(arg[i++] != '\0') + goto loop; + arg = 0; + return(1); +} + +prmodes() +{ + register m; + + if(mode[0].lobyte != mode[0].hibyte) { + prspeed("input speed ", mode[0].lobyte); + prspeed("output speed ", mode[0].hibyte); + } else + prspeed("speed ", mode[0].lobyte); + printf("erase = '%c'; kill = '%c'\n", mode[1].lobyte, mode[1].hibyte); + m = mode[2]; + if(m & 0200) printf("even "); + if(m & 0100) printf("odd "); + if(m & 040) printf("raw "); + if(m & 020) printf("-nl "); + if(m & 010) printf("echo "); + if(m & 04) printf("lcase "); + if(m & 02) printf("-tabs "); + if(m & 01) printf("hup "); + delay(m>>8, "nl"); + delay(m>>10, "tab"); + delay(m>>12, "cr"); + delay((m>>14)&1, "ff"); + delay((m>>15)&1, "bs"); + printf("\n"); +} + +delay(m, s) +char *s; +{ + + if(m =& 3) + printf("%s%d ", s, m); +} + +int speed[] +{ + 0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,0,0 +}; + +prspeed(c, s) +{ + + printf("%s%d baud\n", c, speed[s]); +} + +putchar(c) +{ + + write(2, &c, 1); +} diff --git a/source/s2/su.c b/source/s2/su.c new file mode 100644 index 0000000..679502c --- /dev/null +++ b/source/s2/su.c @@ -0,0 +1,46 @@ +/* su -- become super-user */ + +char password[100]; +char pwbuf[100]; +int ttybuf[3]; +main() +{ + register char *p, *q; + extern fin; + + if(getpw(0, pwbuf)) + goto badpw; + (&fin)[1] = 0; + p = pwbuf; + while(*p != ':') + if(*p++ == '\0') + goto badpw; + if(*++p == ':') + goto ok; + gtty(0, ttybuf); + ttybuf[2] =& ~010; + stty(0, ttybuf); + printf("password: "); + q = password; + while((*q = getchar()) != '\n') + if(*q++ == '\0') + return; + *q = '\0'; + ttybuf[2] =| 010; + stty(0, ttybuf); + printf("\n"); + q = crypt(password); + while(*q++ == *p++); + if(*--q == '\0' && *--p == ':') + goto ok; + goto error; + +badpw: + printf("bad password file\n"); +ok: + setuid(0); + execl("/bin/sh", "-", 0); + printf("cannot execute shell\n"); +error: + printf("sorry\n"); +} diff --git a/source/s2/sum.s b/source/s2/sum.s new file mode 100644 index 0000000..82b9413 --- /dev/null +++ b/source/s2/sum.s @@ -0,0 +1,81 @@ +/ sum -- check sum file + + mov (sp)+,r3 + tst (sp)+ +loop: dec r3 + bgt 1f + sys exit +1: + clr bcnt + mov (sp)+,0f + sys open; 0:..; 0 + bec 3f + mov $1,r0 + sys write; 1f; 2f-1f + br loop +1: +2: .even +3: mov r0,r1 + clr r5 +1: + mov r1,r0 + sys read; buf; 512. + bes err + tst r0 + beq print + inc bcnt + mov $buf,r2 +2: + movb (r2)+,r4 + add r4,r5 + adc r5 + sob r0,2b + br 1b + +err: + mov $1,r0 + sys write; 1f; 2 + +print: + jsr pc,decml + mov $1,r0 + sys write; bl; 1 + mov bcnt,r5 + jsr pc,decml + mov $1,r0 + sys write; nl; 1 + mov r1,r0 + sys close + br loop +1: +nl: <\n> +bl: < > + .even + +decml: + mov r0,-(sp) + mov r1,-(sp) + mov r5,r1 + jsr pc,1f + mov (sp)+,r1 + mov (sp)+,r0 + rts pc + +1: + clr r0 + dvd $10.,r0 + mov r1,-(sp) + mov r0,r1 + beq 1f + jsr pc,1b +1: + mov (sp)+,ch + add $'0,ch + mov $1,r0 + sys write; ch; 1 + rts pc + +.bss +ch: .=.+2 +bcnt: .=.+2 +buf: .=.+512. diff --git a/source/s2/sync.c b/source/s2/sync.c new file mode 100644 index 0000000..3afb9b8 --- /dev/null +++ b/source/s2/sync.c @@ -0,0 +1,5 @@ +main() +{ + + sync(); +} diff --git a/source/s2/tbl.c b/source/s2/tbl.c new file mode 100644 index 0000000..43b731d --- /dev/null +++ b/source/s2/tbl.c @@ -0,0 +1,317 @@ +# +# define ever (;;) +# define MAXCHS 2000 +main(argc,argv) + char *argv[]; +{ +char line[200]; +extern int cin; +extern char *cspace; + cspace = getvec(MAXCHS + 100); +for ever +{ + if (argc>1) + { + argc--; + argv++; + if (match(*argv, "-ms")) + *argv = "/usr/lib/tmac.s"; + cin = copen(*argv, 'r'); + if (cin < 0) + { + printf(2,"where is input file %s\n",*argv); + cexit(); + } + } +while (gets(line)) + if (match(line, ".TS")) + tableput(); + else + puts(line); +if (argc <= 1) break; +} +cexit(); +} +# define MAXCOL 35 +# define MAXLIN 220 +# define ONELINE 250 +char *tabentry[MAXLIN][MAXCOL]; +char extra[MAXCHS]; +char *cspace, *cstore; +char *exstore extra; +int sep[MAXCOL], dwide[MAXCOL]; +char *instead[MAXLIN]; +int newtab[MAXLIN]; +char *style[MAXCOL]; +tableput() +{ +/* read input, write output, make tables on the way */ +char st[ONELINE], *format; +int ilin, nlin, icol, ncol, k, ch, ws, cs, ns; +int maxchnge, ct; +printf(".TS\n"); +/* get command line */ +cstore = cspace; +exstore = extra; +ncol = 0; +for (ilin=0; ilin MAXCHS) + cstore = cspace = getvec(MAXCHS+100); + } +/* find longest command string */ +for (icol=maxchnge=0; icolmaxchnge) + maxchnge = slen(style[icol]); +/* set tab stops */ +printf(".nr 49 0\n"); +for (icol = 0; icol0 ? sep[icol-1] : 0); + printf(".nr %2d 0\n", icol+50); + for (ilin=0; ilin < nlin; ilin++) + { + if (icol>0 && dwide[icol-1]>0 && tabentry[ilin][icol]==0) + { + printf(".nr 48 \\n(%2d+\\w'%s'+%dn\n", + icol+48, tabentry[ilin][icol-1], sep[icol-1]); + printf(".if \\n(48-\\n(%2d .nr %2d \\n(48\n", + icol+50,icol+50); + } + if ( !span(style[icol],ilin) && /* not part of span */ + (dwide[icol] == 0 || tabentry[ilin][icol+1]!= 0) + /* not a double item */ + && (!span(style[icol+1],ilin) || icol==ncol)) + { + printf(".nr 47 \\n(%2d+\\w'%s'+%dn\n", + icol+49,tabentry[ilin][icol], ct); + printf(".if \\n(47-\\n(%2d .nr %2d \\n(47\n", + icol+50,icol+50); + } + } + /* clean up spanned headings */ + for(ilin=0; ilin0 && tabentry[ilin][icol] == 0 )) + printf(format, tabentry[ilin][icol]); + if (!span(style[icol+1],ilin)) + for (k=sep[icol]; k>0; k--) + printf(" "); + } + printf("\n"); + } +printf(".fc\n"); +printf(".TE\n"); +} +match (s1, s2) + char *s1, *s2; +{ + while (*s1 == *s2) + if (*s1++ == '\0') + return(1); + else + *s2++; + return(0); +} +slen(str) + char *str; +{ + int k; + for (k=0; *str++ != '\0'; k++); + return(k); +} +space(ch) + { + switch (ch) + { + case ' ': case '\t': + return(1); + } + return(0); + } +letter (ch) + { + if (ch >= 'a' && ch <= 'z') + return(1); + if (ch >= 'A' && ch <= 'Z') + return(1); + return(0); + } +numb(str) + char *str; + { + /* convert to integer */ + int k; + for (k=0; *str >= '0' && *str <= '9'; str++) + k = k*10 + *str - '0'; + return(k); + } +broken(str, nlin) + { + switch(ylet(str,nlin)) + { + case 'n': case 'N': + return(1); + } + return(0); + } +ylet (str, k) + char *str; +{ + k++; + while (*str &&k--) + str++; + return(*--str); +} +span(str, k) + { + switch(ylet(str,k)) + { + case 's': case 'S': + return(1); + } + return(0); + } +maknew(str) + char *str; +{ + /* make two numerical fields */ + int point; + char *p, *q; + p = str; + for (point=0; *str; str++) + if (*str=='.') + point=1; + if (!point && *(str-1)== '$') + return(0); + for(; str>p; str--) + if ( (point && *str == '.') || + (!point && digit(*(str-1)) ) ) + break; + if (!point && p==str) /* not numerical, don't split */ + return(0); + p= str; + q = exstore; + while (*exstore++ = *str++); + *p = 0; + return(q); + } +digit(x) + { + return(x>= '0' && x<= '9'); + } +settab(ncol, ilin) +{ + int k, icol; + printf(".ta "); + for (icol = 0; icol1) { + open[n++] = creat(argv[1],0666); + if(stat(argv[1],&buf)>=0) + if((buf.type&060000)==020000) + t++; + argv++; + } + r = w = 0; + for(;;) { + for(p=0;p<512;) { + if(r>=w) { + if(t>0&&p>0) break; + w = read(0,in,512); + r = 0; + if(w<=0) { + stash(p); + return; + } + } + out[p++] = in[r++]; + } + stash(p); + } +} + +stash(p) +{ + int k; + int i; + int d; + d = t ? 10 : p; + for(i=0; i; .even + mov $ltbuf,r2 + jsr r5,ptime + jsr r5,mesg; ; .even + jsr r5,ptime + jsr r5,mesg; ; .even + jsr r5,ptime + sys exit + +execarg: + sys fork + br newproc + bec 2f + jsr r5,mesg; ; .even + sys exit +2: + mov r0,r2 + sys signal; 2; 1 +2: + sys wait + cmp r0,r2 + bne 2b + bit $377,r1 + beq 1f + jsr r5,mesg; ; .even + clr r0 + sys seek; 0; 2 +1: + rts pc + +newproc: + tst (sp)+ + mov (sp)+,r0 + tst (sp)+ + mov $ibuf,r1 + mov $end,r2 +1: + mov (sp)+,r3 + mov r2,(r1)+ +2: + movb (r3)+,(r2)+ + bne 2b + dec r0 + cmp r0,$1 + bgt 1b + clr (r1)+ + mov $end,r1 + sys exec; end; ibuf + cmp $8,r0 + beq rcom + mov $end-10.,r0 + mov $"x/,(r0)+ + mov $"us,(r0)+ + mov $"r/,(r0)+ + mov $"bi,(r0)+ + mov $"n/,(r0)+ + mov $end-5,r1 + sys exec; end-5; ibuf + cmp $8,r0 + beq rcom + mov $end-9,r1 + sys exec; end-9.; ibuf + cmp $8,r0 + bne 1f +rcom: + mov r1,ibuf + mov $shname+5,ibuf-2 + sys exec ; shname ; ibuf-2 +1: + jsr r5,mesg; ; .even + clr r0 + sys seek; 0; 2 + sys exit + +printd: + mov $tbuf+4,r4 + jsr r5,tdiv; 10. + jsr r5,tdiv; 10. + jsr r5,tdiv; 10. + jsr r5,tdiv; 10. +1: + cmpb (r4),$'0 + bne 1f + movb $' ,(r4)+ + cmp r4,$tbuf+3 + bne 1b +1: + mov $2,r0 + sys write; tbuf; 4 + rts pc + +ptime: + mov (r2)+,r0 + mov (r2)+,r1 + div $3600.,r0 + mov r0,-(sp) + clr r0 + div $60.,r0 + mov r1,clicks + mov $tbuf+9.,r4 + jsr r5,tdiv; 10. + jsr r5,tdiv; 6. + movb $':,-(r4) + mov (sp)+,r0 + jsr r5,tdiv; 10. + jsr r5,tdiv; 6. + movb $':,-(r4) + jsr r5,tdiv; 10. + jsr r5,tdiv; 10. + jsr r5,tdiv; 10. +1: + cmpb (r4),$'0 + beq 2f + cmpb (r4),$': + bne 1f +2: + movb $' ,(r4)+ + cmp r4,$tbuf+8. + bne 1b +1: + mov $2,r0 + sys write; tbuf; 9. + jsr r5,mesg; <.\0>; .even + mov clicks,r1 + clr r0 + div $6,r0 + add $'0,r0 + mov r0,ch + mov $2,r0 + sys write; ch; 1 + jsr r5,mesg; <\n\0>; .even + rts r5 + +tdiv: + mov r1,-(sp) + mov r0,r1 + clr r0 + div (r5)+,r0 + add $'0,r1 + movb r1,-(r4) + mov (sp)+,r1 + rts r5 + +mesg: + movb (r5)+,ch + beq 2f + mov $2,r0 + sys write; ch; 1 + br mesg +2: + inc r5 + bic $1,r5 + rts r5 + +ch: .=.+1 +.even +.bss + +clicks: .=.+2 + .=.+2 +ibuf: .=.+50. +tbuf: .=.+10. +ltbuf: .=.+16. +end: .=.+1000. + +.data +shname: +.even diff --git a/source/s2/tp1.s b/source/s2/tp1.s new file mode 100644 index 0000000..13e513e --- /dev/null +++ b/source/s2/tp1.s @@ -0,0 +1,267 @@ +/ tap1 -- dec-disk lod/dmp + +.globl _localtime, _end +namep = 0 +mode = 2 +uid = 4; gid = 5 +size0 = 7 +size1 = 8 +time0 = 10. +time1 = 12. +tapea = 14. +dirsiz = 16. +mdirent = 496. + + mov (sp),rnarg + mov (sp)+,narg + mov $cmr,command + incb flu + tst (sp)+ + cmp narg,$2 + bge 1f + mov $2,narg + br 3f +1: + mov (sp)+,r0 + mov sp,parg +1: + movb (r0)+,r1 + beq 3f + mov $swtab,r2 +2: + cmp r1,(r2)+ + beq 2f + tst (r2)+ + bne 2b + br useerr +2: + jsr pc,*(r2)+ + br 1b +3: + jsr pc,optap + mov $_end,r4 / string pointer + jsr pc,setb + jmp *command + +optap: + tstb flm + bne 2f + mov $578.,tapsiz + mov $192.,ndirent + sys open; tc; 2 + br 3f +2: + mov $-1,tapsiz + mov $mdirent,ndirent + cmp command,$cmr + beq 2f + sys open; mt; 0 + br 3f +2: + sys open; mt; 1 +3: + bes 1f + mov r0,fio + mov ndirent,r1 + ash $-3,r1 + mov r1,ndentd8 + mov ndirent,r1 + mul $dirsiz,r1 + add $dir,r1 + mov r1,edir + rts pc +1: + jsr r5,mesg + ; .even + jmp done + +setcom: + cmp command,$cmr + bne useerr + mov (r5)+,command + rts r5 + +noflag: + mov (r5)+,r0 + beq 1f + tstb (r0) + beq noflag + br useerr +1: + rts r5 + +useerr: + jsr r5,mesg + ; .even + jmp done + +swtab: + '0; dcof + '1; dcof + '2; dcof + '3; dcof + '4; dcof + '5; dcof + '6; dcof + '7; dcof + 'c; dcc + 'd; dcd + 'f; dcf + 'i; dci + 'm; dcm + 'r; dcr + 't; dct + 'u; dcu + 'v; dcv + 'w; dcw + 'x; dcx + 0; 0 + +dcof: + movb r1,tcx + movb r1,mtx + rts pc + +dcc: + incb flc + rts pc + +dcf: + incb flf + rts pc + +dcd: + jsr r5,setcom; cmd + rts pc + +dci: + incb fli + rts pc + +dcm: + incb flm + rts pc + +dcu: + incb flu + jsr r5,setcom; cmr + rts pc + +dcr: + clrb flu + jsr r5,setcom; cmr + rts pc + +dct: + jsr r5,setcom; cmt + rts pc + +dcv: + incb flv + rts pc + +dcw: + incb flw + rts pc + +dcx: + jsr r5,setcom; cmx + rts pc + +cmd: + jsr r5,noflag; flm; flc; flf; 0 + cmp narg,$2 + bgt 1f + jmp useerr +1: + jsr pc,rddir + jsr r5,gettape; delete + jsr pc,wrdir + br check + +cmr: + jsr r5,noflag; 0 + tstb flc + bne 1f + tstb flm + bne 1f + jsr pc,rddir + br 2f +1: + jsr pc,clrdir +2: + jsr pc,getfiles + jsr pc,update + br check + +cmt: + jsr r5,noflag; flc; flf; flw; 0 + jsr pc,rddir + tstb flv + beq 1f + jsr r5,mesg + < mode uid gid tapa size date time name\n\0>; .even +1: + jsr r5,gettape; taboc + br check1 + +cmx: + jsr r5,noflag; flc; flf; 0 + jsr pc,rddir + jsr r5,gettape; xtract + br done + +check: + +check1: + jsr pc,usage + +done: + jsr r5,mesg + ; .even + sys exit + +encode: + mov r2,-(sp) + mov r4,(r1) + mov (r5)+,r2 +1: + movb (r2),(r4)+ + jsr pc,setb + tstb (r2)+ + bne 1b + mov (sp)+,r2 + rts r5 + +decode: + mov r2,-(sp) + mov r1,-(sp) + mov (r1),r1 + mov (r5)+,r2 +1: + movb (r1)+,(r2)+ + bne 1b + mov (sp)+,r1 + mov (sp)+,r2 + rts r5 + +setb: + mov r0,-(sp) + mov r4,r0 + add $513.,r0 + cmp r0,sp + bhis 2f + bic $777,r0 + cmp r0,0f + beq 1f + mov r0,0f + sys break; 0:.. + bes 2f +1: + mov (sp)+,r0 + rts pc + +2: + jsr r5,mesg + ; .even + jmp done diff --git a/source/s2/tp2.s b/source/s2/tp2.s new file mode 100644 index 0000000..48e109e --- /dev/null +++ b/source/s2/tp2.s @@ -0,0 +1,449 @@ +/ tap2 -- dec-tape lod/dmp + +pstr: + movb (r1)+,r0 + beq 1f + jsr pc,putc + br pstr +1: + rts pc + +mesg: + movb (r5)+,r0 + beq 1f + jsr pc,putc + br mesg +1: + inc r5 + bic $1,r5 + rts r5 + +putc: + movb r0,ch + mov $1,r0 + sys write; ch; 1 + rts pc + +getc: + clr r0 + sys read; ch; 1 + movb ch,r0 + rts pc + +clrdir: + mov $dir,r1 + mov ndirent,r2 +1: + jsr pc,clrent + sob r2,1b + rts pc + +clrent: + mov r1,-(sp) + add $dirsiz,(sp) +1: + clr (r1)+ + cmp r1,(sp) + blo 1b + tst (sp)+ + rts pc + +rddir: + clr sum + jsr pc,clrdir + clr r0 + jsr pc,rseek + jsr pc,tread + mov tapeb+510.,r0 + beq 1f + tstb flm + beq 1f + mov r0,ndirent +1: + mov $dir,r1 + mov ndirent,r2 +1: + bit $7,r2 + bne 2f + jsr pc,tread + mov $tapeb,r3 +2: + mov r1,-(sp) + mov r3,-(sp) + mov $32.,r0 + clr -(sp) +2: + add (r3)+,(sp) + sob r0,2b + bis (sp),sum + tst (sp)+ + bne 2f + mov (sp),r3 + tst (r3) + beq 2f + mov r3,0f + jsr pc,9f +.data +9: + jsr r5,encode; 0:.. + rts pc +.text + add $32.,r3 + mov r1,-(sp) + add $dirsiz,(sp) + tst (r1)+ / namep +9: + mov (r3)+,(r1)+ + cmp r1,(sp) + blo 9b + tst (sp)+ +2: + mov (sp)+,r3 + add $64.,r3 + mov (sp)+,r1 + bic $100000,mode(r1) + add $dirsiz,r1 + sob r2,1b + tst sum + beq 1f + jsr r5,mesg + ; .even + tstb fli + bne 1f + jmp done +1: + jsr pc,bitmap + rts pc + +wrdir: + clr r0 + jsr pc,wseek + tstb flm + bne 1f + sys open; tboot; 0 + bes 3f + br 2f +1: + sys open; mboot; 0 + bes 3f +2: + mov r0,r1 + sys read; tapeb; 512. + mov r1,r0 + sys close + mov ndirent,tapeb+510. +3: + jsr pc,twrite + mov $dir,r1 + mov ndirent,r2 +1: + bit $7,r2 + bne 2f + mov $256.,r0 + mov $tapeb,r3 +3: + clr (r3)+ + sob r0,3b + mov $tapeb,r3 +2: + mov r3,-(sp) + tst (r1) + beq 2f + mov r3,0f + jsr pc,9f +.data +9: + jsr r5,decode; 0:.. + rts pc +.text +2: + add $32.,r3 + mov r1,-(sp) + add $dirsiz,(sp) + tst (r1)+ +9: + mov (r1)+,(r3)+ + cmp r1,(sp) + blo 9b + tst (sp)+ + mov (sp)+,r3 + clr -(sp) + mov $31.,r0 +2: + sub (r3)+,(sp) + sob r0,2b + mov (sp)+,(r3)+ + dec r2 + bit $7,r2 + bne 1b + jsr pc,twrite + tst r2 + bne 1b + rts pc + +tread: + mov fio,r0 + sys read; tapeb; 512. + bes trderr + cmp r0,$512. + bne trderr +1: + inc rseeka + rts pc + +trderr: + jsr r5,mesg + ; .even + tstb fli + beq 1f + mov $tapeb,r0 +2: + clr (r0)+ + cmp r0,$tapeb+512. + blo 2b + br 1b +1: + jmp done + +twrite: + mov fio,r0 + sys write; tapeb; 512. + bes twrerr + cmp r0,$512. + bne twrerr + inc wseeka + rts pc + +twrerr: + jsr r5,mesg + ; .even + jmp done + +rseek: + mov r0,rseeka + mov r0,0f + mov fio,r0 + sys 0; 9f +.data +9: + sys seek; 0:..; 3 +.text + bes seekerr + rts pc + +wseek: + mov r0,-(sp) + sub wseeka,r0 + bge 1f + neg r0 +1: + cmp r0,$25. / longest write seek + ble 1f + mov (sp),0f + beq 2f + dec 0f +2: + mov fio,r0 + sys 0; 9f +.data +9: + sys seek; 0:..; 3 +.text + mov fio,r0 + sys read; wseeka; 1 +1: + mov (sp),wseeka + mov (sp)+,0f + mov fio,r0 + sys 0; 9f +.data +9: + sys seek; 0:..; 3 +.text + bes seekerr + rts pc + +seekerr: + jsr r5,mesg +; .even + jmp done + +verify: + movb (r5)+,0f + inc r5 + tstb flw + bne 1f + tstb flv + beq 2f +1: + jsr pc,9f +.data +9: + jsr r5,mesg + 0:; .even + rts pc +.text + mov r1,-(sp) + mov $name,r1 + jsr pc,pstr + mov (sp)+,r1 + tstb flw + beq 1f + jsr r5,mesg + < \0> + jsr pc,getc + cmp r0,$'x + bne 3f + jsr pc,getc + jmp done +3: + cmp r0,$'\n + beq 3f + cmp r0,$'y + bne 4f + jsr pc,getc + cmp r0,$'\n + beq 2f +4: + jsr pc,getc + cmp r0,$'\n + bne 4b + br 1b +1: + jsr r5,mesg + <\n\0> +2: + tst (r5)+ +3: + rts r5 + +getfiles: + cmp narg,$2 + bne 1f + mov $".\0,name + jsr pc,callout +1: + cmp narg,$2 + ble 1f + dec narg + mov *parg,r1 + add $2,parg + mov $name,r2 +2: + movb (r1)+,(r2)+ + bne 2b + jsr pc,callout + br 1b +1: + rts pc + +expand: + sys open; name; 0 + bes fserr + mov r0,-(sp) +1: + mov (sp),r0 + sys read; catlb; 16. + bes fserr + tst r0 + beq 1f + tst catlb + beq 1b + mov $name,r0 + mov $catlb+2,r1 + cmpb (r1),$'. + beq 1b +2: + tstb (r0)+ + bne 2b + dec r0 + mov r0,-(sp) + cmpb -1(r0),$'/ + beq 2f + movb $'/,(r0)+ +2: + movb (r1)+,(r0)+ + bne 2b + jsr pc,callout + clrb *(sp)+ + br 1b +1: + mov (sp)+,r0 + sys close + rts pc + +fserr: + mov $name,r1 + jsr pc,pstr + jsr r5,mesg + < -- Cannot open file\n\0>; .even + jmp done + +callout: + sys stat; name; statb + bes fserr + mov statb+4,r0 + bic $!60000,r0 + beq 1f + cmp r0,$40000 + beq expand + rts pc +1: + mov $dir,r1 + clr -(sp) +1: + tst (r1) + bne 3f + tst (sp) + bne 2f + mov r1,(sp) +2: + add $dirsiz,r1 + cmp r1,edir + blo 1b + mov (sp)+,r1 + bne 4f + jsr r5,mesg + ; .even + jmp done +4: + jsr r5,verify; 'a + rts pc + jsr r5,encode; name + br 2f +3: + jsr r5,decode; name1 + mov $name,r2 + mov $name1,r3 +3: + cmpb (r2)+,(r3) + bne 2b + tstb (r3)+ + bne 3b + tst (sp)+ + tstb flu + beq 3f + cmp time0(r1),statb+32. + blo 3f + bhi 1f + cmp time1(r1),statb+34. + bhis 1f +3: + jsr r5,verify; 'r + rts pc +2: + mov statb+4,mode(r1) + bis $100000,mode(r1) + movb statb+7,uid(r1) + movb statb+8,gid(r1) + tstb flf + beq 2f + clrb statb+9. + clr statb+10. +2: + movb statb+9.,size0(r1) + mov statb+10.,size1(r1) + mov statb+32.,time0(r1) + mov statb+34.,time1(r1) +1: + rts pc diff --git a/source/s2/tp3.s b/source/s2/tp3.s new file mode 100644 index 0000000..d500ff3 --- /dev/null +++ b/source/s2/tp3.s @@ -0,0 +1,522 @@ +/ tap3 -- dec-tape lod/dmp + +gettape: + mov $dir,r1 + clr -(sp) +1: + tst (r1) + beq 2f + jsr r5,decode; name + cmp rnarg,$2 + ble 4f + mov $name,r2 + mov *parg,r3 +3: + tstb (r3) + beq 3f + cmpb (r2)+,(r3)+ + beq 3b + br 2f +3: + tstb (r2) + beq 4f + cmpb (r2),$'/ + bne 2f +4: + mov r1,-(sp) + jsr pc,*(r5) + mov (sp)+,r1 + inc (sp) +2: + add $dirsiz,r1 + cmp r1,edir + blo 1b + tst (sp)+ + bne 2f + cmp rnarg,$2 + ble 2f + mov *parg,r1 + jsr pc,pstr + jsr r5,mesg + < not found\n\0>; .even +2: + dec narg + add $2,parg + cmp narg,$2 + bgt gettape + tst (r5)+ + rts r5 + +delete: + jsr r5,verify; 'd + rts pc + jsr pc,clrent + rts pc + +numb: + mov r1,-(sp) + mov r0,-(sp) + clr r0 + br 1f + +numbx: + mov r1,-(sp) + mov r0,-(sp) + movb size0(r1),r0 +1: + mov $catlb,r2 +1: + mov $" ,(r2)+ + cmp r2,$catlb+12. + blo 1b + cmp (r5),$2 + bne 1f + mov $"00,-2(r2) +1: + mov (sp)+,r1 + jsr pc,numb2 + mov (r5)+,r0 + sub r0,r2 + mov r2,0f + mov r0,0f+2 + mov $1,r0 + sys 0; 9f +.data +9: + sys write; 0:..; .. +.text + mov (sp)+,r1 + rts r5 + +numb1: + clr r0 +numb2: + div $10.,r0 + mov r1,-(sp) + mov r0,r1 + beq 1f + jsr pc,numb1 +1: + mov (sp)+,r0 + add $'0,r0 + movb r0,(r2)+ + rts pc + +update: + jsr pc,bitmap + mov $dir,r1 +1: + tst (r1) + beq 2f + bit $100000,mode(r1) + beq 2f + tstb size0(r1) + bne 9f + tst size1(r1) + beq 2f +9: + mov ndentd8,-(sp) + inc (sp) + movb size0(r1),r2 + mov size1(r1),r3 + add $511.,r3 + adc r2 + ashc $-9,r2 + mov r3,size +3: + mov (sp),r2 + mov size,r3 +4: + jsr pc,bitcalc + inc r2 + bitb (sp)+,map(r0) + bne 4f + sob r3,4b + mov (sp)+,tapea(r1) + jsr pc,setmap + br 2f +4: + inc (sp) + br 3b +2: + add $dirsiz,r1 + cmp r1,edir + blo 1b + jsr pc,wrdir + +update1: + mov $dir,r1 + clr -(sp) + mov $-1,-(sp) +1: + tst (r1) + beq 2f + bit $100000,mode(r1) + beq 2f + cmp tapea(r1),(sp) + bhis 2f + mov tapea(r1),(sp) + mov r1,2(sp) +2: + add $dirsiz,r1 + cmp r1,edir + blo 1b + tst (sp)+ + mov (sp)+,r1 + bne 1f + rts pc +1: + bic $100000,mode(r1) + movb size0(r1),mss + mov size1(r1),r2 + bne 4f + tst mss + beq update1 +4: + jsr r5,decode; name + mov tapea(r1),r0 + jsr pc,wseek + clr r3 + sys open; name; 0 + bes phserr + mov r0,r3 +3: + tst mss + bne 4f + cmp r2,$512. + blo 3f +4: + mov r3,r0 + sys read; tapeb; 512. + bes phserr + cmp r0,$512. + bne phserr + jsr pc,twrite + sub $512.,r2 + sbc mss + br 3b +3: + mov r2,0f + beq 3f + mov r3,r0 + sys 0; 9f +.data +9: + sys read; tapeb; 0:.. +.text + bes phserr + cmp r0,0b + bne phserr + jsr pc,twrite +3: + mov r3,r0 + sys read; tapeb; 512. + bes phserr + tst r0 + bne phserr + mov r3,r0 + sys close +2: + jmp update1 + +phserr: + mov r1,-(sp) + mov $name,r1 + jsr pc,pstr + jsr r5,mesg + < -- Phase error\n\0>; .even + mov (sp)+,r1 + clr time0(r1) / time + beq 2b + sys close + br 2b + +bitmap: + mov $map,r0 +1: + clr (r0)+ + cmp r0,$emap + blo 1b + mov $dir,r1 +1: + tst (r1) + beq 2f + bit $100000,mode(r1) + bne 2f + tst size1(r1) + bne 3f + tstb size0(r1) + beq 2f +3: + jsr pc,setmap +2: + add $dirsiz,r1 + cmp r1,edir + blo 1b + rts pc + +setmap: + movb size0(r1),r2 + mov size1(r1),r3 + add $511.,r3 + adc r2 + ashc $-9.,r2 + mov tapea(r1),r2 +1: + jsr pc,bitcalc + bitb (sp),map(r0) + bne maperr + bisb (sp)+,map(r0) + inc r2 + sob r3,1b + rts pc + +bitcalc: + mov (sp),-(sp) + cmp r2,tapsiz + bhis maperr + mov r2,r0 + bic $!7,r0 + mov r0,-(sp) + mov $1,r0 + als (sp)+,r0 + mov r0,2(sp) + mov r2,r0 + ash $-3,r0 + bic $160000,r0 + rts pc + +maperr: + jsr r5,mesg + ; .even + jmp done + +usage: + jsr pc,bitmap + mov $dir,r2 +1: + tst (r2) + beq 2f + inc nentr +2: + add $dirsiz,r2 + cmp r2,edir + blo 1b + mov ndentd8,r2 + inc r2 + mov tapsiz,r3 + dec r3 + sub ndentd8,r3 +1: + jsr pc,bitcalc + bitb (sp)+,map(r0) + beq 2f + inc nused + mov r2,lused + br 3f +2: + inc nfree + tstb flm + bne 1f +3: + inc r2 + sob r3,1b +1: + mov nentr,r0 + jsr r5,numb; 4 + jsr r5,mesg + < entries\n\0>; .even + mov nused,r0 + jsr r5,numb; 4 + jsr r5,mesg + < used\n\0>; .even + tstb flm + bne 1f + mov nfree,r0 + jsr r5,numb; 4 + jsr r5,mesg + < free\n\0>; .even +1: + mov lused,r0 + jsr r5,numb; 4 + jsr r5,mesg + < last\n\0>; .even + rts pc + +taboc: + tstb flv + beq 4f + mov mode(r1),r0 + mov r0,-(sp) + ash $-6,r0 + bit $40,r0 + jsr pc,pmod + mov (sp),r0 + ash $-3,r0 + bit $200,r0 + jsr pc,pmod + mov (sp)+,r0 + bit $1000,r0 + jsr pc,pmod + clr r0 + bisb uid(r1),r0 + jsr r5,numb; 4 + clr r0 + bisb gid(r1),r0 + jsr r5,numb; 4 + mov tapea(r1),r0 + jsr r5,numb; 5 + mov size1(r1),r0 + jsr r5,numbx; 9. + mov r1,-(sp) + add $time0,(sp) + jsr pc,_localtime + mov r0,(sp) + mov 10.(r0),r0 + jsr r5,numb; 3 + mov $'/,r0 + jsr pc,putc + mov (sp),r0 + mov 8.(r0),r0 + inc r0 + jsr r5,numb; 2 + mov $'/,r0 + jsr pc,putc + mov (sp),r0 + mov 6(r0),r0 + jsr r5,numb; 2 + mov (sp),r0 + mov 4(r0),r0 + jsr r5,numb; 3 + mov $':,r0 + jsr pc,putc + mov (sp)+,r0 + mov 2(r0),r0 + jsr r5,numb; 2 + mov $' ,r0 + jsr pc,putc +4: + mov $name,r1 + jsr pc,pstr + jsr r5,mesg + <\n\0> + rts pc + +pmod: + beq 1f + mov $'s,-(sp) + br 2f +1: + bit $1,r0 + beq 1f + mov $'x,-(sp) + br 2f +1: + mov $'-,-(sp) +2: + bit $2,r0 + beq 1f + mov $'w,-(sp) + br 2f +1: + mov $'-,-(sp) +2: + bit $4,r0 + beq 1f + mov $'r,r0 + br 2f +1: + mov $'-,r0 +2: + jsr pc,putc + mov (sp)+,r0 + jsr pc,putc + mov (sp)+,r0 + jsr pc,putc + rts pc + +xtract: + movb size0(r1),mss + bne 2f + tst size1(r1) + beq 1f +2: + jsr r5,verify; 'x + rts pc + mov size1(r1),r3 + mov tapea(r1),r0 + jsr pc,rseek + sys unlink; name + mov mode(r1),0f + sys 0; 9f +.data +9: + sys creat; name; 0:.. +.text + bes crterr + mov r0,r2 +2: + tst mss + bne 3f + cmp r3,$512. + blo 2f +3: + jsr pc,tread + mov r2,r0 + sys write; tapeb; 512. + bes crterr1 + cmp r0,$512. + bne crterr1 + sub r0,r3 + sbc mss + br 2b +2: + mov r3,0f + beq 2f + jsr pc,tread + mov r2,r0 + sys 0; 9f +.data +9: + sys write; tapeb; 0:.. +.text + bes crterr1 + cmp r0,0b + bne crterr1 +2: + mov r2,r0 + sys close + movb gid(r1),0f+1 + movb uid(r1),0f + sys 0; 9f +.data +9: + sys chown; name; 0:.. +.text + mov time0(r1),r0 + mov r1,-(sp) + mov time1(r1),r1 +/ sys 0; 9f +.data +9: + sys smdate; name +.text + mov (sp)+,r1 +1: + rts pc + +crterr1: + clr r0 + mov r1,-(sp) + clr r1 +/ sys smdate; name + mov (sp)+,r1 + mov r2,r0 + sys close + +crterr: + mov $name,r1 + jsr pc,pstr + jsr r5,mesg + < -- create error\n\0>; .even + rts pc diff --git a/source/s2/tp4.s b/source/s2/tp4.s new file mode 100644 index 0000000..1d374c5 --- /dev/null +++ b/source/s2/tp4.s @@ -0,0 +1,49 @@ +/ tap4 -- dec-tape lod/dmp + +.data +tc: +tcx: +mt: +mtx: <0\0> +tboot: +mboot: +.even +.bss +dir: . = .+[mdirent*dirsiz] +tapeb: +map: .=.+4096. +emap: +ch: .=.+1 +flc: .=.+1 +flf: .=.+1 +fli: .=.+1 +flm: .=.+1 +flu: .=.+1 +flv: .=.+1 +flw: .=.+1 +.even + +command:.=.+2 +sum: .=.+2 +size: .=.+2 +nentr: .=.+2 +nused: .=.+2 +nfree: .=.+2 +lused: .=.+2 +catlb: .=.+20. +narg: .=.+2 +rnarg: .=.+2 +parg: .=.+2 +fio: .=.+2 +mss: .=.+2 +ndirent:.=.+2 +ndentd8:.=.+2 +edir: .=.+2 +rseeka: .=.+2 +wseeka: .=.+2 +tapsiz: .=.+2 +name: .=.+32. +name1: .=.+32. +statb: .=.+40. + +smdate = 30. diff --git a/source/s2/tr.c b/source/s2/tr.c new file mode 100644 index 0000000..6b6274a --- /dev/null +++ b/source/s2/tr.c @@ -0,0 +1,144 @@ +int dflag 0; +int sflag 0; +int cflag 0; +int save 0; +char code[256]; +char squeez[256]; +char vect[256]; +struct string { int last, max, rep; char *p; } string1, string2; +int inbuf[259]; + +main(argc,argv) +char **argv; +{ + int i, j; + int c, d; + char *compl; + extern fout; + + string1.last = string2.last = 0; + string1.max = string2.max = 0; + string1.rep = string2.rep = 0; + string1.p = string2.p = ""; + + if(--argc>0) { + argv++; + if(*argv[0]=='-'&&argv[0][1]!=0) { + while(*++argv[0]) + switch(*argv[0]) { + case 'c': + cflag++; + continue; + case 'd': + dflag++; + continue; + case 's': + sflag++; + continue; + } + argc--; + argv++; + } + } + if(argc>0) string1.p = argv[0]; + if(argc>1) string2.p = argv[1]; + for(i=0; i<256; i++) + code[i] = vect[i] = 0; + if(cflag) { + while(c = next(&string1)) + vect[c&0377] = 1; + j = 0; + for(i=1; i<256; i++) + if(vect[i]==0) vect[j++] = i; + vect[j] = 0; + compl = vect; + } + for(i=0; i<256; i++) + squeez[i] = 0; + for(;;){ + if(cflag) c = *compl++; + else c = next(&string1); + if(c==0) break; + d = next(&string2); + if(d==0) d = c; + code[c&0377] = d; + squeez[d&0377] = 1; + } + while(d = next(&string2)) + squeez[d&0377] = 1; + squeez[0] = 1; + for(i=0;i<256;i++) { + if(code[i]==0) code[i] = i; + else if(dflag) code[i] = 0; + } + + inbuf[0] = 0; + fout = dup(1); + close(1); + while((c=getc(inbuf)) >=0 ) { + if(c == 0) continue; + if(c = code[c&0377]&0377) + if(!sflag || c!=save || !squeez[c&0377]) + putchar(save = c); + } + flush(); +} + +next(s) +struct string *s; +{ + int a, b, c, n; + int base; + + if(--s->rep > 0) return(s->last); + if(s->last < s->max) return(++s->last); + if(*s->p=='[') { + nextc(s); + s->last = a = nextc(s); + s->max = 0; + switch(nextc(s)) { + case '-': + b = nextc(s); + if(bp++!=']') + goto error; + s->max = b; + return(a); + case '*': + base = (*s->p=='0')?8:10; + n = 0; + while((c = *s->p)>='0' && c<'0'+base) { + n = base*n + c - '0'; + s->p++; + } + if(*s->p++!=']') goto error; + if(n==0) n = 1000; + s->rep = n; + return(a); + default: + error: + write(1,"Bad string\n",11); + exit(); + } + } + return(nextc(s)); +} + +nextc(s) +struct string *s; +{ + int c, i, n; + + c = *s->p++; + if(c=='\\') { + i = n = 0; + while(i<3 && (c = *s->p)>='0' && c<='7') { + n = n*8 + c - '0'; + i++; + s->p++; + } + if(i>0) c = n; + else c = *s->p++; + } + if(c==0) *--s->p = 0; + return(c&0377); +} diff --git a/source/s2/tty.s b/source/s2/tty.s new file mode 100644 index 0000000..de86382 --- /dev/null +++ b/source/s2/tty.s @@ -0,0 +1,17 @@ +/ tty -- get tty number + +.globl ttyn + + clr r0 + jsr pc,ttyn + movb r0,nam + mov $1,r0 + sys write; name; 5 + sys exit + +.data +name: + +nam: + +.even diff --git a/source/s2/typo.c b/source/s2/typo.c new file mode 100644 index 0000000..0f502f9 --- /dev/null +++ b/source/s2/typo.c @@ -0,0 +1,347 @@ +char number[3]; +int eflg; +char w2006[100]; +flg 0; +char realwd[100]; +char *wd {&realwd[1]}; +char *fptr; +char *ffptr &ffbuf; +char ffbuf[36]; +int neng; +int npr; +int table[2]; /*keep these four cards in order*/ +int tab1[26]; +int tab2[730]; +char tab3[19684]; +int logtab[256]; +float inctab[256]; +char nwd[100]; +int tot; +int wtot; +char *buf[3]; +file[3]; +ptr[3]; +char *name[3]; +bsp[768]; + +main(argc,argv) int argc; char *argv[]; { + char let,lt; + auto arg,t,sw,i,j,salt,er,c; + register k,l,m; + double junk; + int unl(); + int ii; + double log(), exp(), pow(); + + nice(-20); + inctab[0] = 1; + logtab[0] = -10; + for(ii=1; ii<256; ii++){ + inctab[ii] = exp(-ii/30.497); + logtab[ii] = log(30.*pow(1.0333,ii+0.) - 30.) + .5; + } + logtab[1] = -10; + + number[2] = ' '; + buf[0] = bsp; + buf[1] = bsp + 0400; + buf[2] = bsp + 01000; + ptr[0] = 0; ptr[1] = 0; + ptr[2] = 1; + arg = 1; + while(argc>1 && argv[arg][0] == '-') { + switch(argv[arg][1]) { + default: + printf("Unrecognizable argument: %c\n",argv[arg][1]); + exit(); + case 0: + case 'n': + neng++; + break; + case '1': + npr++; + } + arg++; + --argc; + } + if(!neng) { + salt = open("/usr/lib/salt",0); + er = read(salt,table,21200); + if(er != 21200)err("read salt"); + close(salt); + } + if((signal(2,1) & 1) != 1) + signal(2,unl); + name[0] = "/usr/tmp/ttmpa1"; + name[1] = "/usr/tmp/ttmpa2"; + name[2] = "/usr/tmp/ttmpa3"; + while((file[0] = open(name[0],1)) > 0){ + close(file[0]); + for(j=0; j < 3; j++)name[j][13]++; + if(name[0][13] == 'z')err("creat tmp file"); + } + file[0] = creat(name[0],0666); + fptr = argv[arg]; + if(argc == 1) {argc = 2; arg = 0;} + while(--argc){ + if(arg == 0){ + file[2] = 0; + }else{ + file[2] = open(argv[arg++],0); + if(file[2] < 0)err("open input file"); + } + eflg = 1; + while((j = wdval(2)) != 0){ + put(0,nwd,j); + k = -1; + l = 0; + m = 1; + if(inctab[table[0]] > (junk=rand()/32768.)) table[0]++; + while(m <= j){ + c = 27*wd[k++] + wd[l++]; + if(inctab[tab2[c]] > junk) tab2[c]++; + c = 27*c + wd[m++]; + if(inctab[tab3[c]] > junk) tab3[c]++; + } + c = 27*wd[k] + wd[l]; + if(inctab[tab2[c]] > junk) tab2[c]++; + } + if(file[2]) close(file[2]); + } + flsh(0,0); + close(file[0]); + sw = fork(); + if(sw == 0){execl("/usr/bin/usort","usort","-o",name[2],name[0],0); + err("sort"); } + if(sw == -1)err("fork"); + er = wait(); + if(er != sw)err("probs"); + file[0] = creat(name[0],0666); + if(file[0] < 0)err("creat tmp"); + file[1] = open("/usr/lib/w2006",0); + if(file[1] < 0)err("open w2006"); + ptr[1] = 1; + for(k=0;((c = w2006[k] = get(1)) != '\n');k++) + if(c == -1) break; + file[2] = open(name[2],0); + if(file[2] < 0)err("open tmp"); + ptr[2] = 1; + + while(ptr[2]){ + l=0; + for(k=0;((c = wd[k] = get(2)) != '\n');k++) + if(c == -1)goto done; + for(i=0; i<=k;i++){ + if(wd[i] < w2006[l]){ + put(0,wd,k); + break; + } + if(wd[i] > w2006[l]){ + for(l=0;((c = w2006[l] = get(1)) != '\n');l++) + if(c == -1){ + put(0,wd,k); + for(k=0;((c = wd[k] =get(2))!= -1);k++){ + put(0,wd,k); + k = -1; + } + goto done; + } + i = -1; + l=0; + continue; + } + l++; + } + } +done: + close(file[2]); + unlink(name[2]); + flsh(0,0); + close(file[1]); + close(file[0]); + ptr[1] = 1; + file[1] = open(name[0],0); + if(file[1] < 0)err("open tmp "); + file[0] = creat(name[1],0666); + if(file[0] < 0)err("create tmp"); + while((j = nwdval(1)) != 0){ + wtot = 0; + flg = 0; + k = -1; l = 0; m = 1; + while(m <= j){ + tot = 0; + c = wd[k++]*27 + wd[l++]; + tot =+ (logtab[tab2[c]]+logtab[tab2[wd[k]*27+wd[l]]]); + tot =>> 1; + c = c*27 + wd[m++]; + tot =- logtab[tab3[c] & 0377]; + if(tot > wtot) wtot = tot; + } + if(wtot < 0) wtot = 0; + t = conf(wtot,2,number); + put(0,number,2); + put(0,nwd,j); + } + flsh(0,0); + close(file[1]); + close(file[0]); + + sw = fork(); + if(sw == 0){execl("/bin/sort","sort","+0nr", "+1","-o",name[1],name[1] + ,0); + err("sort"); } + if(sw == -1)err("fork"); + er = wait(); + if(er != sw)err("prob"); + + sw = fork(); + if(sw == 0){ + if(npr) { + execl("/bin/cat","cat",name[1],0); + } else { + i = 0 ; + while((c = "Possible typo's in "[i++])!=0) + *ffptr++ = c; + i = 0; + while((c = fptr[i++]) != 0) + *ffptr++ = c; + *ffptr = 0; + execl("/bin/pr","pr","-3", "-h", + ffbuf,name[1],0); + err("pr"); + } + } + if(sw == -1)err("fork"); + er = wait(); + if(er != sw)err("prob"); + unl(); +} + +unl() { + register j; + j = 2; + while(j--)unlink(name[j]); + exit(); +} + + +err(c) char c[];{ + register j; + printf("cannot %s\n",c); + unl(); +} + +get(ifile) int ifile;{ + static char *ibuf[10]; + if(--ptr[ifile]){ + return(*ibuf[ifile]++ & 0377);} + if(ptr[ifile] = read(file[ifile],buf[ifile],512)){ + if(ptr[ifile] < 0)goto prob; + ibuf[ifile] = buf[ifile]; + return(*ibuf[ifile]++ & 0377); + } + ptr[ifile] = 1; + return(-1); + +prob: + ptr[ifile] = 1; + printf("read error\n"); + return(-1); +} + +put(ofile,s,optr) char s[]; { + register i; + + while(optr-- >= 0) + buf[ofile][(ptr[ofile] < 512)?ptr[ofile]++:flsh(ofile,1)] = *s++; + return; +} + +flsh(ofile,i){ + register error; + error = write(file[ofile],buf[ofile],ptr[ofile]); + if(error < 0)goto prob; + + ptr[ofile] = i; + return(0); +prob: + printf("write error on t.%d\n",file[ofile]); + unl(); +} + +wdval(wfile) int wfile; { + static let,wflg; + register j; +beg: + j = -1; + if(wflg == 1){wflg = 0; + goto st; } + while((let = get(wfile)) != '\n'){ +st: + switch(let){ + case -1: return(0); + case '%': if(j != -1)break; + goto ret; + case '-': + if((let = get(wfile)) == '\n'){ + while((let = get(wfile)) == '\n')if(let == -1)return(0); + goto st; } + else {wflg = 1; + goto ret; } + case '\'': + if(eflg != 1){ + if(j < 1)goto beg; + else break; + } + case '.': + if(eflg == 1){ + while((let = get(wfile)) != '\n')if(let == -1)return(0); + goto beg; } + else goto ret; + default: + eflg = 0; + if(let < 'A')goto ret; + if(let <= 'Z'){ wd[++j] = let - 0100; + nwd[j] = let + ' '; + break; } + if(let < 'a' || let > 'z')goto ret; + wd[++j] = let - 0140; + nwd[j] = let; + } + eflg = 0; } + + eflg = 1; +ret: + if(j < 1)goto beg; + nwd[++j] = '\n'; + wd[j] = 0; + return(j); +} + +nwdval(wfile) int wfile;{ + register j; + register char c; + j = -1; + do{ + if(( c = nwd[++j] = get(wfile)) == -1)return(0); + wd[j] = c - 0140; + } + while(c != '\n'); + wd[j] = '\0'; + return(j); +} +conf(n,width,cbuf) char cbuf[]; { + register i,a; + + i = width; + while(i--)cbuf[i] = ' '; + + cbuf[(a = n/10)?conf(a,--width,cbuf):--width] = n%10 + '0'; + + return(++width); +} +rand(){ + static gorp; + gorp = (gorp + 625) & 077777; + return(gorp); +} diff --git a/source/s2/umount.c b/source/s2/umount.c new file mode 100644 index 0000000..98147e2 --- /dev/null +++ b/source/s2/umount.c @@ -0,0 +1,53 @@ +#define NMOUNT 16 +#define NAMSIZ 32 + +struct mtab { + char file[NAMSIZ]; + char spec[NAMSIZ]; +} mtab[NMOUNT]; + +main(argc, argv) +char **argv; +{ + register struct mtab *mp; + register char *p1, *p2; + int mf; + + sync(); + mf = open("/etc/mtab", 0); + read(mf, mtab, NMOUNT*2*NAMSIZ); + if(argc != 2) { + printf("arg count\n"); + return; + } + if (umount(argv[1]) < 0) { + perror("umount"); + return; + } + p1 = argv[1]; + while(*p1++) + ; + p1--; + while(*--p1 == '/') + *p1 = '\0'; + while(p1 > argv[1] && *--p1 != '/') + ; + if(*p1 == '/') + p1++; + argv[1] = p1; + for (mp = mtab; mp < &mtab[NMOUNT]; mp++) { + p1 = argv[1]; + p2 = &mp->spec[0]; + while (*p1++ == *p2) + if (*p2++ == 0) { + for (p1 = mp->file; p1 < &mp->file[NAMSIZ*2];) + *p1++ = 0; + mp = &mtab[NMOUNT]; + while ((--mp)->file[0] == 0); + mf = creat("/etc/mtab", 0644); + write(mf, mtab, (mp-mtab+1)*2*NAMSIZ); + return; + } + } + printf("%s not in mount table\n", argv[1]); +} diff --git a/source/s2/uniq.c b/source/s2/uniq.c new file mode 100644 index 0000000..38373f0 --- /dev/null +++ b/source/s2/uniq.c @@ -0,0 +1,162 @@ +fields 0; +letters 0; +linec; +mode; +uniq; + +main(argc, argv) +int argc; +char *argv[]; +{ + extern fin, fout; + int f; + static char b1[1000], b2[1000]; + +loop: + if(argc > 1) { + if(*argv[1] == '-') { + if(argv[1][1] <= '9') + fields = conv(&argv[1][1]); + else mode = argv[1][1]; + argc--; + argv++; + goto loop; + } + if(*argv[1] == '+') { + letters = conv(&argv[1][1]); + argc--; + argv++; + goto loop; + } + f = open(argv[1], 0); + if(f < 0) { + printf("cannot open %s\n", argv[1]); + exit(); + } + fin = f; + } else + fin = dup(0); + if(argc > 2) { + f = creat(argv[2], 0666); + if(f < 0) { + printf("cannot create %s\n", argv[2]); + exit(); + } + fout = f; + } else + fout = dup(1); + close(0); + close(1); + gline(b1); +l1: + linec++; + if(gline(b2)) { + pline(b1); + flush(); + exit(); + } + if(equal(b1, b2)) goto l1; + pline(b1); + linec = 0; +l2: + linec++; + if(gline(b1)) { + pline(b2); + flush(); + exit(); + } + if(equal(b1, b2)) goto l2; + pline(b2); + linec = 0; + goto l1; +} + +gline(buf) +char buf[]; +{ + int c; + + while((c = getchar()) != '\n') { + if(c == '\0') + return(1); + *buf++ = c; + } + *buf = 0; + return(0); +} + +pline(buf) +char buf[]; +{ + int c; + + switch(mode) { + + case 'u': + if(uniq) {; + uniq = 0; + return; + } + break; + + case 'd': + if(uniq) break; + return; + + case 'c': + printf("%4d ", linec); + } + uniq = 0; + while((c = *buf++) != 0) + putchar(c); + putchar('\n'); +} + +equal(b1, b2) +char b1[], b2[]; +{ + int c; + + b1 = skip(b1); + b2 = skip(b2); + while((c = *b1++) != 0) + if(c != *b2++) return(0); + if(*b2 != 0) + return(0); + uniq++; + return(1); +} + +char * +skip(s) +char *s; +{ + int nf, nl; + + nf = nl = 0; + while(nf++ < fields) { + while(*s==' ' || *s=='\t') + s++; + while( !(*s==' ' || *s=='\t') ) + if(*s == 0) return(s); + else s++; + } + while(nl++ < letters) + if(*s == 0) return(s); + else s++; + return(s); +} + +conv(s) +char *s; +{ + int d, n; + + n = 0; + for(;;) { + d = *s++ - '0'; + if(0>d || d>9) break; + n = n*10 + d; + } + return(n); +} diff --git a/source/s2/units.c b/source/s2/units.c new file mode 100644 index 0000000..060d1e6 --- /dev/null +++ b/source/s2/units.c @@ -0,0 +1,456 @@ +#define NDIM 10 +#define NTAB 601 +char *dfile "/usr/lib/units"; +char *unames[NDIM]; +double getflt(); +int fperr(); +struct unit +{ + double factor; + char dim[NDIM]; +}; + +struct table +{ + double factor; + char dim[NDIM]; + char *name; +} table[NTAB]; +char names[NTAB*10]; +struct prefix +{ + double factor; + char *pname; +} prefix[] +{ + 1e-18, "atto", + 1e-15, "femto", + 1e-12, "pico", + 1e-9, "nano", + 1e-6, "micro", + 1e-3, "milli", + 1e-2, "centi", + 1e-1, "deci", + 1e1, "deka", + 1e2, "hecta", + 1e2, "hecto", + 1e3, "kilo", + 1e6, "mega", + 1e6, "meg", + 1e9, "giga", + 1e12, "tera", + 0.0, 0 +}; +int ibuf[259]; +int fperrc; +int peekc; +int dumpflg; + +main(argc, argv) +char *argv[]; +{ + register i; + register char *file; + struct unit u1, u2; + double f; + + if(argc>1 && *argv[1]=='-') { + argc--; + argv++; + dumpflg++; + } + file = dfile; + if(argc > 1) + file = argv[1]; + if(fopen(file, ibuf) < 0) { + printf("no table\n"); + exit(); + } + ldfps(07600); /* interrupt on fp errors */ + signal(8, fperr); + init(); + close(ibuf[0]); + ibuf[0] = 0; + +loop: + fperrc = 0; + printf("you have: "); + if(convr(&u1)) + goto loop; + if(fperrc) + goto fp; +loop1: + printf("you want: "); + if(convr(&u2)) + goto loop1; + for(i=0; ifactor); + f = 0; + for(i=0; idim[i], i, f); + if(f&1) { + putchar('/'); + f = 0; + for(i=0; idim[i], i, f); + } + putchar('\n'); +} + +pu(u, i, f) +{ + + if(u > 0) { + if(f&2) + putchar('-'); + if(unames[i]) + printf("%s", unames[i]); else + printf("*%c*", i+'a'); + if(u > 1) + putchar(u+'0'); + return(2); + } + if(u < 0) + return(1); + return(0); +} + +convr(up) +struct unit *up; +{ + register struct unit *p; + register c; + register char *cp; + char name[20]; + int den, err; + + p = up; + for(c=0; cdim[c] = 0; + p->factor = getflt(); + if(p->factor == 0.) + p->factor = 1.0; + err = 0; + den = 0; + cp = name; + +loop: + switch(c=get()) { + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + case '/': + case ' ': + case '\t': + case '\n': + if(cp != name) { + *cp++ = 0; + cp = name; + err =| lookup(cp, p, den, c); + } + if(c == '/') + den++; + if(c == '\n') + return(err); + goto loop; + } + *cp++ = c; + goto loop; +} + +lookup(name, up, den, c) +char *name; +struct unit *up; +{ + register struct unit *p; + register struct table *q; + register i; + char *cp1, *cp2; + double e; + + p = up; + e = 1.0; + +loop: + q = hash(name); + if(q->name) { + l1: + if(den) { + p->factor =/ q->factor*e; + for(i=0; idim[i] =- q->dim[i]; + } else { + p->factor =* q->factor*e; + for(i=0; idim[i] =+ q->dim[i]; + } + if(c >= '2' && c <= '9') { + c--; + goto l1; + } + return(0); + } + for(i=0; cp1 = prefix[i].pname; i++) { + cp2 = name; + while(*cp1 == *cp2++) + if(*cp1++ == 0) { + cp1--; + break; + } + if(*cp1 == 0) { + e =* prefix[i].factor; + name = cp2-1; + goto loop; + } + } + for(cp1 = name; *cp1; cp1++); + if(cp1 > name+1 && *--cp1 == 's') { + *cp1 = 0; + goto loop; + } + printf("cannot recognize %s\n", name); + return(1); +} + +equal(s1, s2) +char *s1, *s2; +{ + register char *c1, *c2; + + c1 = s1; + c2 = s2; + while(*c1++ == *c2) + if(*c2++ == 0) + return(1); + return(0); +} + +init() +{ + register char *cp; + register struct table *tp, *lp; + int c, i, f, t; + char *np; + + cp = names; + for(i=0; iname = np; + lp->factor = 1.0; + lp->dim[i] = 1; + } + lp = hash(""); + lp->name = cp-1; + lp->factor = 1.0; + +l0: + c = get(); + if(c == 0) { + printf("%l units; %l bytes\n\n", i, cp-names); + if(dumpflg) + for(tp = &table[0]; tp < &table[NTAB]; tp++) { + if(tp->name == 0) + continue; + printf("%s", tp->name); + units(tp); + } + return; + } + if(c == '/') + while(c != '\n') + c = get(); + if(c == '\n') + goto l0; + np = cp; + while(c != ' ' && c != '\t') { + *cp++ = c; + c = get(); + if(c == '\n') { + *cp++ = 0; + tp = hash(np); + if(tp->name) + goto redef; + tp->name = np; + tp->factor = lp->factor; + for(c=0; cdim[c] = lp->dim[c]; + i++; + goto l0; + } + } + *cp++ = 0; + lp = hash(np); + if(lp->name) + goto redef; + convr(lp); + lp->name = np; + f = 0; + i++; + if(lp->factor != 1.0) + goto l0; + for(c=0; cdim[c]; + if(t>1 || (f>0 && t!=0)) + goto l0; + if(f==0 && t==1) { + if(unames[c]) + goto l0; + f = c+1; + } + } + if(f>0) + unames[f-1] = np; + goto l0; + +redef: + printf("redefination %s\n", np); + goto l0; +} + +double +getflt() +{ + register c, i, dp; + double d, e; + int f; + + d = 0.; + dp = 0; + do + c = get(); + while(c == ' ' || c == '\t'); + +l1: + if(c >= '0' && c <= '9') { + d = d*10. + c-'0'; + if(dp) + dp++; + c = get(); + goto l1; + } + if(c == '.') { + dp++; + c = get(); + goto l1; + } + if(dp) + dp--; + if(c == '+' || c == '-') { + f = 0; + if(c == '-') + f++; + i = 0; + c = get(); + while(c >= '0' && c <= '9') { + i = i*10 + c-'0'; + c = get(); + } + if(f) + i = -i; + dp =- i; + } + e = 1.; + i = dp; + if(i < 0) + i = -i; + while(i--) + e =* 10.; + if(dp < 0) + d =* e; else + d =/ e; + if(c == '|') + return(d/getflt()); + peekc = c; + return(d); +} + +get() +{ + register c; + + if(c=peekc) { + peekc = 0; + return(c); + } + c = getc(ibuf); + if(c <= 0) { + if(ibuf[0]) + return(0); + printf("\n"); + exit(); + } + return(c); +} + +hash(name) +char *name; +{ + register struct table *tp; + register char *np; + register h; + + h = 0; + np = name; + while(*np) + h = h*57 + *np++ - '0'; + h = lrem(0, h, NTAB); + tp = &table[h]; +l0: + if(tp->name == 0) + return(tp); + if(equal(name, tp->name)) + return(tp); + tp++; + if(tp >= &table[NTAB]) + tp = table; + goto l0; +} + +fperr() +{ + + signal(8, fperr); + fperrc++; +} diff --git a/source/s2/update.s b/source/s2/update.s new file mode 100644 index 0000000..841894b --- /dev/null +++ b/source/s2/update.s @@ -0,0 +1,17 @@ + sys fork + br 1f + sys exit +1: + clr r0 + sys close + mov $1,r0 + sys close + mov $2,r0 + sys close +1: + sys sync + mov $30.,r0 + sys sleep + br 1b +sleep = 35. +sync = 36. diff --git a/source/s2/usort.c b/source/s2/usort.c new file mode 100644 index 0000000..8f58766 --- /dev/null +++ b/source/s2/usort.c @@ -0,0 +1,649 @@ +#define L 512 +#define N 7 +#define C 20 +#define MEM (16*2048) +#define NF 10 + +int ibuf[259]; +int obuf[259]; +char *file; +char *filep; +int nfiles; +int nlines; +int ntext; +int *lspace; +char *tspace; +int cmp(); +int term(); +int mflg; +char *outfil; +char tabchar; +int eargc; +char **eargv; + +char fold[128] { + 0000,0001,0002,0003,0004,0005,0006,0007, + 0010,0011,0012,0013,0014,0015,0016,0017, + 0020,0021,0022,0023,0024,0025,0026,0027, + 0030,0031,0032,0033,0034,0035,0036,0037, + 0040,0041,0042,0043,0044,0045,0046,0047, + 0050,0051,0052,0053,0054,0055,0056,0057, + 0060,0061,0062,0063,0064,0065,0066,0067, + 0070,0071,0072,0073,0074,0075,0076,0077, + 0100,0101,0102,0103,0104,0105,0106,0107, + 0110,0111,0112,0113,0114,0115,0116,0117, + 0120,0121,0122,0123,0124,0125,0126,0127, + 0130,0131,0132,0133,0134,0134,0136,0137, + 0140,0101,0102,0103,0104,0105,0106,0107, + 0110,0111,0112,0113,0114,0115,0116,0117, + 0120,0121,0122,0123,0124,0125,0126,0127, + 0130,0131,0132,0173,0174,0175,0176,0177 +}; +char nofold[128]; +char dict[128] { + 1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1 +}; +char nodict[128] { 1 }; + +struct field { + char *code; + char *ignore; + int nflg; + int rflg; + int bflg; + char *m[2]; + char *n[2]; +} fields[NF]; +int proto[9] { + &fold, + &nodict, + 0, + 1, + 0, + 0,-1, + 0,0 +}; +int nfields; +int error 1; + +main(argc, argv) +char **argv; +{ + register a, i; + char *arg; + register int *p; + int *q; + + for(a=0; a<128; a++) + nofold[a] = a; + nodict[127] = 1; + copyproto(); + eargv = argv; + while (--argc > 0) { + if(**++argv == '-') for(arg = *argv;;) { + switch(*++arg) { + case '\0': + if(arg[-1] == '-') + eargv[eargc++] = "-"; + break; + + case 'm': + mflg++; + continue; + + case 'o': + if(--argc > 0) + outfil = *++argv; + continue; + + default: + field(++*argv,1); + break; + } + break; + } else if (**argv == '+') { + if(++nfields>=NF) { + mess("Too many keys\n"); + exit(1); + } + copyproto(); + field(++*argv,0); + } else + eargv[eargc++] = *argv; + } + q = &fields[0]; + for(a=1; a<=nfields; a++) { + p = &fields[a]; + for(i=0; i<5; i++) /*sensitive to sizeof(proto)*/ + if(p[i] != proto[i]) + goto next; + for(i=0; i<5; i++) + p[i] = q[i]; +next: ; + } + if(eargc == 0) + eargv[eargc++] = "-"; + + a = MEM; + i = lspace = sbrk(0); + while(brk(a) == -1) + a =- 512; + brk(a =- 512); /* for recursion */ + a =- i; + nlines = ((a-L)>>1) & 077777; + nlines =/ 5; + ntext = nlines*8; + tspace = lspace+nlines; + file = "/usr/tmp/stmXaa"; +loop: + filep = file; + while(*filep != 'X') + filep++; + for(*filep = 'a';;(*filep)++) { + if(stat(file, lspace) < 0) { + a = creat(file, 0600); + if(a >= 0) + break; + } + if(*filep == 'z') { + if(file[1] != 't') { + file = "/tmp/stmXaa"; + goto loop; + } + mess("Cannot locate temp\n"); + exit(1); + } + } + close(a); + filep++; + if ((signal(2, 1) & 01) == 0) + signal(2, term); + nfiles = eargc; + if(!mflg) { + ibuf[0] = -1; + sort(); + close(0); + } + for(a = mflg?0:eargc; a+N < nfiles; a=+N) { + newfile(); + merge(a, a+N); + } + if(a != nfiles) { + oldfile(); + merge(a, nfiles); + } + error = 0; + term(); +} + +sort() +{ + register char *cp; + register *lp, c; + int done; + int i; + int f; + + done = 0; + i = 0; + do { + cp = tspace; + lp = lspace; + while(lp < lspace+nlines && cp < tspace+ntext) { + *lp++ = cp; + while((*cp++ = c = getc(ibuf)) != '\n') { + if(c >= 0) continue; + cp--; + close(ibuf[0]); + if(i < eargc) { + if((f = setfil(i++)) == 0) + ibuf[0] = 0; + else if(fopen(f, ibuf) < 0) + cant(f); + } else + break; + } + if(c < 0) { + done++; + lp--; + break; + } + } + qsort(lspace, lp-lspace, 2, cmp); + if(done == 0 || nfiles != eargc) + newfile(); else + oldfile(); + while(lp > lspace) { + cp = *--lp; + if(*cp) + do + putc(*cp, obuf); + while(*cp++ != '\n'); + } + fflush(obuf); + close(obuf[0]); + } while(done == 0); +} + +struct merg +{ + char l[L]; + int b[259]; +}; + +merge(a, b) +{ + register struct merg *p; + register char *cp; + register i; + struct { int *ip;}; + int f; + int j; + int k,l,c; + + p = lspace; + j = 0; + for(i=a; ib[0] = dup(0); + else if(fopen(f, p->b) < 0) + cant(f); + ibuf[j] = p; + if(!rline(p)) j++; + p++; + } + + do { + i = j; + qsort(ibuf, i, 2, cmp); + l = 0; + while(i--) { + cp = ibuf[i]; + if(*cp == '\0') { + l = 1; + if(rline(ibuf[i])) { + k = i; + while(++k < j) + ibuf[k-1] = ibuf[k]; + j--; + } + } + } + } while(l); + + i = j; + if(i > 0) for(;;) { + cp = ibuf[i-1]; + if(i == 1 || cmp(&ibuf[i-1], &ibuf[i-2])) + do + putc(*cp, obuf); + while(*cp++ != '\n'); + if(rline(ibuf[i-1])) { + i--; + if(i == 0) + break; + } + cp = &ibuf[i]; + while (--cp.ip > ibuf && cmp(cp.ip, cp.ip-1) < 0) { + p = *cp.ip; + *cp.ip = *(cp.ip-1); + *(cp.ip-1) = p; + } + } + p = lspace; + for(i=a; ib[0]); + p++; + if(i >= eargc) + close(creat(setfil(i))); + } + fflush(obuf); + close(obuf[0]); +} + +rline(mp) +struct merg *mp; +{ + register char *cp; + register *bp, c; + + bp = mp->b; + cp = mp->l; + do { + c = getc(bp); + if(c < 0) + return(1); + *cp++ = c; + } while(c != '\n'); + *cp = '\0'; + return(0); +} + +newfile() +{ + + if(fcreat(setfil(nfiles), obuf) < 0) { + mess("Can't create temp\n"); + term(); + } + nfiles++; +} + +char * +setfil(i) +{ + + if(i < eargc) + if(eargv[i][0] == '-' && eargv[i][1] == '\0') + return(0); + else + return(eargv[i]); + i =- eargc; + filep[0] = i/26 + 'a'; + filep[1] = i%26 + 'a'; + return(file); +} + +oldfile() +{ + + if(outfil) { + if(fcreat(outfil, obuf) < 0) { + mess("Can't create output\n"); + term(); + } + } else + obuf[0] = 1; +} + +cant(f) +{ + mess("Can't open "); + mess(f); + mess("\n"); + term(); +} + +term() +{ + register i; + + if(nfiles == eargc) + nfiles++; + for(i=eargc; im[j]) < 0) + return(-1); + while(i-- > 0) { + if(tabchar != 0) { + while(*p != tabchar) + if(*p != '\n') + p++; + else goto ret; + p++; + } else { + while(blank(*p)) + p++; + while(!blank(*p)) + if(*p != '\n') + p++; + else goto ret; + } + } + if(fp->bflg) + while(blank(*p)) + p++; + i = fp->n[j]; + while(i-- > 0) { + if(*p != '\n') + p++; + else goto ret; + } +ret: + return(p); +} + +digit(c) +{ + + return(c <= '9' && c >= '0'); +} + +mess(s) +char *s; +{ + while(*s) + write(2, s++, 1); +} + +copyproto() +{ + register int i, *p, *q; + + p = proto; + q = &fields[nfields]; + for(i=0; icode = nofold; + break; + + case 'b': + p->bflg++; + break; + + case 'd': + p->ignore = dict; + break; + + case 'n': + p->nflg++; + break; + case 't': + tabchar = *++s; + if(tabchar == 0) s--; + break; + + case 'r': + p->rflg = -1; + break; + + default: + p->m[k] = number(&s); + if(*s == '.') + s++; + p->n[k] = number(&s); + s--; + } + } +} + +number(ppa) +char **ppa; +{ + int n; + register char *pa; + pa = *ppa; + n = 0; + while(digit(*pa)) + n = n*10 + *pa++ - '0'; + *ppa = pa; + return(n); +} + +blank(c) +{ + if(c==' ' || c=='\t') + return(1); + return(0); +} + +int (*qscmp)(); +int qses; + +qsort(a, n, es, fc) +char *a; +int n, es; +int (*fc)(); +{ + qscmp = fc; + qses = es; + qs1(a, a+n*es); +} + +qs1(a, l) +char *a, *l; +{ + register char *i, *j, *es; + char **k; + char *lp, *hp; + int n, c; + + + es = qses; + +start: + if((n=l-a) <= es) + return; + + + n = ((n/(2*es))*es) & 077777; + hp = lp = a+n; + i = a; + j = l-es; + + + for(;;) { + if(i < lp) { + if((c = (*qscmp)(i, lp)) == 0) { + qsexc(i, lp =- es); + continue; + } + if(c < 0) { + i =+ es; + continue; + } + } + +loop: + if(j > hp) { + if((c = (*qscmp)(hp, j)) == 0) { + qsexc(hp =+ es, j); + goto loop; + } + if(c > 0) { + if(i == lp) { + qstexc(i, hp =+ es, j); + i = lp =+ es; + goto loop; + } + qsexc(i, j); + j =- es; + i =+ es; + continue; + } + j =- es; + goto loop; + } + + + if(i == lp) { + for(k=lp+2; k<=hp;) *(*k++)='\0'; + if(lp-a >= l-hp) { + qs1(hp+es, l); + l = lp; + } else { + qs1(a, lp); + a = hp+es; + } + goto start; + } + + + qstexc(j, lp =- es, i); + j = hp =- es; + } +} + +qsexc(i, j) +char *i, *j; +{ + register char *ri, *rj, c; + int n; + + n = qses; + ri = i; + rj = j; + do { + c = *ri; + *ri++ = *rj; + *rj++ = c; + } while(--n); +} + +qstexc(i, j, k) +char *i, *j, *k; +{ + register char *ri, *rj, *rk; + char c; + int n; + + n = qses; + ri = i; + rj = j; + rk = k; + do { + c = *ri; + *ri++ = *rk; + *rk++ = *rj; + *rj++ = c; + } while(--n); +} diff --git a/source/s2/wall.c b/source/s2/wall.c new file mode 100644 index 0000000..3259354 --- /dev/null +++ b/source/s2/wall.c @@ -0,0 +1,68 @@ +char mesg[3000]; +int msize; +struct +{ + char name[8]; + char tty[2]; + int time[2]; + int junk; +} utmp[50]; + +main(argc, argv) +char *argv[]; +{ + register i, *p; + int f; + + f = open("/etc/utmp", 0); + if(f < 0) { + printf("utmp?\n"); + exit(); + } + read(f, utmp, sizeof utmp); + close(f); + f = 0; + if(argc >= 2) { + f = open(argv[1], 0); + if(f < 0) { + printf("%s?\n", argv[1]); + exit(); + } + } + while((i = read(f, &mesg[msize], sizeof mesg - msize)) > 0) + msize =+ i; + close(f); + for(i=0; itty[0] == 0) + continue; + sleep(1); + sendmes(p->tty[0]); + } +} + +sendmes(tty) +{ + register i; + register char *s; + + i = fork(); + if(i == -1) { + printf("try again\n"); + return; + } + if(i) + return; + s = "/dev/ttyx"; + s[8] = tty; + i = open(s, 1); + if(i < 0) { + printf("cannot open tty%c\n", tty); + exit(); + } + close(1); + dup(i); + printf("Broadcast Message ...\n\n"); + write(1, mesg, msize); + exit(); +} diff --git a/source/s2/wc.c b/source/s2/wc.c new file mode 100644 index 0000000..ee6e106 --- /dev/null +++ b/source/s2/wc.c @@ -0,0 +1,73 @@ +/* wc line and word count */ + +int buf[259]; +int wordct[2]; +int twordct[2]; +int linect[2]; +int tlinect[2]; + +main(argc,argv) +char **argv; +{ + int i, token; + register char *p1, *p2; + register int c; + + i = 1; + do { + if(argc<=1) buf[0] = 0; + else if(fopen(argv[i],buf)<0) { + diag(argv[i]); + diag(": cannot open\n"); + continue; + } + p1 = 0; + p2 = 0; + linect[0] = linect[1] = 0; + wordct[0] = wordct[1] = 0; + token = 0; + for(;;) { + if(p1 >= p2) { + p1 = &buf[1]; + c = read(buf[0], p1, 512); + if(c <= 0) + break; + p2 = p1+c; + } + c = 0; + c =| *p1++; + if(' ' 2) { + printf("%7s ",locv(tlinect[0],tlinect[1])); + printf("%7s ",locv(twordct[0],twordct[1])); + printf("total\n"); + } +} + +diag(s) +char *s; +{ + while(*s) + write(2,s++,1); +} diff --git a/source/s2/who.c b/source/s2/who.c new file mode 100644 index 0000000..86a273c --- /dev/null +++ b/source/s2/who.c @@ -0,0 +1,68 @@ +/* + * who + */ + +int fout; +int buf[256]; + +main(argc, argv) +char **argv; +{ + char *s, *cbuf; + int n, fi, i; + int tty; + struct { + char name[8]; + char tty; + char pad1; + int time[2]; + char pad2[2]; + } *p; + + s = "/etc/utmp"; + if(argc == 2) + s = argv[1]; + fi = open(s, 0); + if(fi < 0) { + write("cannot open wtmp\n", 17); + exit(); + } + fout = dup(1); + close(1); + if (argc==3) + tty = ttyn(0); + +loop: + n = read(fi, buf, 512); + if(n == 0) { + flush(); + if (argc==3) + write(fout, "Nobody.\n", 8); + exit(); + } + + p = &buf; + for(p = &buf; (n =- 16)>=0; p++) { + if (argc==3 && tty!=p->tty) + continue; + if(p->name[0] == '\0' && argc==1) + continue; + for(i=0; i<8; i++) { + if(p->name[i] == '\0') + p->name[i] = ' '; + putchar(p->name[i]); + } + for(i=0; i<3; i++) + putchar("tty"[i]); + putchar(p->tty); + cbuf = ctime(p->time); + for(i=3; i<16; i++) + putchar(cbuf[i]); + putchar('\n'); + if (argc==3) { + flush(); + exit(); + } + } + goto loop; +} diff --git a/source/s2/write.s b/source/s2/write.s new file mode 100644 index 0000000..e249acd --- /dev/null +++ b/source/s2/write.s @@ -0,0 +1,204 @@ +/ write -- write to another user + +.globl ttyn + + cmp (sp)+,$2 + beq 1f + bgt 2f + mov $1,r0 + sys write; argm; eargm-argm + sys exit +2: + movb *4(sp),ltty +1: + tst (sp)+ + mov (sp)+,r5 + sys open; utmp; 0 + bec 1f + mov $1,r0 + sys write; film; efilm-film + sys exit +1: + mov r0,ufil +1: + mov ufil,r0 + sys read; ubuf; 16. + tst r0 + bne 2f + jmp 8f +2: + tstb ltty + beq 2f + cmpb ltty,8.+ubuf + bne 1b +2: + mov $ubuf,r3 + mov r5,r4 + mov $9.,r2 +2: + dec r2 + beq 2f + cmpb (r4)+,(r3)+ + beq 2b + tstb -1(r4) + bne 1b + cmpb $' ,-1(r3) + bne 1b +2: + movb 8.+ubuf,ttyno + sys open; ttyx; 1 + bes 3f + sys stat; ttyx; statbuf + bes 3f + bit $2,statbuf+4 + bne 2f +3: + mov $1,r0 + sys write; dnymes; ednymes-dnymes + sys exit +2: + mov r0,ttyf + clr r0 + jsr pc,ttyn + mov r0,r3 + mov statbuf,r4 + mov ufil,r0 + sys seek; 0; 0 +1: + mov ufil,r0 + sys read; ubuf; 16. + tst r0 + beq unknown + cmp r3,ubuf+8. + bne 1b + mov $ubuf,r0 + mov $8.,r1 +1: + cmpb $' ,(r0)+ + beq 1f + dec r1 + bne 1b +1: + neg r1 + add $8,r1 + mov r1,0f +6: + mov ttyf,r0 + sys write; mesg; emesg-mesg + mov ttyf,r0 + sys 0; 5f +.data +5: + sys write; ubuf; 0:2 +.text + mov ttyf,r0 + sys write; qnl; 4 + sys signal; 2; 9f +7: + clr r0 + sys read; ch; 1 + tst r0 + beq 9f + tst nlflg + beq 1f + cmp ch,$'! + bne 1f + sys fork + br mshproc + sys wait + mov $1,r0 + sys write; excl; 2 + br 7b +1: + clr nlflg + cmp ch,$'\n + bne 1f + inc nlflg +1: + mov ttyf,r0 + sys write; ch; 1 + br 7b +8: + movb (r5)+,ch + beq 8f + mov $1,r0 + sys write; ch; 1 + br 8b +8: + tstb ltty + beq 8f + mov $1,r0 + sys write; ltty-1; 2 +8: + mov $1,r0 + sys write; errmsg; eerrmsg-errmsg + sys exit +9: + mov ttyf,r0 + sys write; endmsg; eendmsg-endmsg + sys exit + +unknown: + mov $"??,ubuf + br 6b + +mshproc: + sys exec; msh; mshp + sys exit + +.data +nlflg: + 1 +.text + +mshp: + msh + minust + 0 +msh: + +minust: + <-t\0> +argm: + +eargm: +film: + +efilm: +.data + < > / is ltty -1 +ltty: + .=.+1 +.text +excl: + +qnl: + <...\n> +.data +ttyx: + +ttyno = .-2 +.text +utmp: + +endmsg: + +eendmsg: +errmsg: + < not logged in.\n> +eerrmsg: +mesg: + <\nMessage from > +emesg: +dnymes: + +ednymes: + .even + .bss + +ttyf: .=.+2 +ubuf: .=.+16. +statbuf:.=.+40. +ch: .=.+2 +ufil: .=.+2 +signal = 48. diff --git a/source/s3/atan.s b/source/s3/atan.s new file mode 100644 index 0000000..412cd57 --- /dev/null +++ b/source/s3/atan.s @@ -0,0 +1,212 @@ +ldfps = 170100^tst +stfps = 170200^tst +/ +.globl atan, _atan +.globl atan2, _atan2 +/ +/ floating-point arctangent +/ +/ atan replaces the value in fr0 by its arctangent +/ in the range [-pi/2,pi/2]. +/ +/ atan2 places in fr0 the arctangent of fr0/fr1 +/ in the range [-pi,pi]. +/ +/ there are no error exits +/ +/ coefficients are #5076 from Hart & Cheney. +/ +/ + +_atan: + mov r5,-(sp) + mov sp,r5 + movf 4(r5),fr0 + jsr pc,atan + br 1f + +_atan2: + mov r5,-(sp) + mov sp,r5 + movf 4(r5),fr0 + movf 12.(r5),fr1 + jsr pc,atan2 +1: + mov (sp)+,r5 + rts pc +atan: + jsr r0,save + tstf fr0 + cfcc + blt 1f + jsr pc,satan + br ret +1: + negf fr0 + jsr pc,satan + negf fr0 + br ret +/ +atan2: + jsr r0,save + clr -(sp) + tstf fr0 + cfcc + bge 1f + inc (sp) + negf fr0 +1: + tstf fr1 + cfcc + beq 2f + bgt 1f + add $2,(sp) + negf fr1 +1: + divf fr1,fr0 + jsr pc,satan + br 1f +2: + movf pi2,fr0 +1: + bit $2,(sp) + beq 1f + negf fr0 + addf pi2,fr0 + addf pi2,fr0 +1: + bit $1,(sp)+ + beq 1f + negf fr0 +1: + +ret: + ldfps (sp)+ + movf (sp)+,fr3 + movf (sp)+,fr2 + movf (sp)+,fr1 + mov (sp)+,r0 + rts pc + +save: + movf fr1,-(sp) + movf fr2,-(sp) + movf fr3,-(sp) + stfps -(sp) + ldfps $40200 / DP, no interrupt + jmp (r0) + +satan: + cmpf sq2m1,fr0 + cfcc + bge arctan + cmpf sq2p1,fr0 + cfcc + bgt 1f + movf one,fr1 + divf fr0,fr1 + movf fr1,fr0 + jsr pc,arctan + negf fr0 + addf pi2,fr0 + rts pc +1: + movf fr0,fr1 + subf one,fr0 + addf one,fr1 + divf fr1,fr0 + jsr pc,arctan + addf pi4,fr0 + rts pc +arctan: + mov $p4p,r0 + mov $4,-(sp) + movf fr0,fr3 + mulf fr3,fr3 + movf *(r0)+,fr1 +1: + mulf fr3,fr1 + addf *(r0)+,fr1 + dec (sp) + bne 1b + mov $4,(sp) + movf fr3,fr2 + br 2f +1: + mulf fr3,fr2 +2: + addf *(r0)+,fr2 + dec (sp) + bne 1b + tst (sp)+ + divf fr2,fr1 + mulf fr1,fr0 + rts pc + +.data + +p4p: + p4;p3;p2;p1;p0 + q3;q2;q1;p0 + +one: 40200;0;0;0 +pi2: 40311;7732;121041;64302 +pi4: 40111;7732;121041;64302 + +sq2p1: 40432 + 101171 + 114774 + 167461 + +sq2m1: 37724 + 11714 + 147747 + 74621 + +p4: 37442 + 145026 + 75504 + 15621 +p3: 40725 + 21566 + 115517 + 50305 +p2: 41443 + 160206 + 172714 + 25441 +p1: 41632 + 172223 + 76027 + 56645 +p0: 41462 + 25125 + 6152 + 126064 +q3: 41170 + 10112 + 141724 + 64324 +q2: 41573 + 53776 + 25372 + 71522 +q1: 41670 + 123114 + 51576 + 75020 + +/ one = 1.00000 00000 00000 00000 d0 +/ sq2p1=2.41421 35623 73095 04880 d0 +/ sq2m1= .41421 35623 73095 04880 d0 +/ pi2 = 1.57079 63267 94896 61923 d0 +/ p4 = .15897 40288 48230 7048 d0 +/ p3 = .66605 79017 00926 2658 d1 +/ p2 = .40969 26483 21022 5637 d2 +/ p1 = .77477 68771 92042 0862 d2 +/ p0 = .44541 34005 92906 8032 d2 +/ q4 = .10000 00000 00000 0000 d1 +/ q3 = .15503 97755 14219 8753 d2 +/ q2 = .62835 93051 10323 7683 d2 +/ q1 = .92324 80107 23009 7484 d2 +/ q0 = .44541 34005 92906 8044 d2 diff --git a/source/s3/crypt.s b/source/s3/crypt.s new file mode 100644 index 0000000..d0fa96e --- /dev/null +++ b/source/s3/crypt.s @@ -0,0 +1,155 @@ +/ crypt -- password incoding + +/ mov $key,r0 +/ jsr pc,crypt + +.globl crypt, _crypt +.globl savr5 + +_crypt: + mov r5,-(sp) + mov sp,r5 + mov r5,savr5 + mov 4(r5),r0 + jsr pc,crypt + clr savr5 + mov (sp)+,r5 + rts pc + +crypt: + mov r1,-(sp) + mov r2,-(sp) + mov r3,-(sp) + mov r4,-(sp) + mov r5,-(sp) + + mov r0,r1 + mov $key,r0 + movb $004,(r0)+ + movb $034,(r0)+ +1: + cmp r0,$key+64. + bhis 1f + movb (r1)+,(r0)+ + bne 1b +1: + dec r0 +/ +/ +/ fill out key space with clever junk +/ + mov $key,r1 +1: + movb -1(r0),r2 + movb (r1)+,r3 + xor r3,r2 + movb r2,(r0)+ + cmp r0,$key+128. + blo 1b +/ +/ +/ establish wheel codes and cage codes +/ + mov $wheelcode,r4 + mov $cagecode,r5 + mov $256.,-(sp) +2: + clr r2 + clr (r4) + mov $wheeldiv,r3 +3: + clr r0 + mov (sp),r1 + div (r3)+,r0 + add r1,r2 + bic $40,r2 + bis shift(r2),(r4) + cmp r3,$wheeldiv+6. + bhis 4f + bis shift+4(r2),(r5) +4: + cmp r3,$wheeldiv+10. + blo 3b + sub $2,(sp) + tst (r4)+ + tst (r5)+ + cmp r4,$wheelcode+256. + blo 2b + tst (sp)+ +/ +.data +shift: 1;2;4;10;20;40;100;200;400;1000;2000;4000;10000;20000;40000;100000 + 1;2 +wheeldiv: 32.; 18.; 10.; 6.; 4. +.bss +cagecode: .=.+256. +wheelcode: .=.+256. +.text +/ +/ +/ make the internal settings of the machine +/ both the lugs on the 128 cage bars and the lugs +/ on the 16 wheels are set from the expanded key +/ + mov $key,r0 + mov $cage,r2 + mov $wheel,r3 +1: + movb (r0)+,r1 + bic $!177,r1 + asl r1 + mov cagecode(r1),(r2)+ + mov wheelcode(r1),(r3)+ + cmp r0,$key+128. + blo 1b +/ +/ +/ now spin the cage against the wheel to produce output. +/ + mov $word,r4 + mov $wheel+128.,r3 +3: + mov -(r3),r2 + mov $cage,r0 + clr r5 +1: + bit r2,(r0)+ + beq 2f + incb r5 +2: + cmp r0,$cage+256. + blo 1b +/ +/ we have a piece of output from current wheel +/ it needs to be folded to remove lingering hopes of +/ inverting the function +/ + mov r4,-(sp) + clr r4 + div $26.+26.+10.,r4 + add $'0,r5 + cmp r5,$'9 + blos 1f + add $'A-'9-1,r5 + cmp r5,$'Z + blos 1f + add $'a-'Z-1,r5 +1: + mov (sp)+,r4 + movb r5,(r4)+ + cmp r4,$word+8. + blo 3b +/ + + mov (sp)+,r5 + mov (sp)+,r4 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r1 + mov $word,r0 + rts pc +.bss +key: .=.+128. +word: .=.+32. +cage: .=.+256. +wheel: .=.+256. diff --git a/source/s3/dpadd.s b/source/s3/dpadd.s new file mode 100644 index 0000000..db3d2ab --- /dev/null +++ b/source/s3/dpadd.s @@ -0,0 +1,19 @@ +/ C library -- signed dp add + +/ dpadd(l, i) +/ int l[2]; +/ l =+ i; + +.globl _dpadd + +_dpadd: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),r0 + tst 6(r5) + sxt r1 + add r1,(r0)+ + add 6(r5),(r0) + adc -(r0) + mov (sp)+,r5 + rts pc diff --git a/source/s3/ecvt.s b/source/s3/ecvt.s new file mode 100644 index 0000000..5fc401c --- /dev/null +++ b/source/s3/ecvt.s @@ -0,0 +1,176 @@ +ldfps = 170100^tst +stfps = 170200^tst +/ ftoa -- basic g fp conversion + +.globl _ndigit +.globl ecvt +.globl fcvt + + +/ ecvt converts fr0 into decimal +/ the string of converted digits is pointed to by r0. +/ the number of digits are specified by _ndigit +/ r2 contains the decimal point +/ r1 contains the sign + +.globl _ecvt, _fcvt + +_ecvt: + mov r5,-(sp) + mov sp,r5 + mov r2,-(sp) + movf 4(r5),fr0 + mov 14(r5),_ndigit + jsr pc,ecvt + br 1f + +_fcvt: + mov r5,-(sp) + mov sp,r5 + mov r2,-(sp) + movf 4(r5),fr0 + mov 14(r5),_ndigit + jsr pc,fcvt +1: + mov r2,*16(r5) + mov r1,*20(r5) + mov (sp)+,r2 + mov (sp)+,r5 + rts pc + +fcvt: + clr eflag + br 1f +ecvt: + mov $1,eflag +1: + stfps -(sp) + ldfps $200 + movf fr0,-(sp) + movf fr1,-(sp) + mov r3,-(sp) + mov $buf,r1 + clr r2 + clr sign + tstf fr0 + cfcc + beq zer + bgt 1f + inc sign + negf fr0 +1: + modf $one,fr0 + tstf fr1 + cfcc + beq lss + +gtr: + movf fr0,-(sp) + movf fr1,fr0 +1: + mov $buftop,r3 +1: + modf tenth,fr0 + movf fr0,fr2 + movf fr1,fr0 + addf $epsilon,fr2 + modf $ten,fr2 + movfi fr3,r0 + add $'0,r0 + movb r0,-(r3) + inc r2 + tstf fr0 + cfcc + bne 1b +/ + mov $buf,r1 +1: + movb (r3)+,(r1)+ + cmp r3,$buftop + blo 1b +/ + movf (sp)+,fr0 + br pad + +zer: + inc r2 + br pad + +lss: + dec r2 + modf $ten,fr0 + tstf fr1 + cfcc + beq lss + inc r2 + jsr pc,digit1 + +pad: + jsr pc,digit + br out + br pad + +digit: + cmp r1,$buftop + bhis 1f + add $2,(sp) + modf $ten,fr0 + +digit1: + movfi fr1,r0 + add $'0,r0 + movb r0,(r1)+ +1: + rts pc +/ +out: + mov $buf,r0 + add _ndigit,r0 + tst eflag + bne 1f + add r2,r0 +1: + cmp r0,$buf + blo outout + movb (r0),r3 + add $5,r3 + movb r3,(r0) +1: + cmpb (r0),$'9 + ble 1f + movb $'0,(r0) + cmp r0,$buf + blos 2f + incb -(r0) + br 1b +2: + movb $'1,(r0) + inc r2 +1: +outout: + mov sign,r1 + mov _ndigit,r0 + tst eflag + bne 1f + add r2,r0 +1: + clrb buf(r0) + mov $buf,r0 + mov (sp)+,r3 + movf (sp)+,fr1 + movf (sp)+,fr0 + ldfps (sp)+ + rts pc + +epsilon = 037114 +one = 40200 +ten = 41040 + .data +tenth: 037314; 146314; 146314; 146315 +_ndigit:10. + .bss +buf: .=.+40. +buftop: +sign: .=.+2 +eflag: .=.+2 + .text diff --git a/source/s3/exp.s b/source/s3/exp.s new file mode 100644 index 0000000..65ab2f1 --- /dev/null +++ b/source/s3/exp.s @@ -0,0 +1,117 @@ +.globl exp, _exp +/ +ldfps = 170100^tst +stfps = 170200^tst +ldexp = 176400^movif +stexp = 175000^movfi +/ +/ exp accepts its argument and returns its result +/ in fr0. The carry bit is set if the result overflows. +/ The coefficients are #1067 from Hart & Cheney. +/ +/ movf arg,fr0 +/ jsr pc,exp +/ movf fr0,result +/ +_exp: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),fr0 + jsr pc,exp + mov (sp)+,r5 + rts pc + +exp: + stfps -(sp) + ldfps $200 /di mode + movf fr2,-(sp) + movf fr1,-(sp) + tstf fr0 + cfcc + bne 1f + movf $one,fr0 /exp(0) + clc + br out +1: + modf log2e,fr0 /exp(x) = 2^(x*log2(e)) + cfcc + bmi 2f + movfi fr1,-(sp) /save integer part + subf $half,fr0 + br 3f +2: + movfi fr1,-(sp) + dec (sp) + addf $half,fr0 +3: + movf fr0,fr1 / -.5 < x < +.5 + mulf fr1,fr1 /arg**2 +/ + movf P2,fr2 + mulf fr1,fr2 + addf P1,fr2 + mulf fr1,fr2 + addf P0,fr2 + mulf fr2,fr0 /xP(x**2) +/ + movf fr1,fr2 + addf Q1,fr2 + mulf fr1,fr2 + addf Q0,fr2 /Q(x**2) +/ + movf fr2,fr1 + subf fr0,fr1 + addf fr2,fr0 + divf fr1,fr0 /(Q+xP)/(Q-xP) + mulf sqrt2,fr0 +/ + stexp fr0,-(sp) + add (sp)+,(sp) +/ + cmp (sp),$177 + ble 2f + tst (sp)+ + movf big,fr0 /overflow + sec + br 1f +2: + cmp (sp),$-177 + bge 2f + tst (sp)+ + clrf fr0 /underflow + clc + br 1f +2: + ldexp (sp)+,fr0 + clc +1: +out: + movf (sp)+,fr1 + movf (sp)+,fr2 + ldfps (sp)+ + rts pc +/ +/ + .data +P0: 42675; 36404; 77563; 46675 +P1: 41241; 116724; 114237; 60333 +P2: 36675; 27102; 125560; 136652 +Q0: 43210; 100661; 76072; 62453 +Q1: 42151; 27450; 75350; 112503 +log2e: 40270; 125073; 24534; 13761 +sqrt2: 40265; 02363; 31771; 157144 +half = 40000 +one = 40200 +/ +big: 77777; 177777; 177777; 177777 +/ +/ P0 = .15139 06799 05433 89158 94328 d4 +/ P1 = .20202 06565 12869 27227 886 d2 +/ P2 = .23093 34775 37502 33624 d-1 +/ +/ Q0 = .43682 11662 72755 84984 96814 d4 +/ Q1 = .23318 42114 27481 62379 0295 d3 +/ Q2 = .1 d1 +/ +/ log2e = 1.44269 50408 88963 40735 99246 +/ sqrt2 = 1.41421 35623 73095 04880 16887 diff --git a/source/s3/fakfp.s b/source/s3/fakfp.s new file mode 100644 index 0000000..16005bb --- /dev/null +++ b/source/s3/fakfp.s @@ -0,0 +1,10 @@ +/ fakefp -- fake floating point simulator + +.globl fptrap + +fptrap: + sub $2,(sp) + mov r0,-(sp) + sys signal; 4; 0 + mov (sp)+,r0 + 2 / rti diff --git a/source/s3/floor.s b/source/s3/floor.s new file mode 100644 index 0000000..72f9e7b --- /dev/null +++ b/source/s3/floor.s @@ -0,0 +1,40 @@ +.globl _floor, _ceil +.globl floor, ceil +one = 40200 + +_floor: + mov r5,-(sp) + mov sp,r5 + movf 4(r5),fr0 + jsr pc,floor + br 1f + +_ceil: + mov r5,-(sp) + mov sp,r5 + movf 4(r5),fr0 + jsr pc,ceil +1: + mov (sp)+,r5 + rts pc + +floor: + tstf fr0 + cfcc + bge 1f + modf $one,fr0 + cfcc + beq 2f + subf $one,fr1 + br 2f +1: + modf $one,fr0 +2: + movf fr1,fr0 + rts pc + +ceil: + negf fr0 + jsr pc,floor + negf fr0 + rts pc diff --git a/source/s3/fmod.s b/source/s3/fmod.s new file mode 100644 index 0000000..237c9cd --- /dev/null +++ b/source/s3/fmod.s @@ -0,0 +1,17 @@ +/ C floating mod +/ fmod(a,b) returns a number n such that +/ i*b + n is a and 0 <= n < b + +.globl _fmod +_fmod: + mov r5,-(sp) + mov sp,r5 + movf 4(r5),fr0 + divf 12.(r5),fr0 + modf $one,fr0 + mulf 12.(r5),fr1 + movf 4(r5),fr0 + subf fr1,fr0 + mov (sp)+,r5 + rts pc +one = 40200 diff --git a/source/s3/fp1.s b/source/s3/fp1.s new file mode 100644 index 0000000..243fefa --- /dev/null +++ b/source/s3/fp1.s @@ -0,0 +1,427 @@ +/ fp1 -- floating point simulator + +rti = 2 +bpt = 3 + +m.ext = 200 / long mode bit +m.lngi = 100 / long integer mode + +.globl fptrap +.globl ac0, ac1, ac2, ac3 + +fptrap: + dec reenter + bge 1f + 4 / reentered! +1: + mov (sp)+,spc + mov (sp)+,sps + mov r0,sr0 + mov $sr1,r0 + mov r1,(r0)+ + mov r2,(r0)+ + mov r3,(r0)+ + mov r4,(r0)+ + mov r5,(r0)+ + mov sp,(r0)+ + sub $8,sp / room for double push + mov (r0),r5 / pc + clr trapins + mov -(r5),r5 / trapped instruction + mov r5,r4 + bic $7777,r4 + cmp r4,$170000 + beq 1f + jmp badins +1: + bic $100000,fpsr / clear fp error + bic $170000,r5 + mov r5,r4 + bit $7000,r4 + bne class3 + bit $700,r4 + bne class2 + cmp r4,$12 + blos 1f + jmp badins +1: + asl r4 + jmp *1f(r4) + + .data +1: + i.cfcc / 170000 + i.setf / 170001 + i.seti / 170002 + badins + badins + badins + badins + badins + badins + i.setd / 170011 + i.setl / 170012 + .text + +class2: + cmp r5,$400 + bge 1f + jsr r1,fsrc; mod0rx; mod242 + br 2f +1: + jsr r1,fsrc; mod0f; mod24f +2: + mov r3,r5 + asl r4 + asl r4 + clrb r4 + swab r4 + asl r4 + jsr pc,*1f(r4) + jmp sret + + .data +1: + badins / 1700xx + i.ldfps / 1701xx + i.stfps / 1702xx + badins / 1703xx - stst + i.clrx / 1704xx + i.tstx / 1705xx + i.absx / 1706xx + i.negx / 1707xx + .text + +class3: + cmp r5,$5000 + blt 1f + mov r5,r2 + clrb r2 + cmp r2,$6400 + blt 2f + sub $1400,r2 +2: + cmp r2,$5000 + bne 2f + jsr r1,fsrc; mod0rx; mod242 + br 3f +2: + cmp r2,$5400 + bne 2f + jsr r1,fsrc; mod0ra; mod24i + br 3f +2: + jsr r1,fsrc; mod0f; mod24d + br 3f +1: + jsr r1,fsrc; mod0f; mod24f +3: + jsr pc,freg + mov r2,r5 + clrb r4 + swab r4 + asl r4 + jsr pc,*1f(r4) + br sret + + .data +1: + badins / 1700xx + badins / 1704xx + i.mulx / 1710xx + i.modx / 1714xx + i.addx / 1720xx + i.ldx / 1724xx + i.subx / 1730xx + i.cmpx / 1734xx + i.stx / 1740xx + i.divx / 1744xx + i.stexp / 1750xx + i.stcxj / 1754xx + i.stcxy / 1760xx + i.ldexp / 1764xx + i.ldcjx / 1770xx + i.ldcyx / 1774xx + .text + +i.cfcc: + mov fpsr,r0 + bic $!17,r0 + mov r0,sps + br ret + +i.setf: + bic $m.ext,fpsr + br ret + +i.setd: + bis $m.ext,fpsr + br ret + +i.seti: + bic $m.lngi,fpsr + br ret + +i.setl: + bis $m.lngi,fpsr + br ret + +badins: + inc trapins + br ret + +sret: + mov $fpsr,r0 + bic $17,(r0) + tst (r5) + bpl 1f + bis $10,(r0) + br ret +1: + bne ret + bis $4,(r0) + +ret: + mov $sr1,r0 + mov (r0)+,r1 + mov (r0)+,r2 + mov (r0)+,r3 + mov (r0)+,r4 + mov (r0)+,r5 + mov (r0)+,sp + mov sr0,r0 + mov sps,-(sp) + mov spc,-(sp) + tst trapins + bne 1f + inc reenter + rti +1: + bpt + +freg: + mov r5,r2 + bic $!300,r2 + asr r2 + asr r2 + asr r2 + add $ac0,r2 + rts pc + +fsrc: + mov r5,r3 + bic $!7,r3 / register + asl r3 + add $sr0,r3 + mov r5,r0 + bic $!70,r0 / mode + asr r0 + asr r0 + jmp *1f(r0) + + .data +1: + mod0 + mod1 + mod2 + mod3 + mod4 + mod5 + mod6 + mod7 + .text + +mod24f: + mov $4,r0 + bit $m.ext,fpsr + beq 1f + add $4,r0 +1: + rts pc + +mod24d: + mov $8,r0 + bit $m.ext,fpsr + beq 1f + sub $4,r0 +1: + rts pc + +mod242: + mov $2,r0 + rts pc + +mod24i: + mov $2,r0 + bit $m.lngi,fpsr + beq 1f + add $2,r0 +1: + rts pc + +mod0: + jmp *(r1)+ + +mod0f: + sub $sr0,r3 / get fp ac + cmp r3,$6*2 + bhis badi1 + asl r3 + asl r3 + add $ac0,r3 + tst (r1)+ + rts r1 + +mod0ra: + bit $m.lngi,fpsr + bne badi1 + +mod0r: + cmp r3,$ssp + bhis badi1 +mod0rx: + tst (r1)+ + rts r1 + +mod1: + cmp r3,$spc + beq badi1 + mov (r3),r3 + br check + +mod2: + mov (r3),-(sp) + jsr pc,*2(r1) + cmp r3,$spc + bne 1f + mov $2,r0 + mov *(r3),pctmp + mov $pctmp,(sp) +1: + add r0,(r3) + mov (sp)+,r3 + br check + +mod3: + mov *(r3),-(sp) + add $2,(r3) + mov (sp)+,r3 + br check + +mod4: + cmp r3,$spc / test pc + beq badi1 + jsr pc,*2(r1) + sub r0,(r3) + mov (r3),r3 + br check + +mod5: + cmp r3,$spc + beq badi1 + sub $2,(r3) + mov *(r3),r3 + br check + +mod6: + mov *spc,-(sp) + add $2,spc + add (r3),(sp) + mov (sp)+,r3 + br check + +mod7: + jsr r1,mod6; ..; .. + mov (r3),r3 + br check + +badi1: + jmp badins + +check: + bit $1,r3 + bne badi1 + cmp (r1)+,(r1)+ + rts r1 + +setab: + mov $asign,r0 + jsr pc,seta + mov r3,r2 + mov $bsign,r0 + +seta: + clr (r0) + mov (r2)+,r1 + mov r1,-(sp) + beq 1f + blt 2f + inc (r0)+ + br 3f +2: + dec (r0)+ +3: + bic $!177,r1 + bis $200,r1 + br 2f +1: + clr (r0)+ +2: + mov r1,(r0)+ + mov (r2)+,(r0)+ + bit $m.ext,fpsr + beq 2f + mov (r2)+,(r0)+ + mov (r2)+,(r0)+ + br 3f +2: + clr (r0)+ + clr (r0)+ +3: + mov (sp)+,r1 + asl r1 + clrb r1 + swab r1 + sub $200,r1 + mov r1,(r0)+ / exp + rts pc + +norm: + mov $areg,r0 + mov (r0)+,r1 + mov r1,-(sp) + mov (r0)+,r2 + bis r2,(sp) + mov (r0)+,r3 + bis r3,(sp) + mov (r0)+,r4 + bis r4,(sp)+ + bne 1f + clr asign + rts pc +1: + bit $!377,r1 + beq 1f + clc + ror r1 + ror r2 + ror r3 + ror r4 + inc (r0) + br 1b +1: + bit $200,r1 + bne 1f + asl r4 + rol r3 + rol r2 + rol r1 + dec (r0) + br 1b +1: + mov r4,-(r0) + mov r3,-(r0) + mov r2,-(r0) + mov r1,-(r0) + rts pc + diff --git a/source/s3/fp2.s b/source/s3/fp2.s new file mode 100644 index 0000000..62d8c87 --- /dev/null +++ b/source/s3/fp2.s @@ -0,0 +1,194 @@ +/ fp2 -- floating point simulation + +i.ldx: + mov (r3)+,(r2)+ + mov (r3)+,(r2)+ + bit $m.ext,fpsr + beq 1f + mov (r3)+,(r2)+ + mov (r3)+,(r2)+ + rts pc +1: + clr (r2)+ + clr (r2)+ + rts pc + +i.stx: + mov (r2)+,(r3)+ + mov (r2)+,(r3)+ + bit $m.ext,fpsr + beq 1f + mov (r2)+,(r3)+ + mov (r2)+,(r3)+ +1: + rts pc + +i.clrx: + clr (r3)+ + clr (r3)+ + bit $m.ext,fpsr + beq 1f + clr (r3)+ + clr (r3)+ +1: + rts pc + +i.negx: + tst (r3) + beq 1f + add $100000,(r3) +1: + rts pc + +i.absx: + bic $!77777,(r3) + rts pc + +i.tstx: + rts pc + +i.cmpx: + mov $areg,r5 + tst (r2) + bge 1f + tst (r3) + bge 1f + cmp (r2),(r3) + bgt 4f + blt 3f +1: + cmp (r2)+,(r3)+ + bgt 3f + blt 4f + cmp (r2)+,(r3)+ + bne 1f + bit $m.ext,fpsr + beq 2f + cmp (r2)+,(r3)+ + bne 1f + cmp (r2)+,(r3)+ + beq 2f +1: + bhi 3f +4: + mov $1,(r5) + rts pc +3: + mov $-1,(r5) + rts pc +2: + clr (r5) + rts pc + +i.ldcyx: + mov (r3)+,(r2)+ + mov (r3)+,(r2)+ + bit $m.ext,fpsr + bne 1f + mov (r3)+,(r2)+ + mov (r3)+,(r2)+ + rts pc +1: + clr (r2)+ + clr (r2)+ + rts pc + +i.stcxy: + mov (r2)+,(r3)+ + mov (r2)+,(r3)+ + bit $m.ext,fpsr + bne 1f + clr (r3)+ + clr (r3)+ +1: + rts pc + +i.ldcjx: + mov $asign,r0 + mov $1,(r0)+ + mov (r3)+,(r0)+ + bit $m.lngi,fpsr + beq 1f + mov (r3)+,(r0)+ + clr (r0)+ + clr (r0)+ + mov $32.-8,(r0)+ + jmp saret +1: + clr (r0)+ + clr (r0)+ + clr (r0)+ + mov $16.-8,(r0) + jmp saret + +i.stcxj: + mov r3,r5 + mov $asign,r0 + jsr pc,seta + mov $areg,r0 + mov (r0)+,r1 + mov (r0)+,r2 + mov (r0)+,r3 + mov aexp,r0 +1: + cmp r0,$48.-8 + bge 1f + clc + ror r1 + ror r2 + ror r3 + inc r0 + br 1b +1: + bgt xoflo + tst r1 + bne xoflo +1: + bit $m.lngi,fpsr + beq 1f + tst asign + bge 2f + neg r3 + adc r2 + bcs 2f + neg r2 +2: + mov r2,(r5) + mov r3,2(r5) + rts pc +1: + tst r2 + bne xoflo + tst asign + bge 2f + neg r3 +2: + mov r3,(r5) + rts pc + +xoflo: + bis $1,fpsr / set fixed overflow (carry) + jmp ret + +i.ldexp: + mov $asign,r0 + jsr pc,seta + mov (r3),aexp + jsr pc,reta + jmp sret + +i.stexp: + mov $asign,r0 + jsr pc,seta + mov aexp,(r3) + mov r3,r5 + jmp sret + +i.ldfps: + mov (r3),fpsr + jmp ret + +i.stfps: + mov fpsr,(r3) + jmp ret + diff --git a/source/s3/fp3.s b/source/s3/fp3.s new file mode 100644 index 0000000..66ffecf --- /dev/null +++ b/source/s3/fp3.s @@ -0,0 +1,335 @@ +/ fp3 -- floating simulation + +i.addx: + jsr pc,setab + br 1f + +i.subx: + jsr pc,setab + neg bsign +1: + tst bsign + beq reta + tst asign + beq retb + mov areg+8,r1 + sub breg+8,r1 + blt 1f + beq 2f + cmp r1,$56. + bge reta + mov $breg,r0 + br 4f +1: + neg r1 + cmp r1,$56. + bge retb + mov $areg,r0 +4: + mov r1,-(sp) + mov (r0)+,r1 + mov (r0)+,r2 + mov (r0)+,r3 + mov (r0)+,r4 + add (sp),(r0) +1: + clc + ror r1 + ror r2 + ror r3 + ror r4 + dec (sp) + bgt 1b + mov r4,-(r0) + mov r3,-(r0) + mov r2,-(r0) + mov r1,-(r0) + tst (sp)+ +2: + mov $areg+8,r1 + mov $breg+8,r2 + mov $4,r0 + cmp asign,bsign + bne 4f + clc +1: + adc -(r1) + bcs 3f + add -(r2),(r1) +2: + dec r0 + bne 1b + br 5f +3: + add -(r2),(r1) + sec + br 2b + br 5f +4: + clc +1: + sbc -(r1) + bcs 3f + sub -(r2),(r1) +2: + dec r0 + bne 1b + br 5f +3: + sub -(r2),(r1) + sec + br 2b + +saret: + mov $areg,r1 +5: + tst (r1) + bge 3f + mov $areg+8,r1 + mov $4,r0 + clc +1: + adc -(r1) + bcs 2f + neg (r1) +2: + dec r0 + bne 1b + neg -(r1) +3: + jsr pc,norm + br reta + +retb: + mov $bsign,r1 + mov $asign,r2 + mov $6,r0 +1: + mov (r1)+,(r2)+ + dec r0 + bne 1b + +reta: + mov r5,r2 + mov $asign,r0 + tst (r0) + beq unflo + mov aexp,r1 + cmp r1,$177 + bgt ovflo + cmp r1,$-177 + blt unflo + add $200,r1 + swab r1 + clc + ror r1 + tst (r0)+ + bge 1f + bis $100000,r1 +1: + bic $!177,(r0) + bis (r0)+,r1 + mov r1,(r2)+ + mov (r0)+,(r2)+ + bit $m.ext,fpsr + beq 1f + mov (r0)+,(r2)+ + mov (r0)+,(r2)+ +1: + rts pc + +unflo: + clr (r2)+ + clr (r2)+ + bit $m.ext,fpsr + beq 1f + clr (r2)+ + clr (r2)+ +1: + rts pc + +ovflo: + bis $2,fpsr / set v-bit (overflow) + jmp ret + +i.mulx: + jsr pc,i.mul + br saret + +i.modx: + jsr pc,i.mul + jsr pc,norm + mov $asign,r0 + mov $bsign,r1 + mov $6,r2 +1: + mov (r0)+,(r1)+ + dec r2 + bne 1b + clr r0 / count + mov $200,r1 / bit + clr r2 / reg offset +1: + cmp r0,aexp + bge 2f / in fraction + bic r1,areg(r2) + br 3f +2: + bic r1,breg(r2) +3: + inc r0 + clc + ror r1 + bne 1b + mov $100000,r1 + add $2,r2 + cmp r2,$8 + blt 1b + jsr pc,norm + jsr pc,reta + cmp r5,$ac1 + beq 1f + cmp r5,$ac3 + beq 1f + bit $200,breg + bne 2f + clr bsign +2: + add $8,r5 + jsr pc,retb + sub $8,r5 +1: + rts pc + +i.divx: + jsr pc,setab + tst bsign + beq ovflo + sub bexp,aexp + jsr pc,xorsign + mov r5,-(sp) + mov $areg,r0 + mov (r0),r1 + clr (r0)+ + mov (r0),r2 + clr (r0)+ + mov (r0),r3 + clr (r0)+ + mov (r0),r4 + clr (r0)+ + mov $areg,r5 + mov $400,-(sp) +1: + mov $breg,r0 + cmp (r0)+,r1 + blt 2f + bgt 3f + cmp (r0)+,r2 + blo 2f + bhi 3f + cmp (r0)+,r3 + blo 2f + bhi 3f + cmp (r0)+,r4 + bhi 3f +2: + mov $breg,r0 + sub (r0)+,r1 + clr -(sp) + sub (r0)+,r2 + adc (sp) + clr -(sp) + sub (r0)+,r3 + adc (sp) + sub (r0)+,r4 + sbc r3 + adc (sp) + sub (sp)+,r2 + adc (sp) + sub (sp)+,r1 + bis (sp),(r5) +3: + asl r4 + rol r3 + rol r2 + rol r1 + clc + ror (sp) + bne 1b + mov $100000,(sp) + add $2,r5 + cmp r5,$areg+8 + blo 1b + tst (sp)+ + mov (sp)+,r5 + jmp saret + + +i.mul: + jsr pc,setab + add bexp,aexp + dec aexp + jsr pc,xorsign + mov r5,-(sp) + mov $breg+4,r5 + bit $m.ext,fpsr + beq 1f + add $4,r5 +1: + clr r0 + clr r1 + clr r2 + clr r3 + clr r4 +1: + asl r0 + bne 2f + inc r0 + tst -(r5) +2: + cmp r0,$400 + bne 2f + cmp r5,$breg + bhi 2f + mov $areg,r0 + mov r1,(r0)+ + mov r2,(r0)+ + mov r3,(r0)+ + mov r4,(r0)+ + mov (sp)+,r5 + rts pc +2: + clc + ror r1 + ror r2 + ror r3 + ror r4 + bit r0,(r5) + beq 1b + mov r0,-(sp) + mov $areg,r0 + add (r0)+,r1 + clr -(sp) + add (r0)+,r2 + adc (sp) + clr -(sp) + add (r0)+,r3 + adc (sp) + add (r0)+,r4 + adc r3 + adc (sp) + add (sp)+,r2 + adc (sp) + add (sp)+,r1 + mov (sp)+,r0 + br 1b + +xorsign: + cmp asign,bsign + beq 1f + mov $-1,asign + rts pc +1: + mov $1,asign + rts pc + diff --git a/source/s3/fpx.s b/source/s3/fpx.s new file mode 100644 index 0000000..eaa1de2 --- /dev/null +++ b/source/s3/fpx.s @@ -0,0 +1,34 @@ +/ fpx -- floating point simulation + +.data +reenter: 1 + +.bss +asign: .=.+2 +areg: .=.+8 +aexp: .=.+2 +bsign: .=.+2 +breg: .=.+8 +bexp: .=.+2 + +fpsr: .=.+2 +trapins: .=.+2 + +ac0: .=.+8. +ac1: .=.+8. +ac2: .=.+8. +ac3: .=.+8. +ac4: .=.+8. +ac5: .=.+8. + +sr0: .=.+2 +sr1: .=.+2 + .=.+2 + .=.+2 + .=.+2 + .=.+2 +ssp: .=.+2 +spc: .=.+2 +sps: .=.+2 +pctmp: .=.+8 + diff --git a/source/s3/gamma.s b/source/s3/gamma.s new file mode 100644 index 0000000..d333865 --- /dev/null +++ b/source/s3/gamma.s @@ -0,0 +1,329 @@ +.globl gamma, _gamma, signgam, _signgam +.globl log, sin +half = 040000 +one = 40200 +two = 40400 +eight = 41000 +large = 77777 +ldfps = 170100^tst +stfps = 170200^tst +/ +/ gamma computes the log of the abs of the gamma function. +/ gamma accepts its argument and returns its result +/ in fr0. The carry bit is set if the result is +/ too large to represent. +/ The sign of the gamma function is +/ returned in the globl cell signgam. +/ +/ The coefficients for expansion around zero +/ are #5243 from Hart & Cheney; for expansion +/ around infinity they are #5404. +/ +/ movf arg,fr0 +/ jsr pc,gamma +/ movf fr0,... +/ + +_gamma: + mov r5,-(sp) + mov sp,r5 + movf 4(r5),fr0 + jsr pc,gamma + mov (sp)+,r5 + rts pc +gamma: + stfps -(sp) + ldfps $200 + clr signgam + movf fr1,-(sp) + tstf fr0 + cfcc + ble negative + cmpf $eight,fr0 + cfcc + blt asymptotic + jsr pc,regular +/ +lret: + jsr pc,log + bec ret + 4 +ret: + movf (sp)+,fr1 + ldfps (sp)+ + clc + rts pc +/ +erret: + movf $large,fr0 + movf (sp)+,fr1 + ldfps (sp)+ + sec + rts pc + +/ +/ here for positive x > 8 +/ the log of the gamma function is +/ approximated directly by the asymptotic series. +/ +asymptotic: + movf fr0,-(sp) + movf fr0,fr1 + jsr pc,log + subf $half,fr1 + mulf fr1,fr0 + subf (sp),fr0 + addf goobie,fr0 +/ + movf $one,fr1 + divf (sp)+,fr1 + movf fr0,-(sp) + movf fr1,-(sp) + mulf fr1,fr1 +/ + mov r0,-(sp) + mov $p5p,r0 + mov $5,-(sp) + movf *(r0)+,fr0 +1: + mulf fr1,fr0 + addf *(r0)+,fr0 + dec (sp) + bne 1b + tst (sp)+ + mov (sp)+,r0 + mulf (sp)+,fr0 + addf (sp)+,fr0 + br ret + +/ +/ here on negative +/ the negative gamma is computed +/ in terms of the pos gamma. +/ +negative: + absf fr0 + movf fr0,fr1 + mulf pi,fr0 + jsr pc,sin + negf fr0 + cfcc + beq erret + bgt 1f + inc signgam + absf fr0 +1: + mov signgam,-(sp) + mulf fr1,fr0 + divf pi,fr0 + jsr pc,log + movf fr0,-(sp) + movf fr1,fr0 + jsr pc,gamma + addf (sp)+,fr0 + negf fr0 + mov (sp)+,signgam + br ret + +/ +/ control comes here for arguments less than 8. +/ if the argument is 23 then the argument +/ is reduced in range by the formula +/ gamma(x+1) = x*gamma(x) +/ +regular: + subf $two,fr0 + cfcc + bge 1f + addf $two,fr0 + movf fr0,-(sp) + addf $one,fr0 + movf fr0,-(sp) + addf $one,fr0 + jsr pc,regular + divf (sp)+,fr0 + divf (sp)+,fr0 + rts pc +1: + cmpf $one,fr0 + cfcc + bgt 1f + addf $one,fr0 + movf fr0,-(sp) + subf $two,fr0 + jsr pc,1b + mulf (sp)+,fr0 + rts pc +1: + movf fr2,-(sp) + mov r0,-(sp) + mov $p4p,r0 + mov $6,-(sp) + movf fr0,fr2 + movf *(r0)+,fr0 +1: + mulf fr2,fr0 + addf *(r0)+,fr0 + dec (sp) + bne 1b + mov $7,(sp) + movf fr2,fr1 + br 2f +1: + mulf fr2,fr1 +2: + addf *(r0)+,fr1 + dec (sp) + bne 1b + tst (sp)+ + mov (sp)+,r0 + divf fr1,fr0 + movf (sp)+,fr2 + rts pc +/ +.data +p4p: + p6;p5;p4;p3;p2;p1;p0 + q6;q5;q4;q3;q2;q1;q0 + +/ p6 = -.67449 50724 59252 89918 d1 +/ p5 = -.50108 69375 29709 53015 d2 +/ p4 = -.43933 04440 60025 67613 d3 +/ p3 = -.20085 27401 30727 91214 d4 +/ p2 = -.87627 10297 85214 89560 d4 +/ p1 = -.20886 86178 92698 87364 d5 +/ p0 = -.42353 68950 97440 89647 d5 +/ q7 = 1.0 d0 +/ q6 = -.23081 55152 45801 24562 d2 +/ q5 = +.18949 82341 57028 01641 d3 +/ q4 = -.49902 85266 21439 04834 d3 +/ q3 = -.15286 07273 77952 20248 d4 +/ q2 = +.99403 07415 08277 09015 d4 +/ q1 = -.29803 85330 92566 49932 d4 +/ q0 = -.42353 68950 97440 90010 d5 +p1: + 143643 + 26671 + 36161 + 72154 +p2: + 143410 + 165327 + 54121 + 172630 +p3: + 142773 + 10340 + 74264 + 152066 +p4: + 142333 + 125113 + 176657 + 75740 +p5: + 141510 + 67515 + 65111 + 24263 +p6: + 140727 + 153242 + 163350 + 32217 +p0: + 144045 + 70660 + 101665 + 164444 +q1: + 143072 + 43052 + 50302 + 136745 +q2: + 43433 + 50472 + 145404 + 175462 +q3: + 142677 + 11556 + 144553 + 154177 +q4: + 142371 + 101646 + 141245 + 11264 +q5: + 42075 + 77614 + 43022 + 27573 +q6: + 141270 + 123404 + 76130 + 12650 +q0: + 144045 + 70660 + 101665 + 164444 + +p5p: + s5;s4;s3;s2;s1;s0 +/ +/ s5 = -.16334 36431 d-2 +/ s4 = +.83645 87892 2 d-3 +/ s3 = -.59518 96861 197 d-3 +/ s2 = +.79365 05764 93454 d-3 +/ s1 = -.27777 77777 35865 004 d-2 +/ s0 = +.83333 33333 33331 01837 d-1 +/ goobie = 0.91893 85332 04672 74178 d0 +s5: + 135726 + 14410 + 15074 + 17706 +s4: + 35533 + 42714 + 111634 + 76770 +s3: + 135434 + 3200 + 171173 + 156141 +s2: + 35520 + 6375 + 12373 + 111437 +s1: + 136066 + 5540 + 132625 + 63540 +s0: + 37252 + 125252 + 125252 + 125047 +goobie: + 40153 + 37616 + 41445 + 172645 +pi: + 40511 + 7732 + 121041 + 64302 +.bss +_signgam: +signgam:.=.+2 diff --git a/source/s3/get.s b/source/s3/get.s new file mode 100644 index 0000000..24d87e4 --- /dev/null +++ b/source/s3/get.s @@ -0,0 +1,92 @@ +/ getw/getc -- get words/characters from input file +/ fopen -- open a file for use by get(c|w) +/ +/ calling sequences -- +/ +/ mov $filename,r0 +/ jsr r5,fopen; ioptr +/ +/ on return ioptr buffer is set up or error bit is set if +/ file could not be opened. +/ +/ jsr r5,get(c|w)1; ioptr +/ +/ on return char/word is in r0; error bit is +/ set on error or end of file. +/ +/ ioptr is the address of a 518-byte buffer +/ whose layout is as follows: +/ +/ ioptr: .=.+2 / file descriptor +/ .=.+2 / charact+2 / pointer to next character (reset if no. chars=0) +/ .=.+512. / the buffer + + .globl getc,getw,fopen + +fopen: + mov r1,-(sp) + mov (r5)+,r1 + mov r0,0f + sys 0; 9f +.data +9: + sys open; 0:..; 0 +.text + bes 1f + mov r0,(r1)+ + clr (r1)+ + mov (sp)+,r1 + rts r5 +1: + mov $-1,(r1) + mov (sp)+,r1 + sec + rts r5 + +.data +getw: + mov (r5),9f + mov (r5)+,8f + jsr r5,getc; 8:.. + bec 1f + rts r5 +1: + mov r0,-(sp) + jsr r5,getc; 9:.. + swab r0 + bis (sp)+,r0 + rts r5 +.text + +getc: + mov r1,-(sp) + mov (r5)+,r1 + dec 2(r1) + bge 1f + mov r1,r0 + add $6,r0 + mov r0,0f + mov r0,4(r1) + mov (r1),r0 + sys 0; 9f +.data +9: + sys read; 0:..; 512. +.text + bes 2f + tst r0 + bne 3f +2: + mov (sp)+,r1 + sec + rts r5 +3: + dec r0 + mov r0,2(r1) +1: + clr r0 + bisb *4(r1),r0 + inc 4(r1) + mov (sp)+,r1 + rts r5 + diff --git a/source/s3/ldiv.s b/source/s3/ldiv.s new file mode 100644 index 0000000..58081a8 --- /dev/null +++ b/source/s3/ldiv.s @@ -0,0 +1,21 @@ +/ C library-- long divide/remainder + +.globl _ldiv, _ldivr +.globl _lrem + +_ldiv: + mov 2(sp),r0 + mov 4(sp),r1 + div 6(sp),r0 + mov r1,_ldivr + rts pc + +_lrem: + mov 2(sp),r0 + mov 4(sp),r1 + div 6(sp),r0 + mov r1,r0 + rts pc + +.bss +_ldivr: .=.+2 diff --git a/source/s3/log.s b/source/s3/log.s new file mode 100644 index 0000000..8f04716 --- /dev/null +++ b/source/s3/log.s @@ -0,0 +1,105 @@ +.globl log, _log +ldfps = 170100^tst +stfps = 170200^tst +ldexp = 176400^movif +stexp = 175000^movfi +/ +/ log accepts its argument and returns its result +/ in fr0. The carry bit is set if the argument is +/ zero or negative. +/ The coefficients are #2705 from Hart & Cheney. +/ +/ movf arg,fr0 +/ jsr pc,log +/ movf fr0,... +/ +_log: + mov r5,-(sp) + mov sp,r5 + movf 4(r5),fr0 + jsr pc,log + mov (sp)+,r5 + rts pc + +log: + tstf fr0 + cfcc + bgt 1f + movf $bigneg,fr0 /return -(big) on error + sec + rts pc +1: + stfps -(sp) + ldfps $200 /di mode + movf fr2,-(sp) + movf fr1,-(sp) +/ + stexp fr0,-(sp) /scale + ldexp $0,fr0 + cmpf sqrt2o2,fr0 + cfcc + blt 1f + ldexp $1,fr0 + dec (sp) +1: + movf fr0,fr1 /(1/2)^(1/2) < x < 2^(1/2) + subf $one,fr0 + addf $one,fr1 + divf fr1,fr0 /z = (x-1)/(x+1) + movf fr0,fr1 + mulf fr0,fr1 /z^2 +/ + movf p3,fr2 + mulf fr1,fr2 + addf p2,fr2 + mulf fr1,fr2 + addf p1,fr2 + mulf fr1,fr2 + addf p0,fr2 + mulf fr2,fr0 /zP(z) +/ + movf fr1,fr2 + addf q2,fr2 + mulf fr1,fr2 + addf q1,fr2 + mulf fr1,fr2 + addf q0,fr2 /Q(z) +/ + divf fr2,fr0 /zP(z)/Q(z) + movif (sp)+,fr1 + mulf log2,fr1 + addf fr1,fr0 +/ + movf (sp)+,fr1 + movf (sp)+,fr2 + ldfps (sp)+ + rts pc +/ +/ +one = 40200 +bigneg = 177777 +/ +.data +sqrt2o2: 40065; 02363; 31771; 157145 +log2: 40061; 71027;173721;147572 +/ +p0: 141300; 16201; 02154; 10216 +p1: 41367;124211; 21611;114442 +p2: 141032; 31773; 64222; 40261 +p3: 37727;114303;110107;114145 +/ +q0: 141100; 16201; 02154; 10216 +q1: 41233;154404;136454; 22153 +q2: 141016;111747; 07541; 52530 +/ +/ +/p0 = -.24013 91795 59210 50986 8484 d2 +/p1 = .30957 29282 15376 50062 264 d2 +/p2 = -.96376 90933 68686 59324 d1 +/p3 = .42108 73712 17979 7145 d0 +/ +/q0 = -.12006 95897 79605 25471 7525 d2 +/q1 = .19480 96607 00889 73051 623 d2 +/q2 = -.89111 09027 93783 12337 d1 +/q3 = .1 d1 +/ diff --git a/source/s3/mesg.s b/source/s3/mesg.s new file mode 100644 index 0000000..0698c04 --- /dev/null +++ b/source/s3/mesg.s @@ -0,0 +1,32 @@ +.globl mesg + +/ usage: +/ jsr r5,mesg +/ +/ .even +/ ... +/ +/ string is output onto $1 +/ + +mesg: + mov r0,-(sp) + mov r5,r0 + mov r5,0f +1: + tstb (r5)+ + bne 1b + sub r5,r0 + com r0 + mov r0,0f+2 + mov $1,r0 + sys 0; 9f +.data +9: + sys write; 0:..; .. +.text + inc r5 + bic $1,r5 + mov (sp)+,r0 + rts r5 + diff --git a/source/s3/pow.s b/source/s3/pow.s new file mode 100644 index 0000000..fb532d2 --- /dev/null +++ b/source/s3/pow.s @@ -0,0 +1,60 @@ +.globl pow, _pow +.globl log, exp + +_pow: + mov r5,-(sp) + mov sp,r5 + movf 4(r5),fr0 + movf 12.(r5),fr1 + jsr pc,pow + mov (sp)+,r5 + rts pc + +pow: + +/ 0^0~ is 0 + + tstf fr0 + cfcc + bne 1f + tstf fr1 + cfcc + beq bad + rts pc +1: + +/ -^i is +^i fixed sign + + bpl 1f + movf fr1,-(sp) + modf $one,fr1 + cfcc + bne bad1 + movf (sp)+,fr1 + absf fr0 + jsr pc,1f + bes bad + movf fr1,-(sp) + modf $half,fr1 + cfcc + beq 2f + negf fr0 +2: + movf (sp)+,fr1 + rts pc +1: + jsr pc,log + bes 1f + mulf fr1,fr0 + jsr pc,exp +1: + rts pc + +bad1: + movf (sp)+,fr1 +bad: + sec + rts pc + +one = 40200 +half = 40000 diff --git a/source/s3/put.s b/source/s3/put.s new file mode 100644 index 0000000..82aa5ca --- /dev/null +++ b/source/s3/put.s @@ -0,0 +1,102 @@ +/ putw/putc -- write words/characters on output file +/ +/ fcreat -- create an output file for use by put(w|c) +/ +/ calling sequences -- +/ +/ mov $filename,r0 +/ jsr r5,fcreat; ioptr +/ +/ on return ioptr is set up for use by put or error +/ bit is set if file could not be created. +/ +/ mov(b) thing,r0 +/ jsr r5,put(w|c)1; ioptr +/ +/ the character or word is written out. +/ +/ jsr r5,flush; ioptr +/ +/ the buffer is fled. +/ + + .globl putc, putw, flush, fcreat + +fcreat: + mov r1,-(sp) + mov (r5)+,r1 + mov r0,0f + sys 0; 9f +.data +9: + sys creat; 0:..; 666 +.text + bes 1f + mov r0,(r1)+ +2: + clr (r1)+ + clr (r1)+ + mov (sp)+,r1 + rts r5 +1: + mov $-1,(r1)+ + mov (sp)+,r1 + sec + rts r5 + +.data +putw: + mov (r5),8f + mov (r5)+,9f + mov r0,-(sp) + jsr r5,putc; 8:.. + mov (sp)+,r0 + swab r0 + jsr r5,putc; 9:.. + rts r5 +.text + +putc: + mov r1,-(sp) + mov (r5)+,r1 +1: + dec 2(r1) + bge 1f + mov r0,-(sp) + jsr pc,fl + mov (sp)+,r0 + br 1b +1: + movb r0,*4(r1) + inc 4(r1) + mov (sp)+,r1 + rts r5 + +flush: + mov r0,-(sp) + mov r1,-(sp) + mov (r5)+,r1 + jsr pc,fl + mov (sp)+,r1 + mov (sp)+,r0 + rts r5 + +fl: + mov r1,r0 + add $6,r0 + mov r0,-(sp) + mov r0,0f + mov 4(r1),0f+2 + beq 1f + sub (sp),0f+2 + mov (r1),r0 + sys 0; 9f +.data +9: + sys write; 0:..; .. +.text +1: + mov (sp)+,4(r1) + mov $512.,2(r1) + rts pc + diff --git a/source/s3/rand.s b/source/s3/rand.s new file mode 100644 index 0000000..eaea20d --- /dev/null +++ b/source/s3/rand.s @@ -0,0 +1,27 @@ +/ random fixed point number generator + +.globl rand, srand +.globl _rand, _srand + +_srand: + mov 2(sp),ranx + rts pc + +srand: + mov r0,ranx + rts pc + +_rand: +rand: + mov r1,-(sp) + mov ranx,r1 + mpy $13077.,r1 + add $6925.,r1 + mov r1,r0 + mov r0,ranx + bic $100000,r0 + mov (sp)+,r1 + rts pc + +.data +ranx: 1 diff --git a/source/s3/run b/source/s3/run new file mode 100644 index 0000000..334a5fc --- /dev/null +++ b/source/s3/run @@ -0,0 +1,24 @@ +as atan.s; mv a.out atan.o +as crypt.s; mv a.out crypt.o +as dpadd.s; mv a.out dpadd.o +as ecvt.s; mv a.out ecvt.o +as exp.s; mv a.out exp.o +as floor.s; mv a.out floor.o +as fmod.s; mv a.out fmod.o +as fp?.s; mv a.out fp.o +: as fakfp.s: mv a.out fp.o +as gamma.s; mv a.out gamma.o +as get.s; mv a.out get.o +as ldiv.s; mv a.out ldiv.o +as log.s; mv a.out log.o +as mesg.s; mv a.out mesg.o +as pow.s; mv a.out pow.o +as put.s; mv a.out put.o +as rand.s; mv a.out rand.o +as savr5.s; mv a.out savr5.o +as sin.s; mv a.out sin.o +as sqrt.s; mv a.out sqrt.o +as switch.s; mv a.out switch.o +as ttyn.s; mv a.out ttyn.o +ar r /lib/liba.a +rm *.o diff --git a/source/s3/savr5.s b/source/s3/savr5.s new file mode 100644 index 0000000..c141155 --- /dev/null +++ b/source/s3/savr5.s @@ -0,0 +1,5 @@ +/ savr5 - for as progs that call c-callable entries + +.globl savr5 +.bss +savr5: .=.+2 diff --git a/source/s3/sin.s b/source/s3/sin.s new file mode 100644 index 0000000..6e1c000 --- /dev/null +++ b/source/s3/sin.s @@ -0,0 +1,125 @@ +ldfps = 170100^tst +stfps = 170200^tst +/ +.globl sin, _sin +.globl cos, _cos +/ +/ floating point sin/cos +/ replaces the value in fr0 by its sin/cos +/ there are no error exits +/ coefficients are #3370 from Hart & Cheney +/ +_sin: + mov r5,-(sp) + mov sp,r5 + movf 4(r5),fr0 + jsr pc,sin + br 1f + +_cos: + mov r5,-(sp) + mov sp,r5 + movf 4(r5),fr0 + jsr pc,cos +1: + mov (sp)+,r5 + rts pc + +cos: + absf fr0 + mov $1,-(sp) + br 1f +sin: + clr -(sp) +1: + stfps -(sp) + ldfps $200 + movf fr1,-(sp) + movf fr2,-(sp) + mov r0,-(sp) +/ +/ quadrant reduction - arg = (2/J)x +/ -1 < arg < 1 +/ + movf fr0,-(sp) + absf fr0 + modf frpi2,fr0 + modf $fourth,fr1 + mulf $four,fr1 + movfi fr1,r0 + add 34(sp),r0 + movf $one,fr1 + inc r0 + ror r0 + bcs 1f + subf $one,fr0 +1: + ror r0 + bcc 1f + negf fr0 +1: + tstf (sp)+ + cfcc + bpl 1f + negf fr0 +1: + movf fr0,fr1 + mulf fr0,fr1 /arg^2 +/ + movf p4,fr2 + mulf fr1,fr2 + addf p3,fr2 + mulf fr1,fr2 + addf p2,fr2 + mulf fr1,fr2 + addf p1,fr2 + mulf fr1,fr2 + addf p0,fr2 + mulf fr2,fr0 / zP(z^2) +/ + movf fr1,fr2 + addf q3,fr2 + mulf fr1,fr2 + addf q2,fr2 + mulf fr1,fr2 + addf q1,fr2 + mulf fr1,fr2 + addf q0,fr2 / Q(z^2) +/ + divf fr2,fr0 / zP(z^2)/Q(z^2) +/ + mov (sp)+,r0 + movf (sp)+,fr2 + movf (sp)+,fr1 + ldfps (sp)+ + tst (sp)+ +/ clc /tst clears carry + rts pc +/ +fourth = 37600 +one = 40200 +four = 40600 +/ +.data +frpi2: 40042;174603; 67116; 42025 +/ +p0: 046117;031130;175220;165273 +p1: 145626;154170;031651;104637 +p2: 044726;162341;133224;052302 +p3: 143530;056427;005061;125021 +p4: 042021;174005;170441;175607 +q0: 046003;163716;123445;167144 +q1: 044707;047147;032436;120046 +q2: 043423;156142;064161;007314 +q3: 042004;123513;026637;160477 +/ +/p0 = .13578 84097 87737 56690 92680 d8 +/p1 = -.49429 08100 90284 41611 58627 d7 +/p2 = .44010 30535 37526 65019 44918 d6 +/p3 = -.13847 27249 98245 28730 54457 d5 +/p4 = .14596 88406 66576 87222 26959 d3 +/q0 = .86445 58652 92253 44299 15149 d7 +/q1 = .40817 92252 34329 97493 95779 d6 +/q2 = .94630 96101 53820 81805 71257 d4 +/q3 = .13265 34908 78613 63589 11494 d3 +/q4 = .1 d1 diff --git a/source/s3/sqrt.s b/source/s3/sqrt.s new file mode 100644 index 0000000..65a18a2 --- /dev/null +++ b/source/s3/sqrt.s @@ -0,0 +1,58 @@ +ldfps = 170100^tst +stfps = 170200^tst +/ +/ sqrt replaces the f.p. number in fr0 by its +/ square root. newton's method +/ +.globl sqrt, _sqrt +/ +/ +_sqrt: + mov r5,-(sp) + mov sp,r5 + movf 4(r5),fr0 + jsr pc,sqrt + mov (sp)+,r5 + rts pc + +sqrt: + tstf fr0 + cfcc + bne 1f + clc + rts pc /sqrt(0) +1: + bgt 1f + clrf fr0 + sec + rts pc / sqrt(-a) +1: + mov r0,-(sp) + stfps -(sp) + mov (sp),r0 + bic $!200,r0 / retain mode + ldfps r0 + movf fr1,-(sp) + movf fr2,-(sp) +/ + movf fr0,fr1 + movf fr0,-(sp) + asr (sp) + add $20100,(sp) + movf (sp)+,fr0 /initial guess + mov $4,r0 +1: + movf fr1,fr2 + divf fr0,fr2 + addf fr2,fr0 + mulf $half,fr0 / x = (x+a/x)/2 + sob r0,1b +2: + movf (sp)+,fr2 + movf (sp)+,fr1 + ldfps (sp)+ + mov (sp)+,r0 + clc + rts pc +/ +half = 40000 diff --git a/source/s3/switch.s b/source/s3/switch.s new file mode 100644 index 0000000..9f1bef5 --- /dev/null +++ b/source/s3/switch.s @@ -0,0 +1,40 @@ +/ switch -- switch on contents of r0 +/ +/ +/ calling sequence -- +/ +/ jsr r5,switch; swtab +/ +/ r0 is looked up in swtab and if found +/ control is returned to the corresponding place +/ if r0 is not found, the next inline instruction is +/ executed +/ +/ swtab format -- +/ +/ swtab: +/ val1; ret1 +/ val2; ret2 +/ ... +/ valn; retn +/ ..; 0 +/ + + .globl switch +switch: + mov r1,-(sp) + mov (r5)+,r1 +1: + cmp r0,(r1)+ + beq 1f + tst (r1)+ + bne 1b +2: + mov (sp)+,r1 + rts r5 +1: + mov (r1)+,r1 + beq 2b + mov r1,r5 + br 2b + diff --git a/source/s3/ttyn.s b/source/s3/ttyn.s new file mode 100644 index 0000000..5266b96 --- /dev/null +++ b/source/s3/ttyn.s @@ -0,0 +1,57 @@ +/ return name of current tty + +.globl ttyn, _ttyn + +_ttyn: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),r0 + jsr pc,1f + mov (sp)+,r5 + rts pc + +ttyn: + clr r0 +1: + mov $'x,name + tst -(sp) + sys fstat; buf + bes er1 + mov buf+2,(sp) + sys open; dev; 0 + bes er1 + mov r0,r1 +1: + mov r1,r0 + sys read; buf; 16. + bes er + cmp r0,$16. + bne er + mov $buf,r0 + cmp (r0)+,(sp) + bne 1b + cmp (r0)+,$"tt + bne 1b + cmpb (r0)+,$'y + bne 1b + tstb (r0)+ + beq 1b + cmpb (r0),$'\0 + bne 1b + movb -(r0),name + +er: + mov r1,r0 + sys close + +er1: + tst (sp)+ + movb name,r0 + rts pc + +.data +dev: +.even +.bss +buf: .=.+40. +name: .=.+2 diff --git a/source/s4/abort.s b/source/s4/abort.s new file mode 100644 index 0000000..73b0373 --- /dev/null +++ b/source/s4/abort.s @@ -0,0 +1,11 @@ +/ C library -- abort + +.globl _abort +iot = 4 + +_abort: + mov r5,-(sp) + mov sp,r5 + iot + mov (sp)+,r5 + rts pc diff --git a/source/s4/abs.s b/source/s4/abs.s new file mode 100644 index 0000000..ac8f2c9 --- /dev/null +++ b/source/s4/abs.s @@ -0,0 +1,16 @@ +/ abs - int absolute value. +/ fabs - floating abs + +.globl _abs +_abs: + mov 2(sp),r0 + bge 1f + neg r0 +1: + rts pc + +.globl _fabs +_fabs: + movf 2(sp),fr0 + absf fr0 + rts pc diff --git a/source/s4/alloc.s b/source/s4/alloc.s new file mode 100644 index 0000000..fc5b554 --- /dev/null +++ b/source/s4/alloc.s @@ -0,0 +1,165 @@ +/ storage allocator for use with C +/ +/ +/ +/ hand-tooled from C compilation to modify save-return +/ so that it can be called from within the C save +/ when running with coroutines +/ +/# +//* +/ * C storage allocator +/ * (circular first fit strategy) +/ */ +/#define BLOK 512 +/#define BUSY 01 +/ +/char *allocs[2] { /*initial empty arena*/ +/ &allocs[1], +/ &allocs[0] +/}; +/struct { int word; }; +/char **allocp &allocs[1]; /*current search pointer*/ +/char **alloct &allocs[1]; /*top of arena (last cell)*/ +/ +/alloc(nbytes) +/{ +/ register int nwords; +/ register char **p, **q; +/ static char **t; +/ +/ allocs[0].word =| BUSY; /*static initialization*/ +/ allocs[1].word =| BUSY; +/ +/ nwords = (nbytes+(2*sizeof(p)-1))/sizeof(p); +/ for(p=allocp;;) { +/ do { +/ if((p->word&BUSY)==0) { +/ while(((q = *p)->word&BUSY)==0) +/ *p = *q; +/ if(q >= &p[nwords]) +/ goto found; +/ } +/ q = p; +/ p = p->word & ~BUSY; +/ } while(q>=allocp || pword =| BUSY; +/ alloct = (*t = &t[BLOK]-1); +/ *alloct = allocs; +/ alloct->word =| BUSY; +/ } +/found: +/ allocp = &p[nwords]; +/ if(q>allocp) +/ *allocp = *p; +/ *p = allocp.word|BUSY; +/ return(p+1); +/} +/ +/free(p) +/char **p; +/{ +/ allocp = p-1; +/ allocp->word =& ~BUSY; +/} +.globl _allocs +.data +_allocs=. +2+_allocs +_allocs +.globl _allocp +.data +_allocp=. +2+_allocs +.globl _alloct +.data +_alloct=. +2+_allocs +.globl _alloc + +.globl _sbrk +.text +_alloc: +mov r5,-(sp) +mov sp,r5 +mov r4,-(sp) +mov r3,-(sp) +mov r2,-(sp) +bis $1,_allocs +bis $1,2+_allocs +mov 4(r5),r4 +add $3,r4 +asr r4 +mov _allocp,r3 +jbr L6 +L7:mov r3,r2 +mov (r3),r3 +bic $!177776,r3 +cmp r2,_allocp +jhis L6 +cmp r3,_allocp +jlo L6 +mov $2000,-(sp) +jsr pc,*$_sbrk +tst (sp)+ +mov r0,t +mov r0,*_alloct +cmp $177777,r0 +jeq L11 +mov _alloct,r0 +add $2,r0 +cmp t,r0 +jeq L12 +bis $1,*_alloct +L12:mov t,r0 +add $1776,r0 +mov r0,*t +mov r0,_alloct +mov $_allocs,*_alloct +bis $1,*_alloct +L6:bit $1,(r3) +jeq L8 +jbr L7 +L20001:mov (r2),(r3) +L8:mov (r3),r2 +bit $1,(r2) +jeq L20001 +mov r4,r0 +asl r0 +add r3,r0 +cmp r2,r0 +jlo L7 +mov r4,r0 +asl r0 +add r3,r0 +mov r0,_allocp +cmp r2,r0 +jlos L13 +mov (r3),*_allocp +L13:mov _allocp,r0 +bis $1,r0 +mov r0,(r3) +mov r3,r0 +add $2,r0 +L11: +mov (sp)+,r2 +mov (sp)+,r3 +mov (sp)+,r4 +mov (sp)+,r5 +rts pc +.globl _free +.text +_free: +mov r5,-(sp) +mov sp,r5 +mov 4(r5),r0 +add $177776,r0 +mov r0,_allocp +bic $!177776,*_allocp +mov (sp)+,r5 +rts pc +.bss +t: .=.+2 diff --git a/source/s4/atof.s b/source/s4/atof.s new file mode 100644 index 0000000..81d161d --- /dev/null +++ b/source/s4/atof.s @@ -0,0 +1,130 @@ +/ C library -- ascii to floating + +/ f = atof(p) +/ char *p; + +ldfps = 170100^tst +stfps = 170200^tst + +.globl _atof + +.globl csv, cret + +_atof: + jsr r5,csv + stfps -(sp) + ldfps $200 + movf fr1,-(sp) + clr -(sp) + clrf fr0 + clr r2 + mov 4(r5),r3 +1: + movb (r3)+,r0 + cmp $' ,r0 + beq 1b + cmpb r0,$'- + bne 2f + inc (sp) +1: + movb (r3)+,r0 +2: + sub $'0,r0 + cmp r0,$9. + bhi 2f + jsr pc,digit + br 1b + inc r2 + br 1b +2: + cmpb r0,$'.-'0 + bne 2f +1: + movb (r3)+,r0 + sub $'0,r0 + cmp r0,$9. + bhi 2f + jsr pc,digit + dec r2 + br 1b +2: + cmpb r0,$'E-'0 + beq 3f + cmpb r0,$'e-'0 + bne 1f +3: + clr r4 + clr r1 + cmpb (r3),$'- + bne 3f + inc r4 + inc r3 +3: + movb (r3)+,r0 + sub $'0,r0 + cmp r0,$9. + bhi 3f + mul $10.,r1 + add r0,r1 + br 3b +3: + tst r4 + bne 3f + neg r1 +3: + sub r1,r2 +1: + movf $one,fr1 + mov r2,-(sp) + beq 2f + bgt 1f + neg r2 +1: + cmp r2,$38. + blos 1f + clrf fr0 + tst (sp)+ + bmi out + movf $huge,fr0 + br out +1: + mulf $ten,fr1 + sob r2,1b +2: + tst (sp)+ + bge 1f + divf fr1,fr0 + br 2f +1: + mulf fr1,fr0 + cfcc + bvc 2f + movf $huge,fr0 +2: +out: + tst (sp)+ + beq 1f + negf fr0 +1: + movf (sp)+,fr1 + ldfps (sp)+ + jmp cret +/ +/ +digit: + cmpf $big,fr0 + cfcc + blt 1f + mulf $ten,fr0 + movif r0,fr1 + addf fr1,fr0 + rts pc +1: + add $2,(sp) + rts pc +/ +/ +one = 40200 +ten = 41040 +big = 56200 +huge = 77777 diff --git a/source/s4/atoi.c b/source/s4/atoi.c new file mode 100644 index 0000000..b55da69 --- /dev/null +++ b/source/s4/atoi.c @@ -0,0 +1,24 @@ +atoi(ap) +char *ap; +{ + register n, c; + register char *p; + int f; + + p = ap; + n = 0; + f = 0; +loop: + while(*p == ' ' || *p == ' ') + p++; + if(*p == '-') { + f++; + p++; + goto loop; + } + while(*p >= '0' && *p <= '9') + n = n*10 + *p++ - '0'; + if(f) + n = -n; + return(n); +} diff --git a/source/s4/cerror.s b/source/s4/cerror.s new file mode 100644 index 0000000..d7e2231 --- /dev/null +++ b/source/s4/cerror.s @@ -0,0 +1,12 @@ +/ C return sequence which +/ sets errno, returns -1. + +.globl cerror +.comm _errno,2 + +cerror: + mov r0,_errno + mov $-1,r0 + mov r5,sp + mov (sp)+,r5 + rts pc diff --git a/source/s4/chdir.s b/source/s4/chdir.s new file mode 100644 index 0000000..6247ab4 --- /dev/null +++ b/source/s4/chdir.s @@ -0,0 +1,20 @@ +/ C library -- chdir + +/ error = chdir(string); + +.globl _chdir, cerror + +_chdir: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + sys 0; 9f + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc +.data +9: + sys chdir; 0:.. diff --git a/source/s4/chmod.s b/source/s4/chmod.s new file mode 100644 index 0000000..ec06db7 --- /dev/null +++ b/source/s4/chmod.s @@ -0,0 +1,21 @@ +/ C library -- chmod + +/ error = chmod(string, mode); + +.globl _chmod, cerror + +_chmod: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov 6(r5),0f+2 + sys 0; 9f + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc +.data +9: + sys chmod; 0:..; .. diff --git a/source/s4/chown.s b/source/s4/chown.s new file mode 100644 index 0000000..a5b448a --- /dev/null +++ b/source/s4/chown.s @@ -0,0 +1,21 @@ +/ C library -- chown + +/ error = chown(string, owner); + +.globl _chown, cerror + +_chown: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov 6(r5),0f+2 + sys 0; 9f + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc +.data +9: + sys chown; 0:..; .. diff --git a/source/s4/close.s b/source/s4/close.s new file mode 100644 index 0000000..d65a9c5 --- /dev/null +++ b/source/s4/close.s @@ -0,0 +1,17 @@ +/ C library -- close + +/ error = close(file); + +.globl _close, cerror + +_close: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),r0 + sys close + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc diff --git a/source/s4/creat.s b/source/s4/creat.s new file mode 100644 index 0000000..39238ac --- /dev/null +++ b/source/s4/creat.s @@ -0,0 +1,22 @@ +/ C library -- creat + +/ file = creat(string, mode); +/ +/ file == -1 if error + +.globl _creat, cerror + +_creat: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov 6(r5),0f+2 + sys 0; 9f + bec 1f + jmp cerror +1: + mov (sp)+,r5 + rts pc +.data +9: + sys creat; 0:..; .. diff --git a/source/s4/crt0.s b/source/s4/crt0.s new file mode 100644 index 0000000..9eb3244 --- /dev/null +++ b/source/s4/crt0.s @@ -0,0 +1,20 @@ +/ C runtime startoff + +.globl savr5 +.globl _exit + +.globl _main + +start: + setd + mov sp,r0 + mov (r0),-(sp) + tst (r0)+ + mov r0,2(sp) + jsr pc,_main + mov r0,(sp) + jsr pc,*$_exit + sys exit + +.bss +savr5: .=.+2 diff --git a/source/s4/csv.s b/source/s4/csv.s new file mode 100644 index 0000000..8254ad6 --- /dev/null +++ b/source/s4/csv.s @@ -0,0 +1,22 @@ +/ C register save and restore -- version 12/74 + +.globl csv +.globl cret + +csv: + mov r5,r0 + mov sp,r5 + mov r4,-(sp) + mov r3,-(sp) + mov r2,-(sp) + tst -(sp) + jmp (r0) + +cret: + mov r5,r1 + mov -(r1),r4 + mov -(r1),r3 + mov -(r1),r2 + mov r5,sp + mov (sp)+,r5 + rts pc diff --git a/source/s4/ctime.c b/source/s4/ctime.c new file mode 100644 index 0000000..31ed6c5 --- /dev/null +++ b/source/s4/ctime.c @@ -0,0 +1,249 @@ +# +/* + * This routine converts time as follows. + * The epoch is 0000 Jan 1 1970 GMT. + * The argument time is in seconds since then. + * The localtime(t) entry returns a pointer to an array + * containing + * seconds (0-59) + * minutes (0-59) + * hours (0-23) + * day of month (1-31) + * month (0-11) + * year-1970 + * weekday (0-6, Sun is 0) + * day of the year + * daylight savings flag + * + * The routine corrects for daylight saving + * time and will work in any time zone provided + * "timezone" is adjusted to the difference between + * Greenwich and local standard time (measured in seconds). + * In places like Michigan "daylight" must + * be initialized to 0 to prevent the conversion + * to daylight time. + * There is a table which accounts for the peculiarities + * undergone by daylight time in 1974-1975. + * + * The routine does not work + * in Saudi Arabia which runs on Solar time. + * + * asctime(tvec)) + * where tvec is produced by localtime + * returns a ptr to a character string + * that has the ascii time in the form + * Thu Jan 01 00:00:00 1970n0\\ + * 01234567890123456789012345 + * 0 1 2 + * + * ctime(t) just calls localtime, then asctime. + */ +char cbuf[26]; +int dmsize[12] +{ + 31, + 28, + 31, + 30, + 31, + 30, + 31, + 31, + 30, + 31, + 30, + 31 +}; + +int timezone 5*60*60; +int tzname[] +{ + "EST", + "EDT", +}; +int daylight 1; /* Allow daylight conversion */ +/* + * The following table is used for 1974 and 1975 and + * gives the day number of the first day after the Sunday of the + * change. + */ +struct { + int daylb; + int dayle; +} daytab[] { + 5, 333, /* 1974: Jan 6 - last Sun. in Nov */ + 58, 303, /* 1975: Last Sun. in Feb - last Sun in Oct */ +}; + +#define SEC 0 +#define MIN 1 +#define HOUR 2 +#define MDAY 3 +#define MON 4 +#define YEAR 5 +#define WDAY 6 +#define YDAY 7 +#define ISDAY 8 + +ctime(at) +int *at; +{ + return(asctime(localtime(at))); +} + +localtime(tim) +int tim[]; +{ + register int *t, *ct, dayno; + int daylbegin, daylend; + int copyt[2]; + + t = copyt; + t[0] = tim[0]; + t[1] = tim[1]; + dpadd(t, -timezone); + ct = gmtime(t); + dayno = ct[YDAY]; + daylbegin = 119; /* last Sun in Apr */ + daylend = 303; /* Last Sun in Oct */ + if (ct[YEAR]==74 || ct[YEAR]==75) { + daylbegin = daytab[ct[YEAR]-74].daylb; + daylend = daytab[ct[YEAR]-74].dayle; + } + daylbegin = sunday(ct, daylbegin); + daylend = sunday(ct, daylend); + if (daylight && + (dayno>daylbegin || (dayno==daylbegin && ct[HOUR]>=2)) && + (dayno= 58) + d =+ dysize(t[YEAR]) - 365; + return(d - (d - t[YDAY] + t[WDAY] + 700) % 7); +} + +gmtime(tim) +int tim[]; +{ + register int d0, d1; + register *tp; + static xtime[9]; + extern int ldivr; + + /* + * break initial number into + * multiples of 8 hours. + * (28800 = 60*60*8) + */ + + d0 = ldiv(tim[0], tim[1], 28800); + d1 = ldivr; + tp = &xtime[0]; + + /* + * generate hours:minutes:seconds + */ + + *tp++ = d1%60; + d1 =/ 60; + *tp++ = d1%60; + d1 =/ 60; + d1 =+ (d0%3)*8; + d0 =/ 3; + *tp++ = d1; + + /* + * d0 is the day number. + * generate day of the week. + */ + + xtime[WDAY] = (d0+4)%7; + + /* + * year number + */ + for(d1=70; d0 >= dysize(d1); d1++) + d0 =- dysize(d1); + xtime[YEAR] = d1; + xtime[YDAY] = d0; + + /* + * generate month + */ + + if (dysize(d1)==366) + dmsize[1] = 29; + for(d1=0; d0 >= dmsize[d1]; d1++) + d0 =- dmsize[d1]; + dmsize[1] = 28; + *tp++ = d0+1; + *tp++ = d1; + xtime[ISDAY] = 0; + return(xtime); +} + +asctime(t) +int *t; +{ + register char *cp, *ncp; + register int *tp; + + cp = cbuf; + for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;); + ncp = &"SunMonTueWedThuFriSat"[3*t[6]]; + cp = cbuf; + *cp++ = *ncp++; + *cp++ = *ncp++; + *cp++ = *ncp++; + cp++; + tp = &t[4]; + ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3]; + *cp++ = *ncp++; + *cp++ = *ncp++; + *cp++ = *ncp++; + cp = ct_numb(cp, *--tp); + cp = ct_numb(cp, *--tp+100); + cp = ct_numb(cp, *--tp+100); + cp = ct_numb(cp, *--tp+100); + cp =+ 2; + cp = ct_numb(cp, t[YEAR]); + return(cbuf); +} + +dysize(y) +{ + if((y%4) == 0) + return(366); + return(365); +} + +ct_numb(acp, n) +{ + register char *cp; + + cp = acp; + cp++; + if (n>=10) + *cp++ = (n/10)%10 + '0'; + else + *cp++ = ' '; + *cp++ = n%10 + '0'; + return(cp); +} diff --git a/source/s4/dup.s b/source/s4/dup.s new file mode 100644 index 0000000..45013ec --- /dev/null +++ b/source/s4/dup.s @@ -0,0 +1,19 @@ +/ C library -- dup + +/ f = dup(of) +/ f == -1 for error + +dup = 41. + +.globl _dup, cerror + +_dup: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),r0 + sys dup + bec 1f + jmp cerror +1: + mov (sp)+,r5 + rts pc diff --git a/source/s4/errlst.c b/source/s4/errlst.c new file mode 100644 index 0000000..90f927f --- /dev/null +++ b/source/s4/errlst.c @@ -0,0 +1,36 @@ +char *sys_errlist[] { + "Error 0", + "Not super-user", + "No such file or directory", + "No such process", + "Interrupted system call", + "I/O error", + "No such device or address", + "Arg list too long", + "Exec format error", + "Bad file number", + "No children", + "No more processes", + "Not enough core", + "Permission denied", + "Error 14", + "Block device required", + "Mount device busy", + "File exists", + "Cross-device link", + "No such device", + "Not a directory", + "Is a directory", + "Invalid argument", + "File table overflow", + "Too many open files", + "Not a typewriter", + "Text file busy", + "File too large", + "No space left on device", + "Illegal seek", + "Read-only file system", + "Too many links", + "Broken Pipe", +}; +int sys_nerr { sizeof sys_errlist/sizeof sys_errlist[0] }; diff --git a/source/s4/execl.s b/source/s4/execl.s new file mode 100644 index 0000000..75bd05e --- /dev/null +++ b/source/s4/execl.s @@ -0,0 +1,19 @@ +/ C library -- execl + +/ execl(file, arg1, arg2, ... , 0); +/ + +.globl _execl, cerror + +_execl: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov r5,r0 + add $6,r0 + mov r0,0f+2 + sys 0; 9f + jmp cerror +.data +9: + sys exec; 0:..; .. diff --git a/source/s4/execv.s b/source/s4/execv.s new file mode 100644 index 0000000..77d7b2f --- /dev/null +++ b/source/s4/execv.s @@ -0,0 +1,31 @@ +/ C library -- execv + +/ execv(file, argv); +/ +/ where argv is a vector argv[0] ... argv[x], 0 +/ last vector element must be 0 +/ +/ The _exectrap flags is used by the debugger and causes +/ a trace trap on the first instruction of the executed instruction +/ to give a chance to set breakpoints. + +.globl _execv, cerror +.comm __exectrap,2 +rtt = 6 + +_execv: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov 6(r5),0f+2 + tst __exectrap + beq 1f + mov $170020,-(sp) / t-bit + mov $1f,-(sp) + rtt +1: + sys 0; 9f + jmp cerror +.data +9: + sys exec; 0:..; .. diff --git a/source/s4/exit.s b/source/s4/exit.s new file mode 100644 index 0000000..c50b47e --- /dev/null +++ b/source/s4/exit.s @@ -0,0 +1,13 @@ +/ C library -- exit + +/ exit(code) +/ code is return in r0 to system + +.globl _exit + +_exit: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),r0 + sys exit + diff --git a/source/s4/fcrt0.s b/source/s4/fcrt0.s new file mode 100644 index 0000000..16662f3 --- /dev/null +++ b/source/s4/fcrt0.s @@ -0,0 +1,23 @@ +/ C runtime startoff +/ with floating point interpreter + +.globl savr5 +.globl fptrap +.globl _exit + +.globl _main + +start: + sys signal; 4; fptrap + setd + mov sp,r0 + mov (r0),-(sp) + tst (r0)+ + mov r0,2(sp) + jsr pc,_main + mov r0,(sp) + jsr pc,*$_exit + sys exit + +.bss +savr5: .=.+2 diff --git a/source/s4/ffltpr.s b/source/s4/ffltpr.s new file mode 100644 index 0000000..29320cb --- /dev/null +++ b/source/s4/ffltpr.s @@ -0,0 +1,10 @@ +/ C library-- fake floating output + +.globl pfloat +.globl pscien + +pfloat: +pscien: + add $8,r4 + movb $'?,(r3)+ + rts pc diff --git a/source/s4/fltpr.s b/source/s4/fltpr.s new file mode 100644 index 0000000..5457ad8 --- /dev/null +++ b/source/s4/fltpr.s @@ -0,0 +1,91 @@ +/ C library-- floating output + +.globl pfloat +.globl pscien +.globl fltused + +.globl _ndigit +.globl ecvt +.globl fcvt + +fltused: / force loading +pfloat: + mov r0,_ndigit + tst r2 + bne 1f + mov $6,_ndigit +1: + movf (r4)+,fr0 + jsr pc,fcvt + tst r1 + beq 1f + movb $'-,(r3)+ +1: + tst r2 + bgt 1f + movb $'0,(r3)+ +1: + mov r2,r1 + ble 1f +2: + movb (r0)+,(r3)+ + sob r1,2b +1: + mov _ndigit,r1 + beq 1f + movb $'.,(r3)+ +1: + neg r2 + ble 1f +2: + dec r1 + blt 1f + movb $'0,(r3)+ + sob r2,2b +1: + tst r1 + ble 2f +1: + movb (r0)+,(r3)+ + sob r1,1b +2: + rts pc + +pscien: + mov r0,_ndigit + tst r2 + bne 1f + mov $6,_ndigit +1: + movf (r4)+,fr0 + jsr pc,ecvt + tst r1 + beq 1f + movb $'-,(r3)+ +1: + movb (r0)+,(r3)+ + movb $'.,(r3)+ + mov _ndigit,r1 + dec r1 + ble 1f +2: + movb (r0)+,(r3)+ + sob r1,2b +1: + movb $'e,(r3)+ + dec r2 + mov r2,r1 + bge 1f + movb $'-,(r3)+ + neg r1 + br 2f +1: + movb $'+,(r3)+ +2: + clr r0 + div $10.,r0 + add $'0,r0 + movb r0,(r3)+ + add $'0,r1 + movb r1,(r3)+ + rts pc diff --git a/source/s4/fork.s b/source/s4/fork.s new file mode 100644 index 0000000..b155cc0 --- /dev/null +++ b/source/s4/fork.s @@ -0,0 +1,24 @@ +/ C library -- fork + +/ pid = fork(); +/ +/ pid == 0 in child process; pid == -1 means error return +/ in child, parents id is in par_uid if needed + +.globl _fork, cerror, _par_uid + +_fork: + mov r5,-(sp) + mov sp,r5 + sys fork + br 1f + bec 2f + jmp cerror +1: + mov r0,_par_uid + clr r0 +2: + mov (sp)+,r5 + rts pc +.bss +_par_uid: .=.+2 diff --git a/source/s4/fstat.s b/source/s4/fstat.s new file mode 100644 index 0000000..6300be5 --- /dev/null +++ b/source/s4/fstat.s @@ -0,0 +1,25 @@ +/ C library -- fstat + +/ error = fstat(file, statbuf); + +/ int statbuf[17] or +/ char statbuf[34] +/ as appropriate + +.globl _fstat, cerror + +_fstat: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),r0 + mov 6(r5),0f + sys 0; 9f + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc +.data +9: + sys fstat; 0:.. diff --git a/source/s4/getc.s b/source/s4/getc.s new file mode 100644 index 0000000..e6899f1 --- /dev/null +++ b/source/s4/getc.s @@ -0,0 +1,83 @@ +/ getw/getc -- get words/characters from input file +/ fopen -- open a file for use by get(c|w) + +indir = 0 + +.globl _getc, _getw, _fopen +.globl cerror +.comm _errno,2 + +_fopen: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + sys 0; 9f + .data +9: sys open; 0:..; 0 + .text + bes badret + mov 6(r5),r1 + mov r0,(r1)+ + clr (r1)+ + clr r0 + mov (sp)+,r5 + rts pc + +_getw: + clr _errno + mov r5,-(sp) + mov sp,r5 + mov 4(r5),r1 + sub $2,2(r1) + bge 1f + cmp 2(r1),$-1 + blt 2f + movb *4(r1),-(sp) + jsr pc,fill + mov 4(r1),r0 + br 3f +2: + jsr pc,fill + dec 2(r1) +1: + mov 4(r1),r0 + movb (r0)+,-(sp) +3: + movb (r0)+,1(sp) + mov r0,4(r1) + mov (sp)+,r0 + mov (sp)+,r5 + rts pc + +_getc: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),r1 + dec 2(r1) + bge 1f + jsr pc,fill +1: + clr r0 + bisb *4(r1),r0 + inc 4(r1) + mov (sp)+,r5 + rts pc + +fill: + mov r1,r0 + add $6,r0 + mov r0,0f + mov r0,4(r1) + mov (r1),r0 + sys 0; 9f +.data +9: sys read; 0:..; 512. +.text + bes badret + dec r0 + bmi badret + mov r0,2(r1) + rts pc + +badret: + jmp cerror diff --git a/source/s4/getchr.s b/source/s4/getchr.s new file mode 100644 index 0000000..02faec6 --- /dev/null +++ b/source/s4/getchr.s @@ -0,0 +1,32 @@ +/ getchar() -- get a character from input file fin + +.globl _getchar +.comm _errno,2 +.comm _fin,518. + +_getchar: + mov r5,-(sp) + mov sp,r5 + dec _fin+2 + bge 1f + mov $_fin+6,_fin+4 + mov _fin,r0 + sys read; _fin+6; 512. + bes badret + tst r0 + beq badret + dec r0 + mov r0,_fin+2 +1: + clr r0 + bisb *_fin+4,r0 + inc _fin+4 + mov (sp)+,r5 + rts pc + +badret: + mov r0,_errno + clr r0 + clr _fin+2 + mov (sp)+,r5 + rts pc diff --git a/source/s4/getcsw.s b/source/s4/getcsw.s new file mode 100644 index 0000000..ac97e83 --- /dev/null +++ b/source/s4/getcsw.s @@ -0,0 +1,12 @@ +/ C library - getcsw + +/ csw = getcsw(); + +.globl _getcsw + +_getcsw: + mov r5,-(sp) + mov sp,r5 + sys 38. + mov (sp)+,r5 + rts pc diff --git a/source/s4/getgid.s b/source/s4/getgid.s new file mode 100644 index 0000000..371bcd2 --- /dev/null +++ b/source/s4/getgid.s @@ -0,0 +1,14 @@ +/ C library -- getgid + +/ gid = getgid(); +/ + +getgid = 47. +.globl _getgid + +_getgid: + mov r5,-(sp) + mov sp,r5 + sys getgid + mov (sp)+,r5 + rts pc diff --git a/source/s4/getpid.s b/source/s4/getpid.s new file mode 100644 index 0000000..6f7c24f --- /dev/null +++ b/source/s4/getpid.s @@ -0,0 +1,13 @@ +/ getpid -- get process ID + +getpid = 20. + +.globl _getpid + +_getpid: + mov r5,-(sp) + mov sp,r5 + sys getpid + mov (sp)+,r5 + rts pc + diff --git a/source/s4/getpw.c b/source/s4/getpw.c new file mode 100644 index 0000000..fe53c3c --- /dev/null +++ b/source/s4/getpw.c @@ -0,0 +1,43 @@ +getpw(uid, buf) +int uid; +char buf[]; +{ + auto pbuf[259]; + static pwf; + register n, c; + register char *bp; + + if(pwf == 0) + pwf = open("/etc/passwd", 0); + if(pwf < 0) + return(1); + seek(pwf, 0, 0); + pbuf[0] = pwf; + pbuf[1] = 0; + pbuf[2] = 0; + uid =& 0377; + + for (;;) { + bp = buf; + while((c=getc(pbuf)) != '\n') { + if(c <= 0) + return(1); + *bp++ = c; + } + *bp++ = '\0'; + bp = buf; + n = 3; + while(--n) + while((c = *bp++) != ':') + if(c == '\n') + return(1); + while((c = *bp++) != ':') { + if(c<'0' || c>'9') + continue; + n = n*10+c-'0'; + } + if(n == uid) + return(0); + } + return(1); +} diff --git a/source/s4/getuid.s b/source/s4/getuid.s new file mode 100644 index 0000000..da25322 --- /dev/null +++ b/source/s4/getuid.s @@ -0,0 +1,13 @@ +/ C library -- getuid + +/ uid = getuid(); +/ + +.globl _getuid + +_getuid: + mov r5,-(sp) + mov sp,r5 + sys getuid + mov (sp)+,r5 + rts pc diff --git a/source/s4/gtty.s b/source/s4/gtty.s new file mode 100644 index 0000000..16c040e --- /dev/null +++ b/source/s4/gtty.s @@ -0,0 +1,24 @@ +/ C library -- gtty + +/ error = gtty(filep, ttyvec); + +/ filep is descriptor of open tty +/ ttyvec[0, 1, 2] correspond to args of gtty + +.globl _gtty, cerror + +_gtty: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),r0 + mov 6(r5),0f + sys 0; 9f + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc +.data +9: + sys gtty; 0:.. diff --git a/source/s4/hmul.s b/source/s4/hmul.s new file mode 100644 index 0000000..e1081d9 --- /dev/null +++ b/source/s4/hmul.s @@ -0,0 +1,6 @@ +.globl _hmul + +_hmul: + mov 2(sp),r0 + mul 4(sp),r0 + rts pc diff --git a/source/s4/kill.s b/source/s4/kill.s new file mode 100644 index 0000000..57fba82 --- /dev/null +++ b/source/s4/kill.s @@ -0,0 +1,22 @@ +/ C library -- kill + +.globl _kill, cerror +kill = 37. +indir = 0 + +_kill: + mov r5,-(sp) + mov sp,r5 + mov 4(sp),r0 + mov 6(sp),8f + sys indir; 9f + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc + +.data +9: + sys kill; 8:.. diff --git a/source/s4/ladd.s b/source/s4/ladd.s new file mode 100644 index 0000000..6de48f4 --- /dev/null +++ b/source/s4/ladd.s @@ -0,0 +1,38 @@ +/ C routine-- long integer subtract and add + +/ ladd/lsub (a, b, c); +/ int a[2], b[2], c[2]; +/ a = b +- c; + +.globl _lsub +.globl _ladd +.globl csv +.globl cret + +_lsub: + jsr r5,csv + mov 6(r5),r2 + mov (r2)+,r0 + mov (r2),r1 + mov 10(r5),r2 + sub (r2)+,r0 + sub (r2),r1 + sbc r0 + mov 4(r5),r2 + mov r0,(r2)+ + mov r1,(r2) + jmp cret + +_ladd: + jsr r5,csv + mov 6(r5),r2 + mov (r2)+,r0 + mov (r2),r1 + mov 10(r5),r2 + add (r2)+,r0 + add (r2),r1 + adc r0 + mov 4(r5),r2 + mov r0,(r2)+ + mov r1,(r2) + jmp cret diff --git a/source/s4/ldfps.s b/source/s4/ldfps.s new file mode 100644 index 0000000..800cf62 --- /dev/null +++ b/source/s4/ldfps.s @@ -0,0 +1,11 @@ +ldfps = 170100^tst +/ +/ ldfps(number); + +.globl _ldfps +_ldfps: + mov r5,-(sp) + mov sp,r5 + ldfps 4(r5) + mov (sp)+,r5 + rts pc diff --git a/source/s4/link.s b/source/s4/link.s new file mode 100644 index 0000000..332c0e5 --- /dev/null +++ b/source/s4/link.s @@ -0,0 +1,22 @@ +/ C library -- link + +/ error = link(old-file, new-file); +/ + +.globl _link, cerror + +_link: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov 6(r5),0f+2 + sys 0; 9f + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc +.data +9: + sys link; 0:..; .. diff --git a/source/s4/locv.s b/source/s4/locv.s new file mode 100644 index 0000000..9650747 --- /dev/null +++ b/source/s4/locv.s @@ -0,0 +1,56 @@ +/ C library -- long output conversion + +.globl _locv + +_locv: + mov r5,-(sp) + mov sp,r5 + mov r4,-(sp) + mov r3,-(sp) + mov r2,-(sp) + mov $buf,r4 + mov 6(r5),r3 + mov 4(r5),r2 + bpl 1f + neg r2 + neg r3 + sbc r2 + movb $'-,(r4)+ +1: + jsr pc,1f + clrb (r4)+ + mov $buf,r0 + mov (sp)+,r2 + mov (sp)+,r3 + mov (sp)+,r4 + mov (sp)+,r5 + rts pc + +1: + jsr pc,divid + add $'0,r1 + mov r1,-(sp) + ashc $0,r2 + beq 1f + jsr pc,1b +1: + movb (sp)+,(r4)+ + rts pc + +divid: + clr r1 + mov $32.,r0 +1: + ashc $1,r2 + rol r1 + cmp r1,$10. + blo 2f + sub $10.,r1 + inc r3 +2: + sob r0,1b + rts pc + + +.bss +buf: .=.+12. diff --git a/source/s4/ltod.s b/source/s4/ltod.s new file mode 100644 index 0000000..8dbb835 --- /dev/null +++ b/source/s4/ltod.s @@ -0,0 +1,27 @@ +/ C library +/ return floating-point from long integer +/ d = ltod(l) + +.globl _ltod +_ltod: + mov r5,-(sp) + mov sp,r5 + setl + movif *4(r5),fr0 + seti + mov (sp)+,r5 + rts pc + +/ return long integer from floating +/ dtol(d, l) + +.globl _dtol +_dtol: + mov r5,-(sp) + mov sp,r5 + setl + movf 4(r5),fr0 + movfi fr0,*12.(r5) + seti + mov (sp)+,r5 + rts pc diff --git a/source/s4/run b/source/s4/run new file mode 100644 index 0000000..3a29b7d --- /dev/null +++ b/source/s4/run @@ -0,0 +1,42 @@ +as crt0.s +cmp a.out /lib/crt0.o +cp a.out /lib/crt0.o +as fcrt0.s +cmp a.out /lib/fcrt0.o +cp a.out /lib/fcrt0.o +as abort.s; mv a.out abort.o +as abs.s; mv a.out abs.o +as alloc.s; mv a.out alloc.o +as atof.s; mv a.out atof.o +as cerror.s; mv a.out cerror.o +as chdir.s; mv a.out chdir.o +as chmod.s; mv a.out chmod.o +as chown.s; mv a.out chown.o +as close.s; mv a.out close.o +as creat.s; mv a.out creat.o +as csv.s; mv a.out csv.o +as dup.s; mv a.out dup.o +as execl.s; mv a.out execl.o +as execv.s; mv a.out execv.o +as exit.s; mv a.out exit.o +as ffltpr.s; mv a.out ffltpr.o +as fltpr.s; mv a.out fltpr.o +as fork.s; mv a.out fork.o +as fstat.s; mv a.out fstat.o +as getc.s; mv a.out getc.o +as getchr.s; mv a.out getchr.o +as getcsw.s; mv a.out getcsw.o +as getgid.s; mv a.out getgid.o +as getpid.s; mv a.out getpid.o +as getuid.s; mv a.out getuid.o +as gtty.s; mv a.out gtty.o +as hmul.s; mv a.out hmul.o +as kill.s; mv a.out kill.o +as ladd.s; mv a.out ladd.o +as ldfps.s; mv a.out ldfps.o +as link.s; mv a.out link.o +as locv.s; mv a.out locv.o +as ltod.s; mv a.out ltod.o +cc -c -O *.c +ar r /lib/libc.a +rm *.o diff --git a/source/s5/makdir.s b/source/s5/makdir.s new file mode 100644 index 0000000..6331422 --- /dev/null +++ b/source/s5/makdir.s @@ -0,0 +1,20 @@ +/ C library -- makdir + +/ error = makdir(string); + +.globl _makdir, cerror + +_makdir: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + sys 0; 9f + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc +.data +9: + sys makdir; 0:.. diff --git a/source/s5/mcount.s b/source/s5/mcount.s new file mode 100644 index 0000000..a3d91d2 --- /dev/null +++ b/source/s5/mcount.s @@ -0,0 +1,20 @@ +/ count subroutine calls during profiling + +.globl mcount +.comm countbase,2 + +mcount: + mov (r0),r1 + bne 1f + mov countbase,r1 + beq 2f + add $6,countbase + mov (sp),(r1)+ + mov r1,(r0) +1: + inc 2(r1) + bne 2f + inc (r1) +2: + rts pc + diff --git a/source/s5/mcrt0.s b/source/s5/mcrt0.s new file mode 100644 index 0000000..8cc665a --- /dev/null +++ b/source/s5/mcrt0.s @@ -0,0 +1,60 @@ +/ C runtime startoff including monitoring + +cbufs = 150. + +.globl _monitor +.globl _sbrk +.globl _main +.globl _exit +.globl _etext +.comm countbase,2 + +.comm savr5,2 + +start: + setd + mov sp,r0 + mov (r0),-(sp) + tst (r0)+ + mov r0,2(sp) + + mov $_etext,r1 + sub $eprol,r1 + add $7,r1 + ash $-3,r1 + bic $!17777,r1 + mov $cbufs,-(sp) + add $3*[cbufs+1],r1 + mov r1,-(sp) + asl r1 + mov r1,-(sp) + jsr pc,_sbrk + tst (sp)+ + cmp r0,$-1 + beq 9f + mov r0,-(sp) + add $6,r0 + mov r0,countbase + mov $_etext,-(sp) + mov $eprol,-(sp) + jsr pc,_monitor + add $10.,sp + jsr pc,_main + cmp (sp)+,(sp)+ + jsr pc,_exit + +9: + mov $2,r0 + sys write; 8f; 9f-8f + +.data; 8: ; 9:.even; .text + +_exit: + mov r5,-(sp) + mov sp,r5 + clr -(sp) + jsr pc,_monitor + tst (sp)+ + mov 4(r5),r0 + sys exit +eprol: diff --git a/source/s5/mdate.s b/source/s5/mdate.s new file mode 100644 index 0000000..6975e09 --- /dev/null +++ b/source/s5/mdate.s @@ -0,0 +1,21 @@ +/ C library-- mdate + +.globl _mdate, cerror + +_mdate: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov 6(r5),r1 + mov (r1)+,r0 + mov (r1),r1 + sys 0; 9f + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc +.data +9: + sys mdate; 0:.. diff --git a/source/s5/mknod.s b/source/s5/mknod.s new file mode 100644 index 0000000..a22b167 --- /dev/null +++ b/source/s5/mknod.s @@ -0,0 +1,23 @@ +/ C library -- mknod + +/ error = mknod(string, mode, major.minor); + +.globl _mknod, cerror + +mknod = 14. +_mknod: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov 6(r5),0f+2 + mov 8(r5),0f+4 + sys 0; 9f + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc +.data +9: + sys mknod; 0:..; ..; .. diff --git a/source/s5/mon.c b/source/s5/mon.c new file mode 100644 index 0000000..1fb22d7 --- /dev/null +++ b/source/s5/mon.c @@ -0,0 +1,31 @@ +monitor(lowpc, highpc, buf, bufsiz, cntsiz) +char *lowpc, *highpc; +int *buf, bufsiz; +{ + register char *o; + static *sbuf, ssiz; + + if (lowpc == 0) { + profil(0, 0, 0, 0); + o = creat("mon.out", 0666); + write(o, sbuf, ssiz<<1); + close(o); + return; + } + if (nargs() <= 4) + cntsiz = 0; + ssiz = bufsiz; + buf[0] = lowpc; + buf[1] = highpc; + buf[2] = cntsiz; + sbuf = buf; + buf =+ 3*(cntsiz+1); + bufsiz =- 3*(cntsiz+1); + if (bufsiz<=0) + return; + o = ((highpc - lowpc)>>1) & 077777; + if(bufsiz < o) + o = ldiv(bufsiz, 0, o<<1); else + o = 077777; + profil(buf, bufsiz<<1, lowpc, o<<1); +} diff --git a/source/s5/mount.s b/source/s5/mount.s new file mode 100644 index 0000000..1835788 --- /dev/null +++ b/source/s5/mount.s @@ -0,0 +1,22 @@ +/ C library -- mount + +/ error = mount(dev, file, flag) + +.globl _mount, cerror + +_mount: + mov r5,-(sp) + mov sp,r5 + mov 4(sp),0f + mov 6(sp),0f+2 + mov 8(sp),0f+4 + sys 0; 9f + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc +.data +9: + sys mount; 0:..; ..; .. diff --git a/source/s5/nargs.s b/source/s5/nargs.s new file mode 100644 index 0000000..2dd8449 --- /dev/null +++ b/source/s5/nargs.s @@ -0,0 +1,62 @@ +/ C library -- nargs + +/ WARNING: this routine does not work +/ with user I&D space separate. +/ Moreover, due to a design botch in +/ the 11/45, it cannot be made to work +/ by adding mfpi instructions. + +.globl _nargs + +_nargs: + mov r5,-(sp) + mov 2(r5),r1 / pc of caller of caller + mov sp,r5 + clr r0 + cmp -4(r1),jsrsd + bne 8f + mov $2,r0 +8: + cmp (r1),tsti + bne 1f + add $2,r0 + br 2f +1: + cmp (r1),cmpi + bne 1f + add $4,r0 + br 2f +1: + cmp (r1),addi + bne 1f + add 2(r1),r0 + br 2f +1: + cmp (r1),jmpi + bne 1f + add 2(r1),r1 + add $4,r1 + br 8b +1: + cmpb 1(r1),bri+1 + bne 2f + mov r0,-(sp) + mov (r1),r0 + swab r0 + ash $-7,r0 + add r0,r1 + add $2,r1 + mov (sp)+,r0 + br 8b +2: + asr r0 + mov (sp)+,r5 + rts pc + +.data +jsrsd: jsr pc,*$0 +tsti: tst (sp)+ +cmpi: cmp (sp)+,(sp)+ +addi: add $0,sp +jmpi: jmp 0 +bri: br . diff --git a/source/s5/nice.s b/source/s5/nice.s new file mode 100644 index 0000000..4121cb9 --- /dev/null +++ b/source/s5/nice.s @@ -0,0 +1,17 @@ +/ C library-- nice + +/ error = nice(hownice) + +.globl _nice, cerror + +_nice: + mov r5,-(sp) + mov sp,r5 + mov 4(sp),r0 + sys nice + bec 1f + jmp cerror +1: + clr r0 + mov (sp)+,r5 + rts pc diff --git a/source/s5/nlist.s b/source/s5/nlist.s new file mode 100644 index 0000000..f46487e --- /dev/null +++ b/source/s5/nlist.s @@ -0,0 +1,98 @@ +/ nlist -- extract values from name list +/ + +/ nlist(file, list); +/ +.globl _nlist + +_nlist: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov 6(r5),r1 + mov r2,-(sp) + + mov r1,r0 +1: + tst (r0) + beq 1f + add $8.,r0 + clr (r0)+ + clr (r0)+ / initialize to undefined + br 1b +1: + sys 0; 9f +.data +9: + sys open; 0:..; 0 +.text + bes done + mov r0,r2 + sys read; buf; 20 + cmp r0,$20 + bne cdone + mov buf+4,count / assume older a.out + mov buf+2,0f + cmp buf,$405 + beq 1f + mov buf+8.,count / now assume newer + mov buf+2,r0 / txt + add buf+4,r0 / data + cmp buf+16,$1 / relocation? + beq 4f + asl r0 / txt+data reloc +4: + add $20,r0 / header + mov r0,0f + cmp buf,$411 + beq 1f + cmp buf,$410 + beq 1f + cmp buf,$407 + bne cdone +1: + mov r2,r0 + sys 0; 9f +.data +9: + sys seek; 0:..; 0 +.text + +1: + sub $12.,count + blt cdone + mov r2,r0 + sys read; buf; 12. + cmp r0,$12. + bne cdone + mov r1,r0 + +2: + tst (r0) + beq 1b + cmp (r0),buf + bne 1f + cmp 2(r0),buf+2 + bne 1f + cmp 4(r0),buf+4 + bne 1f + cmp 6(r0),buf+6 + bne 1f + mov buf+8.,8.(r0) + mov buf+10.,10.(r0) +1: + add $12.,r0 + br 2b + +cdone: + mov r2,r0 + sys close + +done: + mov (sp)+,r2 + mov (sp)+,r5 + rts pc + +.bss +buf: .=.+20 +count: .=.+2 diff --git a/source/s5/open.s b/source/s5/open.s new file mode 100644 index 0000000..6d4c49b --- /dev/null +++ b/source/s5/open.s @@ -0,0 +1,22 @@ +/ C library -- open + +/ file = open(string, mode) +/ +/ file == -1 means error + +.globl _open, cerror + +_open: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov 6(r5),0f+2 + sys 0; 9f + bec 1f + jmp cerror +1: + mov (sp)+,r5 + rts pc +.data +9: + sys open; 0:..; .. diff --git a/source/s5/perror.c b/source/s5/perror.c new file mode 100644 index 0000000..e15a2f3 --- /dev/null +++ b/source/s5/perror.c @@ -0,0 +1,40 @@ +/* + * Print the error indicated + * in the cerror cell. + */ + +int errno; +int sys_nerr; +char *sys_errlist[]; +perror(s) +char *s; +{ + register char *c; + register n; + + c = "Unknown error"; + if(errno < sys_nerr) + c = sys_errlist[errno]; + n = strlen(s); + if(n) { + write(2, s, n); + write(2, ": ", 2); + } + write(2, c, strlen(c)); + write(2, "\n", 1); +} + +/* + * Return the number of bytes in a string + */ + +strlen(str) +char *str; +{ + register char *s; + + s = str; + while(*s++) + ; + return(s-str-1); +} diff --git a/source/s5/pipe.s b/source/s5/pipe.s new file mode 100644 index 0000000..9db458e --- /dev/null +++ b/source/s5/pipe.s @@ -0,0 +1,22 @@ +/ pipe -- C library + +/ pipe(f) +/ int f[2]; + +.globl _pipe, cerror + +pipe = 42. + +_pipe: + mov r5,-(sp) + mov sp,r5 + sys pipe + bec 1f + jmp cerror +1: + mov 4(r5),r2 + mov r0,(r2)+ + mov r1,(r2) + clr r0 + mov (sp)+,r5 + rts pc diff --git a/source/s5/printf.s b/source/s5/printf.s new file mode 100644 index 0000000..b801aba --- /dev/null +++ b/source/s5/printf.s @@ -0,0 +1,238 @@ +/ C library -- printf + + +.globl _printf + +.globl pfloat +.globl pscien +.globl _putchar + +.globl csv +.globl cret + +_printf: + jsr r5,csv + sub $126.,sp + mov 4(r5),formp / format + mov r5,r4 + add $6,r4 / arglist +loop: + movb *formp,r0 + beq 1f + inc formp + cmp r0,$'% + beq 2f +3: + mov r0,(sp) + jsr pc,*$_putchar + br loop +1: + jmp cret +2: + clr rjust + clr ndigit + cmpb *formp,$'- + bne 2f + inc formp + inc rjust +2: + jsr r3,gnum + mov r1,width + clr ndfnd + cmp r0,$'. + bne 1f + jsr r3,gnum + mov r1,ndigit +1: + mov sp,r3 + add $4,r3 + mov $swtab,r1 +1: + mov (r1)+,r2 + beq 3b + cmp r0,(r1)+ + bne 1b + jmp (r2) + .data +swtab: + decimal; 'd + octal; 'o + hex; 'x + float; 'f + scien; 'e + charac; 'c + string; 's + logical; 'l + remote; 'r + 0; 0 + .text + +decimal: + mov (r4)+,r1 + bge 1f + neg r1 + movb $'-,(r3)+ + br 1f + +logical: + mov (r4)+,r1 +1: + jsr pc,1f + br prbuf +1: + clr r0 + div $10.,r0 + mov r1,-(sp) + mov r0,r1 + beq 1f + jsr pc,1b +1: + mov (sp)+,r0 + add $'0,r0 + movb r0,(r3)+ + rts pc + +charac: + movb (r4)+,(r3)+ + bne 1f + dec r3 +1: + movb (r4)+,(r3)+ + bne prbuf + dec r3 + br prbuf + +string: + mov ndigit,r1 + clr r3 + mov (r4),r2 +1: + tstb (r2)+ + beq 1f + inc r3 + sob r1,1b +1: + mov (r4)+,r2 + br prstr + +hex: + mov $1f,r2 + .data +1: + -4; !17 + .text + br 2f + +octal: + mov $1f,r2 + .data +1: + -3; !7 + .text +2: + mov (r4)+,r1 + beq 2f + tst ndigit + beq 2f + movb $'0,(r3)+ +2: + clr r0 + jsr pc,1f + br prbuf +1: + mov r1,-(sp) + ashc (r2),r0 + beq 1f + jsr pc,1b +1: + mov (sp)+,r0 + bic 2(r2),r0 + add $'0,r0 + cmp r0,$'9 + ble 1f + add $'A-'0-10.,r0 +1: + movb r0,(r3)+ + rts pc + +float: + mov ndigit,r0 + mov ndfnd,r2 + jsr pc,pfloat + br prbuf + +scien: + mov ndigit,r0 + mov ndfnd,r2 + jsr pc,pscien + br prbuf + +remote: + mov (r4)+,r4 + mov (r4)+,formp + jmp loop + +prbuf: + mov sp,r2 + add $4,r2 + sub r2,r3 +prstr: + mov r4,-(sp) + mov $' ,-(sp) + mov r3,r4 + neg r3 + add width,r3 + ble 1f + tst rjust + bne 1f +2: + jsr pc,*$_putchar + sob r3,2b +1: + tst r4 + beq 2f +1: + movb (r2)+,(sp) + jsr pc,*$_putchar + sob r4,1b +2: + tst r3 + ble 1f + mov $' ,(sp) +2: + jsr pc,*$_putchar + sob r3,2b +1: + tst (sp)+ + mov (sp)+,r4 + jmp loop + +gnum: + clr ndfnd + clr r1 +1: + movb *formp,r0 + inc formp + sub $'0,r0 + cmp r0,$'*-'0 + bne 2f + mov (r4)+,r0 + br 3f +2: + cmp r0,$9. + bhi 1f +3: + inc ndfnd + mul $10.,r1 + add r0,r1 + br 1b +1: + add $'0,r0 + rts r3 + +.bss +width: .=.+2 +formp: .=.+2 +rjust: .=.+2 +ndfnd: .=.+2 +ndigit: .=.+2 diff --git a/source/s5/prof.s b/source/s5/prof.s new file mode 100644 index 0000000..f206904 --- /dev/null +++ b/source/s5/prof.s @@ -0,0 +1,16 @@ +/ profil + +.globl _profil +_profil: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov 6(r5),0f+2 + mov 10(r5),0f+4 + mov 12(r5),0f+6 + sys 0; 9f + mov (sp)+,r5 + rts pc +.data +9: + sys 44.; 0:..; ..; ..; .. diff --git a/source/s5/ptrace.s b/source/s5/ptrace.s new file mode 100644 index 0000000..2d17d9f --- /dev/null +++ b/source/s5/ptrace.s @@ -0,0 +1,28 @@ +/ ptrace -- C library + +/ result = ptrace(req, pid, addr, data); + +ptrace = 26. +indir = 0 + +.globl _ptrace +.globl cerror, _errno + +_ptrace: + mov r5,-(sp) + mov sp,r5 + mov 4.(r5),0f+4 + mov 6.(r5),0f+0 + mov 8.(r5),0f+2 + mov 10.(r5),r0 + clr _errno + sys indir; 9f + bec 1f + jmp cerror +1: + mov (sp)+,r5 + rts pc + +.data +9: + sys ptrace; 0: .=.+6 diff --git a/source/s5/putc.s b/source/s5/putc.s new file mode 100644 index 0000000..39e86f5 --- /dev/null +++ b/source/s5/putc.s @@ -0,0 +1,89 @@ +/ putw/putc -- write words/characters on output file + + .globl _putc, _putw, _fflush, _fcreat + .globl cerror + .comm _errno,2 + +_fcreat: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),0f + mov 6(r5),r1 + mov pc,(r1) / a putatively illegal file desc. + sys 0; 9f +.data +9: sys creat; 0:..; 666 +.text + bes badret + mov r0,(r1)+ + clr (r1)+ + clr (r1)+ + br goodret + +_putw: + mov r5,-(sp) + mov sp,r5 + mov 6(r5),r1 + dec 2(r1) + bge 1f + jsr pc,fl + dec 2(r1) +1: + movb 4(r5),*4(r1) + inc 4(r1) + dec 2(r1) + bge 1f + jsr pc,fl + dec 2(r1) +1: + movb 5(r5),*4(r1) + inc 4(r1) + mov 4(r5),r0 + br goodret + +_putc: + mov r5,-(sp) + mov sp,r5 + mov 6(r5),r1 + dec 2(r1) + bge 1f + jsr pc,fl + dec 2(r1) +1: + mov 4(r5),r0 + movb r0,*4(r1) + inc 4(r1) + br goodret + +_fflush: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),r1 + jsr pc,fl + br goodret + +fl: + mov r1,r0 + add $6,r0 + mov r0,-(sp) + mov r0,0f + mov 4(r1),0f+2 + beq 1f + sub r0,0f+2 + mov (r1),r0 + sys 0; 9f +.data +9: sys write; 0:..; .. +.text +1: + mov (sp)+,4(r1) + mov $512.,2(r1) + rts pc + +badret: + jmp cerror + +goodret: + clr _errno + mov (sp)+,r5 + rts pc diff --git a/source/s5/putchr.s b/source/s5/putchr.s new file mode 100644 index 0000000..94a8d56 --- /dev/null +++ b/source/s5/putchr.s @@ -0,0 +1,55 @@ +/ C library -- putchar + + .globl _putchar,_flush + .globl _fout + +_putchar: + mov r5,-(sp) + mov sp,r5 + mov _fout+4,r0 + bne 1f + jsr pc,fl + mov _fout+4,r0 +1: + movb 4(r5),(r0)+ + beq 1f + inc _fout+4 + dec _fout+2 + bgt 1f + jsr pc,fl +1: + mov 4(r5),r0 + mov (sp)+,r5 + rts pc + +_flush: + mov r5,-(sp) + mov sp,r5 + jsr pc,fl + mov (sp)+,r5 + rts pc + +fl: + mov _fout+4,r0 + beq 1f + sub $_fout+6,r0 + mov r0,0f + mov _fout,r0 + bne 2f + inc r0 +2: + sys 0; 9f +.data +9: sys write; _fout+6; 0:.. +.text +1: + mov $_fout+6,_fout+4 + mov $512.,_fout+2 + cmp _fout,$2 + bhi 1f + mov $1,_fout+2 +1: + rts pc + +.bss +_fout: .=.+518. diff --git a/source/s5/qsort.c b/source/s5/qsort.c new file mode 100644 index 0000000..4319b0c --- /dev/null +++ b/source/s5/qsort.c @@ -0,0 +1,120 @@ + +int (*qscmp)(); +int qses; + +qsort(a, n, es, fc) +char *a; +int n, es; +int (*fc)(); +{ + qscmp = fc; + qses = es; + qs1(a, a+n*es); +} + +qs1(a, l) +char *a, *l; +{ + register char *i, *j, *es; + char *lp, *hp; + int n, c; + + + es = qses; + +start: + if((n=l-a) <= es) + return; + + + n = ((n/(2*es))*es) & 077777; + hp = lp = a+n; + i = a; + j = l-es; + + + for(;;) { + if(i < lp) { + if((c = (*qscmp)(i, lp)) == 0) { + qsexc(i, lp =- es); + continue; + } + if(c < 0) { + i =+ es; + continue; + } + } + +loop: + if(j > hp) { + if((c = (*qscmp)(hp, j)) == 0) { + qsexc(hp =+ es, j); + goto loop; + } + if(c > 0) { + if(i == lp) { + qstexc(i, hp =+ es, j); + i = lp =+ es; + goto loop; + } + qsexc(i, j); + j =- es; + i =+ es; + continue; + } + j =- es; + goto loop; + } + + + if(i == lp) { + if(lp-a >= l-hp) { + qs1(hp+es, l); + l = lp; + } else { + qs1(a, lp); + a = hp+es; + } + goto start; + } + + + qstexc(j, lp =- es, i); + j = hp =- es; + } +} + +qsexc(i, j) +char *i, *j; +{ + register char *ri, *rj, c; + int n; + + n = qses; + ri = i; + rj = j; + do { + c = *ri; + *ri++ = *rj; + *rj++ = c; + } while(--n); +} + +qstexc(i, j, k) +char *i, *j, *k; +{ + register char *ri, *rj, *rk; + char c; + int n; + + n = qses; + ri = i; + rj = j; + rk = k; + do { + c = *ri; + *ri++ = *rk; + *rk++ = *rj; + *rj++ = c; + } while(--n); +} diff --git a/source/s5/read.s b/source/s5/read.s new file mode 100644 index 0000000..9efdd4a --- /dev/null +++ b/source/s5/read.s @@ -0,0 +1,23 @@ +/ C library -- read + +/ nread = read(file, buffer, count); +/ +/ nread ==0 means eof; nread == -1 means error + +.globl _read, cerror + +_read: + mov r5,-(sp) + mov sp,r5 + mov 4(r5),r0 + mov 6(r5),0f + mov 8(r5),0f+2 + sys 0; 9f + bec 1f + jmp cerror +1: + mov (sp)+,r5 + rts pc +.data +9: + sys read; 0:..; .. diff --git a/source/s5/reset.s b/source/s5/reset.s new file mode 100644 index 0000000..e72214c --- /dev/null +++ b/source/s5/reset.s @@ -0,0 +1,31 @@ +/ C library -- reset, setexit + +/ reset() +/ will generate a "return" from +/ the last call to +/ setexit() +/ by restoring sp, r5 +/ and doing a return. +/ +/ useful for going back to the main loop +/ after a horrible error in a lowlevel +/ routine. + +.globl _setexit +.globl _reset +.globl csv, cret + +_setexit: + jsr r5,csv + mov r5,sr5 + mov 2(r5),spc + jmp cret + +_reset: + mov sr5,r5 + mov spc,2(r5) + jmp cret + +.bss +sr5: .=.+2 +spc: .=.+2 diff --git a/source/s5/rin.c b/source/s5/rin.c new file mode 100644 index 0000000..9f8b240 --- /dev/null +++ b/source/s5/rin.c @@ -0,0 +1,33 @@ +rin() +{ + double d; + register n, c, f; + + d = 0.; + f = 0; + n = 0; +loop: + c = getchar(); + if(c == '\0') + exit(); + if(c == '-') { + f++; + goto loop; + } + if(c == '.') { + n++; + goto loop; + } + if(c>='0' && c<='9') { + if(n) + n++; + d = d*10.+c-'0'; + goto loop; + } + if(f) + d = -d; + for(f=1; fc1; } + | LEFT MQ ={ $$ = '{'; } + ; + +right : RIGHT text ={ $$ = $2->c1; } + | RIGHT MQ1 ={ $$ = '}'; } + | ={ $$ = 0; } + ; + +list : eqn ={ lp[ct++] = $1; } + | list ABOVE eqn ={ lp[ct++] = $3; } + ; + +lpile : LPILE ={ $$=ct; } ; +cpile : CPILE ={ $$=ct; } ; +pile : PILE ={ $$=ct; } ; +rpile : RPILE ={ $$=ct; } ; + +size : SIZE text + ; + +font : ROMAN + | ITALIC + | BOLD + | FONT text + ; + +sub : SUB ={ shift(1); } ; + +super : SUPER ={ shift(-1); } ; + +pbox : MQ eqn MQ1 ={ $$ = $2; } + | QTEXT ={ text('q',$1); } + | CONTIG ={ text('c',$1); } + | SPACE ={ text('~', $1); } + | THIN ={ text('^', $1); } + | TAB ={ text('\t', $1); } + | SUM ={ text('c', "SIGMA"); } + | PROD ={ text('c', "PI"); } + | INT ={ text('c', "^"); } + | UNION ={ text('c' ,"U"); } + | INTER ={ text('c', "A"); } + ; + +text : CONTIG + | QTEXT + | SPACE ={ $$ = & "\\|\\|"; } + | THIN ={ $$ = & "\\|"; } + ; + +%% diff --git a/source/s7/ne.h b/source/s7/ne.h new file mode 100644 index 0000000..df52505 --- /dev/null +++ b/source/s7/ne.h @@ -0,0 +1,35 @@ +# +int dbg; +int ct; +int lp[40]; +char used[100]; /* available registers */ +int ps; /* dflt init pt size */ +int ft; /* dflt font */ +int first; +extern int fout, fin; +int ifile; +int linect; /* line number in file */ +int eqline; /* line where eqn started */ +int svargc; +char **svargv; +int eht[100]; +int ebase[100]; +int ewid[100]; +struct { char c1; char c2; }; +int yyval; +int *yypv; +int yylval; +int tht[30]; +int tbase[30]; +int ptr; +char *nptr[50]; +char *sptr[50]; +int eqnreg, eqnht, eqnbase; +int lefteq, righteq; +int lastchar; /* last character read by lex */ +#define FATAL 1 +int ESC; +int HREV; +int HFWD; +int SI; +int SO; diff --git a/source/s7/ne1.c b/source/s7/ne1.c new file mode 100644 index 0000000..40875a8 --- /dev/null +++ b/source/s7/ne1.c @@ -0,0 +1,218 @@ +# include "ne.h" + +boverb(p1,p2) int p1,p2; { + int h,b,w,treg; + yyval = oalloc(); + eht[yyval] = eht[p1] + eht[p2] ; + ebase[yyval] = eht[p2] - 1; + ewid[yyval] = w = max(ewid[p1],ewid[p2]); + if(dbg)printf(".\tb:bob: S%d <- S%d over S%d; b=%d,h=%d,w=%d\n", + yyval, p1, p2, ebase[yyval], eht[yyval], ewid[yyval]); + printf(".ds %d ", yyval); + down(eht[p2]-ebase[p2]-1); + fwd((ewid[yyval]-ewid[p2])/2); + printf("\\*(%d", p2); + back((ewid[yyval]+ewid[p2])/2); + up(eht[p2]-ebase[p2]+ebase[p1]); + fwd((ewid[yyval]-ewid[p1])/2); + printf("\\*(%d", p1); + back((ewid[yyval]+ewid[p1])/2); + down(ebase[p1]); + line(ewid[yyval]); + down(1); + putchar('\n'); + ofree(p1); + ofree(p2); +} + +bshiftb(p1,dir,p2) int p1,dir,p2; { + int shval, d1, h1, b1,h2,b2; + yyval = oalloc(); + ewid[yyval] = ewid[p1] + ewid[p2]; + h1 = eht[p1]; b1 = ebase[p1]; + h2 = eht[p2]; b2 = ebase[p2]; + printf(".ds %d \"\\*(%d", yyval, p1); + if( dir > 0 ){ /* subscript */ + shval = h2-b2-1; + if( shval < b1 ) + shval = b1; + down(shval); + printf("\\*(%d", p2); + up(shval); + ebase[yyval] = max(b1, h2-1); + eht[yyval] = h1 + max(0,h2-b1-1); + } else { /* superscript */ + ebase[yyval] = b1; + shval = b2+1; + if( shval+h2 < h1-b1 ) + shval = h1-b1-h2; + up(shval); + printf("\\*(%d", p2); + down(shval); + eht[yyval] = max(h1, b1+1+h2); + } + putchar('\n'); + if(dbg)printf(".\tb:b shift b: S%d <- S%d vert %d S%d vert %d; b=%d,h=%d,w=%d\n", + yyval,p1,shval,p2,-shval,ebase[yyval],eht[yyval],ewid[yyval]); + ofree(p1); + ofree(p2); +} + +eqnbox(p1,p2) int p1,p2; { + int b,h; + if( p1==0 ){ + yyval = p2; return; + } + yyval = oalloc(); + b = max(ebase[p1], ebase[p2]); + eht[yyval] = h = b + max(eht[p1]-ebase[p1], + eht[p2]-ebase[p2]); + ebase[yyval] = b; + ewid[yyval] = ewid[p1] + ewid[p2]; + if(dbg)printf(".\te:eb: S%d <- S%d S%d; b=%d,h=%d,w=%d\n", + yyval,p1,p2,b,h,ewid[yyval]); + printf(".ds %d \\*(%d\\*(%d\n", yyval, p1, p2); + ofree(p1); + ofree(p2); +} + +size(p1,p2) int p1,p2; { + yyval = p2; +} + +numb(p1) char *p1; { + int i, n, c; + for(i=n=0; (c=p1[i++])!='\0'; ) + if( c>='0' && c<='9' ) + n = n*10 + c-'0'; + if(dbg)printf(".\tnumb: %s %d\n",p1,n); + return( n ); +} + +font(p1,p2) int p1,p2; { + yyval = p2; +} + +shift(p1) int p1; { + yyval = p1; + if(dbg)printf(".\tshift: %d\n",yyval); +} + +sqrt(p2) int p2; { + int nps, h, i; + yyval = oalloc(); + h = eht[p2]; + eht[yyval] = h+1; + nps = h-1; + ebase[yyval] = ebase[p2]; + ewid[yyval] = ewid[p2] + 2; + if(dbg)printf(".\tsqrt: S%d <- S%d;b=%d,h=%d,w=%d\n", + yyval,p2,ebase[yyval],eht[yyval],ewid[yyval]); + printf(".ds %d \\e|", yyval); + for( i=2; i<=nps; i++ ){ + back(1); + up(1); + putchar('|'); + } + up(2); + line(ewid[p2]); + back(ewid[p2]); + down(h); + printf("\\*(%d\n", p2); + ofree(p2); +} + +lpile(type,p1,p2) int type,p1,p2; { + int w,bi,hi,i,gap,h,b,j, nlist, nlist2, mid; + yyval = oalloc(); + gap = type == '-' ? 0 : 1; + nlist = p2 - p1; + nlist2 = (nlist+1)/2; + mid = p1 + nlist2 -1; + h = b = w = 0; + for( i=p1; imid; i-- ) + b =+ eht[lp[i]] + gap; + ebase[yyval] = (nlist%2) ? b + ebase[lp[mid]] : b - gap -1; + if(dbg){ + printf(".\tS%d <- %c pile of:", yyval, type); + for( i=p1; i=p1; i--){ + hi = eht[lp[i]]; + bi = ebase[lp[i]]; + switch(type){ + + case 'L': + up(bi); + printf("\\*(%d", lp[i]); + back(ewid[lp[i]]); + up(hi-bi+gap); + printf("\\\n"); + continue; + case 'R': + up(bi); + back(ewid[lp[i]]); + printf("\\*(%d", lp[i]); + up(hi-bi+gap); + printf("\\\n"); + continue; + case 'C': + case '-': + up(bi); + fwd((ewid[yyval]-ewid[lp[i]])/2); + printf("\\*(%d", lp[i]); + back((ewid[yyval]+ewid[lp[i]])/2); + up(hi-bi+gap); + printf("\\\n"); + continue; + } + } + down(eht[yyval]-ebase[yyval]+gap); + if( type!='R' ) + fwd(ewid[yyval]); + putchar('\n'); + for( i=p1; i h2 ) + subsh = b1-b2; + supsh = b3 + 1; + if( supsh+h3 < h1-b1 ) + supsh = h1-b1-h3; + eht[yyval] = h1 + max(0,h3-1) + max(0,h2-b1-d1); + ebase[yyval] = b1+max(0,h2-b1-d1); + ewid[yyval] = ewid[p1] + max(ewid[p2], ewid[p3]); + printf(".ds %d \\*(%d", yyval, p1); + down(subsh); + printf("\\*(%d", p2); + back(ewid[p2]); + up(subsh+supsh); + printf("\\*(%d", p3); + down(supsh); + if(ewid[p3] < ewid[p2] ) + fwd(ewid[p2]-ewid[p3]); + putchar('\n'); + if(dbg)printf(".\tshift2 s%d <- %d %d %d",yyval,p1,p2,p3); + if(dbg)printf(" h=%d,b=%d,w=%d\n", eht[yyval],ebase[yyval],ewid[yyval]); + ofree(p1); ofree(p2); ofree(p3); +} diff --git a/source/s7/ne2.c b/source/s7/ne2.c new file mode 100644 index 0000000..db2f419 --- /dev/null +++ b/source/s7/ne2.c @@ -0,0 +1,154 @@ +# include "ne.h" + +fromto(p1,p2,p3) int p1,p2,p3; { + int w,h,b,h1,b1; + yyval = oalloc(); + h1 = eht[yyval] = eht[p1]; + b1 = ebase[p1]; + b = 0; + w = ewid[p1]; + if( p2>0 ){ + w = max(w, ewid[p2]); + eht[yyval] =+ eht[p2]; + b = eht[p2]; + } + if( p3>0 ){ + w = max(w, ewid[p3]); + eht[yyval] =+ eht[p3]; + } + ewid[yyval] = w; + printf(".ds %d ", yyval); /* bottom of middle box */ + if( p2>0 ){ + down(eht[p2]-ebase[p2]+b1); + fwd((w-ewid[p2])/2); + printf("\\*(%d", p2); + back((w+ewid[p2])/2); + up(eht[p2]-ebase[p2]+b1); + } + fwd((w-ewid[p1])/2); + printf("\\*(%d", p1); + fwd((1+w-ewid[p1])/2); + if( p3>0 ){ + up(h1-b1+ebase[p3]); + back((w+ewid[p3])/2); + printf("\\*(%d", p3); + fwd((w-ewid[p3])/2); + down(h1-b1+ebase[p3]); + } + putchar('\n'); + ebase[yyval] = b + b1; + if(dbg)printf(".\tfrom to: S%d <- %d f %d t %d; h=%d b=%d,w=%d\n", + yyval,p1,p2,p3,eht[yyval], ebase[yyval], ewid[yyval]); + ofree(p1); + if( p2>0 ) ofree(p2); + if( p3>0 ) ofree(p3); +} + +paren(leftc,p1,rightc) int p1, leftc, rightc; { + int n,h1,b1; + yyval = oalloc(); + h1 = eht[p1]; ebase[yyval] = b1 = ebase[p1]; + n = max(b1+1, h1-b1-1); + eht[yyval] = 2*n; + if( eht[yyval] > h1 ) + ++ebase[yyval]; + printf(".ds %d ", yyval); + brack(n,'|'); + printf("\\*(%d", p1); + if( rightc ) + brack(n,'|'); + putchar('\n'); + ewid[yyval] = ewid[p1] + 1 + (rightc ? 1 : 0); + if(dbg)printf(".\tcurly: h=%d b=%d n=%d w=%d l=%c,r=%c\n", + eht[yyval],ebase[yyval],n,ewid[yyval],leftc,rightc); + ofree(p1); +} + +brack(n,c) int n,c; { + int j; + down(n-1); + for( j=0; j < n; j++ ){ + putchar(c); + back(1); + up(2); + } + down(n+1); + fwd(1); +} + +diacrit(p1,type) int p1,type; { + int c,t; + c = oalloc(); + switch(type){ + case 'H': + printf(".ds %d ^\n",c); + ewid[c] = 1; + break; + case 'T': + printf(".ds %d ~\n",c); + ewid[c] = 1; + break; + case 'D': + printf(".ds %d ", c); + up(2); + putchar('.'); + down(2); + putchar('\n'); + ewid[c] = 1; + break; + case 'U': + printf(".ds %d ", c); + up(2); + printf(".."); + down(2); + putchar('\n'); + ewid[c] = 2; + break; + case 'B': + printf(".ds %d ", c); + up(eht[p1]); + line(ewid[p1]); + down(eht[p1]); + putchar('\n'); + ewid[c] = ewid[p1]; + break; + case 'N': + printf(".ds %d ", c); + down(ebase[p1]); + line(ewid[p1]); + up(ebase[p1]); + putchar('\n'); + ewid[c] = ewid[p1]; + break; + } + yyval = oalloc(); + printf(".ds %d \\*(%d", yyval, p1); + back((ewid[p1]+ewid[c])/2); + printf("\\*(%d", c); + fwd(abs(ewid[p1]-ewid[c])/2); + putchar('\n'); + ewid[yyval] = max(ewid[p1], ewid[c]); + ebase[yyval] = ebase[p1]; + eht[yyval] = eht[p1]; + if( type != 'N' ) + eht[yyval]++; + if(dbg)printf(".\t%c diacrit: S%d <- %d; h=%d,b=%d,w=%d\n", + type, yyval, p1, eht[yyval], ebase[yyval], ewid[yyval]); + ofree(p1); ofree(c); +} + +move(dir, amt, p) int dir, amt; char *p; { + yyval = p; + printf(".ds %d ", yyval); + if( dir==0 ) fwd(amt); + else if( dir==1 ) up(amt); + else if( dir==2 ) back(amt); + else if( dir==3 ) down(amt); + printf("\\*(%d\n", p); + if( dir==1 ) + ebase[yyval] =- amt; + else if( dir==3 ) + ebase[yyval] =+ amt; + if(dbg)printf(".\tmove %d dir %d amt %d; h=%d b=%d\n", + p,dir,amt,eht[yyval],ebase[yyval]); +} diff --git a/source/s7/ne3.c b/source/s7/ne3.c new file mode 100644 index 0000000..d3de95b --- /dev/null +++ b/source/s7/ne3.c @@ -0,0 +1,103 @@ +# include "ne.h" + +char *res[] { + ">=", "<=", "!=", + "+-", "==", "cdot", "CDOT", + "times", "TIMES", + "SIGMA", "pi", "PI", + "alpha", "beta", "gamma", "GAMMA", "delta", "epsilon", "omega", + "DELTA", "LAMBDA", "PHI", "OMEGA", + "lambda", "mu", "nu", "theta", "rho", "sigma", "tau", "phi", + "INF", "INFINITY", + "inf", "infinity", + "partial", "PARTIAL", + "zeta", "eta", "iota", "kappa", "xi", "omicron", "upsilon", + "chi", "psi", "THETA", "XI", "UPSILON", "PSI", + "del", "DEL", + "nothing", "NOTHING", + "approx", "APPROX", + 0}; +char *restran[] { + ">\b_", "<\b_", "/\b=", + "+\b_", "=\b_", "8.9", "8.9", + "x", "x", + "R", "J", "P", + "A", "B", "\\e", "G", "D", "S", "C", + "W", "E", "F", "Z", + "L", "M", "@", "T", "K", "Y", "I", "U", + "o", "o", "o", "o", + "]", "]", + "Q", "N", "i", "k", "X", "o", "u", + "X", "V", "O", "X", "U", "H", + "[", "[", + "", "", + "~\b=", "~\b=", + 0}; + +int csp; +int psp; +#define CSSIZE 400 +char cs[420]; + +text(t,p1) int t; char *p1; { + int i,j,c; + int w; + yyval = oalloc(); + ebase[yyval] = 0; + eht[yyval] = 2; /* ht in 1/2 spaces */ + if( t=='q' ) + j = p1; + else if ( t == '~' ) + j = &"~"; + else if ( t == '^' ) + j = &""; + else if ( t == '\t' ) + j = &"\\t"; + else if( (i=lookup(p1,res))>=0 ) + j = restran[i]; + else { + for( csp=psp=0; (c=p1[psp++])!='\0'; ){ + trans(c,p1); + if( csp>CSSIZE ) + error(FATAL,"converted token %.20s... too long",p1); + } + cs[csp] = '\0'; + j = cs; + } + ewid[yyval] = width(j); + if(dbg)printf(".\t%ctext: S%d <- %s; b=%d,h=%d,w=%d\n", + t, yyval, j, ebase[yyval], eht[yyval], ewid[yyval]); + printf(".ds %d \"%s\n",yyval,j); +} + +width(s) char *s; { + int c,w; + w = 0; + while( (c = *s++) != '\0' ){ + if( c == '\b' || c == 033 ) + w--; + else if ( c == '\\' && *s == '\\' ); + else if ( c == '\\' && *s == 'e' ); + else if ( c >= 040 ) + w++; + } + return(w); +} + +trans(c,p1) int c; char *p1; { + switch( c){ + case '>': case '<': case '=': + if( p1[psp]=='=' ){ /* look ahead for == <= >= */ + cs[csp++] = c; cs[csp++] = '\b'; cs[csp++] = '_'; + psp++; + } else + cs[csp++] = c; + break; + case '\\': /* troff - pass 2 or 3 more chars */ + cs[csp++] = c; cs[csp++] = c = p1[psp++]; cs[csp++] = p1[psp++]; + if( c=='(' ) cs[csp++] = p1[psp++]; + break; + default: + cs[csp++] = c; break; + } +} diff --git a/source/s7/ne4.c b/source/s7/ne4.c new file mode 100644 index 0000000..0c37ab8 --- /dev/null +++ b/source/s7/ne4.c @@ -0,0 +1,215 @@ +# include "ne.h" +# define SIGPIPE 13 /* nroff has stopped reading */ + +int ESC 033; +int HREV '8'; +int HFWD '9'; +int SI 017; +int SO 016; +int ESCOUT 033; +int HFWDOUT '9'; +int HREVOUT '8'; +int BKSPOUT '\b'; +int FWDOUT '~'; + +char in[400]; /* input buffer */ +int exit(); + +main(argc,argv) int argc; char *argv[];{ + int i, type; + flush(); + first = 0; + lefteq = righteq = '\0'; + signal(SIGPIPE, &exit); + setfile(argc,argv); + while( (type=getline(in)) != '\0' ){ + eqline = linect; + if( in[0]=='.' && in[1]=='E' && in[2]=='Q' ){ + for( i=11; i<100; used[i++]=0 ); + printf(".tr ~\n"); + printf("%s",in); + init(); + yyparse(); + if( eqnreg>0 ) + printf(".ne %d\n.rs\n'sp %d\n\\*(%d\n'sp %d\n", + (eqnht+1)/2, (eqnht-eqnbase-2)/2,eqnreg,eqnbase/2); + printf(".EN"); + if( lastchar == '\0' ){ + putchar('\n'); + break; + } + if( putchar(lastchar) != '\n' ) + while( putchar(getc()) != '\n' ); + flush(); + } else if( type != lefteq ) + printf("%s",in); + else + inline(); + } + putchar('\0'); + flush(); + exit(); +} + +getline(s) char *s; { + char c; + while((*s++=c=getc())!='\n' && c!='\0' && c!=lefteq ); + if( c==lefteq ) + s--; + *s++ = '\0'; + return(c); +} + +inline() { + int i,j,ds[20],t; + i = -1; + do{ + if( i>=17 ){ + while((j=getline(in))!='\n' && j!='\0'); + error(!FATAL,"missing right delim (?) at %.20s",in); + break; + } + ds[++i] = oalloc(); + printf(".ds %d \"%s\n", ds[i], in); + init(); + yyparse(); + if( eqnreg > 0 ) + ds[++i] = eqnreg; + } while( (t=getline(in)) == lefteq ); + ds[++i] = oalloc(); + printf(".ds %d \"%s", ds[i], in); + for( j=0; j<=i; j++){ + printf("\\*(%d", ds[j]); + ofree(ds[j]); + } + putchar('\n'); + flush(); +} + +putout(p1) int p1; { + if(dbg)printf(".\tanswer <- S%d\n",p1); + eqnht = eht[p1]; + eqnbase = ebase[p1]; + eqnreg = p1; +} + +abs(v) int v; { + return( v>0 ? v : -v ); +} + +max(i,j) int i,j; { + return( i>j ? i : j ); +} + +oalloc(){ + int i; + for( i=11; i<100; i++) + if( used[i]++ == 0 ) return(i); + error( FATAL, "no strings left", i); +} + +ofree(n) int n; { + used[n] = 0; +} + +setfile(argc, argv) int argc; char *argv[]; { + svargc = --argc; + svargv = argv; + while( svargc > 0 && svargv[1][0] == '-'){ + switch( svargv[1][1] ){ + + case 'd': lefteq=svargv[1][2]; righteq=svargv[1][3]; break; + case 's': break; + case 'f': break; + default: + dbg = 1; + ESCOUT = 'E'; + HFWDOUT = 'F'; + HREVOUT = 'R'; + BKSPOUT = 'B'; + FWDOUT = 'S'; + } + svargc--; + svargv++; + } + if( svargc == 0 ) + fin = dup(0); + else if( (fin = open(svargv[1], 0)) < 0) + error( FATAL,"can't open file %s", argv[1]); + ptr = 0; + fout = dup(1); + ifile = 1; + linect = 1; +} + +yyerror(){;} + +int gsize 10; +int gfont 'I'; + +init(){ + ct = 0; + first++; +} + +error(fatal, s1, s2) int fatal; char *s1, *s2; { + int sfout; + printf("NEQN ERROR HERE"); + flush(fout); + sfout = fout; + fout = 2; + if( fatal>0 ) + printf("fatal error: "); + printf(s1,s2); + printf(" file %s, between lines %d and %d\n", + svargv[ifile], eqline, linect); + flush(2); + fout = sfout; + if( fatal > 0 ) + exit(1); +} + +down(n) int n; { + int c; + if( n<= 0 ) + c = HREVOUT; + else + c = HFWDOUT; + n = abs(n); + while( n-- > 0 ){ + putchar(ESCOUT); putchar(c); + } +} + +up(n) int n; { + int c; + if( n<= 0 ) + c = HFWDOUT; + else + c = HREVOUT; + n = abs(n); + while( n-- > 0 ){ + putchar(ESCOUT); putchar(HREVOUT); + } +} + +fwd(n) int n; { + int c,i; + c = n<0 ? BKSPOUT : FWDOUT; + n = abs(n); + while( n-- > 0 ) + putchar(c); +} + +back(n) int n; { + int c,i; + c = n>0 ? BKSPOUT : FWDOUT; + n = abs(n); + while( n-- > 0 ) + putchar(c); +} + +line(n) int n; { + while( n-- > 0 ) + putchar('_'); +} diff --git a/source/s7/ne5.c b/source/s7/ne5.c new file mode 100644 index 0000000..cb55599 --- /dev/null +++ b/source/s7/ne5.c @@ -0,0 +1,34 @@ +#include "ne.h" + +int markpos; + +mark(n) int n; { + if( n ) + markpos = ewid[n]; + else { + yyval = oalloc(); + printf(".ds %d \"\n", yyval); + ebase[yyval] = ewid[yyval] = markpos = 0; + eht[yyval] = 2; + } + if(dbg)printf(".\tmark %d as %d\n", n, markpos); +} + +lineup(n) int n; { + if( n ) { + printf(".ds %d \"", n); + fwd(markpos-ewid[n]); + printf("\\*(%d\n", n); + ewid[n] = markpos; + } + else { + yyval = oalloc(); + printf(".ds %d \"", yyval); + fwd(markpos); + printf("\n"); + ebase[yyval] = 0; + eht[yyval] = 2; + ewid[yyval] = markpos; + } + if(dbg)printf(".\tlineup %d at %d\n", n, markpos); +} diff --git a/source/s7/ne6.c b/source/s7/ne6.c new file mode 100644 index 0000000..e548f84 --- /dev/null +++ b/source/s7/ne6.c @@ -0,0 +1,63 @@ +#include "ne.h" + +column(type, p1, p2) int type, p1, p2; { + int i, n; + lp[p1] = ct - p1 - 1; + if( dbg ){ + printf(".\t%c column of", type); + for( i=p1+1; i= 0){ + lastchar = (peek<0) ? *swt[sw]++ : peek; + peek = -1; + if(lastchar != '\0')return(lastchar); + peek = speek[sw--]; + return(' '); + } + lastchar = (peek<0) ? getchar() : peek; + if( lastchar=='\n' ) + linect++; + peek = -1; + if( lastchar!= '\0' ) + return(lastchar); + if( ++ifile > svargc ){ + peek = '\0'; + return('\0'); + } + close(fin); + linect = 1; + if( (fin=open(svargv[ifile],0)) >= 0 ) + goto loop; + error(FATAL,"can't open file %s\n", svargv[ifile]); +} + +yylex(){ + int c, type; + beg: + while( (c=getc())==' ' || c=='\n'); + yylval=c; + switch(c){ + + case '\0': + return('\0'); + case '~': + return(SPACE); + case '^': + return(THIN); + case '\t': + return(TAB); + case '{': + return(MQ); + case '}': + return(MQ1); + case '"': + for(sp=0; (c=getc())!='"'; ){ + if(c !='\\')token[sp++]=c; + else { if((c=getc())!= '"')token[sp++]='\\'; + token[sp++] = c; } + if( sp>=SSIZE ) + error(FATAL,"quoted string %.20s... too long", token); + } + token[sp]='\0'; + yylval= &token[0]; + return(QTEXT); + } + if( c==righteq ) + return('\0'); + + getstr(token, c); + if((type = lookup(token,nptr)) >= 0){ + if(sw >= 9) + error(FATAL,"definitions nested > 9", sw); + swt[++sw] = sptr[type]; + speek[sw] = peek; + peek = -1; + goto beg; + } + type = lookup(token,cntrl); + if( type < 0 ) + return(CONTIG); + if( icntrl[type]==DEFINE ) { + define(); + goto beg; + } + else if( icntrl[type]==DELIM ) { + delim(); + goto beg; + } + else if( icntrl[type]==GSIZE ){ + globsize(); + goto beg; + } + else if( icntrl[type]==GFONT ) { + globfont(); + goto beg; + } + else + return( icntrl[type] ); +} + +getstr(s,c) char *s, c; { + for (sp=0; c!=' ' && c!='\t' && c!='\n' && c!='{' && c!='}' + && c!='"' && c!='~' && c!='^' && c!=righteq; ) { + if(c == '\\') if((c = getc()) != '"')s[sp++] = '\\'; + s[sp++] = c; + if( sp>=SSIZE ) + error(FATAL,"token %.20s... too long",s); + c = getc(); + } + if( c=='{' || c=='}' || c=='"' || c=='~' || c=='^' || c=='\t' || c==righteq ) + peek = c; + s[sp]='\0'; + yylval = s; +} + +lookup(str,tbl) char *str; char *tbl[]; { + register i,j, r; + for(i=0; tbl[i]!=0; i++){ /* table of tbl wds */ + for( j=0; (r=tbl[i][j])==str[j] && r!='\0'; j++); + if( r == str[j] ) + return(i); + } + return( -1 ); +} + +cstr(s,quote) char *s; int quote; { + int del,c,i; + while((del=getc()) == ' ' || del == '\t' || del == '\n'); + if(quote) + for(i=0; (c=getc()) != del;) + s[i++] = c; + else { + s[0] = del; + for(i=1; (c=getc())!=' ' && c!= '\t' && c!='\n';) + s[i++]=c; + } + s[i] = '\0'; + return(s); +} + +define() { + char *alloc(); + int i, c; + while( (c=getc())==' ' || c=='\n' ); + getstr(token,c); + if((i = lookup(token,nptr)) >= 0){ + yyval = i; + free(sptr[yyval]); + } else { + yyval = ptr++; + for(i=0; token[i] != '\0'; i++); + nptr[yyval] = alloc(i+1); + for(i=0; nptr[yyval][i]=token[i]; i++); + } + if(dbg)printf(".\tdefine %s\n",nptr[yyval]); + cstr(token,1); + for(i=0; token[i] != '\0'; i++); + sptr[yyval] = alloc(i+1); + for(i=0; sptr[yyval][i] = token[i]; i++); + if(dbg)printf(".\tname %s defined as %s\n",nptr[yyval],sptr[yyval]); +} + +delim() { + char *s; + yyval = eqnreg = 0; + cstr(token,0); + lefteq = token[0]; + righteq = token[1]; + if( (lefteq == 'o' && righteq == 'f') || (lefteq == 'O' && righteq == 'F') ) + lefteq = righteq = '\0'; +} + +globsize() { + extern int gsize; + int c; + while( (c=getc())==' ' || c=='\n' ); + getstr(token,c); + gsize = numb(token); + yyval = eqnreg = 0; +} + +globfont() { + extern int gfont; + while( (gfont=getc())==' ' || gfont=='\n' ); + yyval = eqnreg = 0; +} diff --git a/source/s7/nroff1.s b/source/s7/nroff1.s new file mode 100644 index 0000000..923d2c5 --- /dev/null +++ b/source/s7/nroff1.s @@ -0,0 +1,1362 @@ +/ +/ + +/ nroff1 -- text formatter + +/ rts = 104000 + signal = 48. + nop = 000240 + + jmp ibuf +.data +ibuf: /init code in ibuf+obuf + cmp sp,$end + bhi 1f + jsr r5,string; emes1 + sys exit +1: + clr r0 + jsr pc,ttyn + cmpb r0,$'x + bne 0f + inc iflg + mov $1,r0 + jsr pc,ttyn +0: + movb r0,ttyx+8 + clr r0 + jsr pc,mesg + sys open; ttyx; 2 + bes 0f + mov r0,ttyid + mov r0,ttyod +0: + mov ttyid,r0 + sys gtty; ttys + sys signal; 1; place + sys signal; 2; place + bit $1,r0 + beq 0f + sys signal; 2; 1 /no deletes + sys signal; 3; 1 /no quits + sys signal; 1; 1 /allow hangup +0: + mov $'%,rlist + mov $"nl,rlist+2 + mov $"dn,rlist+4 + mov $"yr,rlist+6 + mov $"mo,rlist+8. + mov $"dy,rlist+10. + mov $"dw,rlist+12. + mov $"hp,rlist+14. + mov sp,r0 + jsr pc,makebf + sys open; suffil; 0 + bes 1f + mov r0,suff + sys seek; 20; 0 + bes 1f + mov suff,r0 + sys read; suftab; 2*26. +1: + clr r0 + mov (sp)+,argc + dec argc + ble 4f +1: + tst (sp)+ + mov (sp),r4 + cmpb (r4)+,$'+ + bne 2f + jsr r5,pnum; pfrom + br 3f +2: + cmpb -1(r4),$'- + bne 2f + tstb (r4) + beq 4f + cmpb (r4),$'m + bne 0f + mov $nextf1,r0 + tstb (r4)+ +8: + movb (r4)+,(r0)+ + bne 8b + inc nx + inc mflg + br 3f +0: + cmpb (r4),$'r + bne 0f + tstb (r4)+ + movb (r4)+,r0 + beq 3f + jsr pc,findr + mov r1,-(sp) + mov r4,ibufp + mov $-1,eibuf + jsr pc,atoi + mov (sp)+,r1 + mov r0,(r1) + clr ch + br 3f +0: + cmpb (r4),$'s + bne 0f + inc stop + br 3f +0: + cmpb (r4),$'o + bne 0f + inc old + br 3f +0: + cmpb (r4),$'i + bne 0f + inc stdi + br 3f +0: + cmpb (r4),$'q + bne 0f + inc quiet + br 3f +0: + cmpb (r4),$'h + bne 0f + clr slow + br 3f +0: + cmpb (r4),$'n + bne 0f + inc r4 + jsr r5,pnum; npn + br 3f +0: + jsr r5,pnum; pto +3: + dec argc + bgt 1b +2: +4: +/ tst index +/ beq 1f +/ sys creat; indf; 666 +/ mov r0,indid +1: +/ mov $nop,get1a + clr init + mov $ibuf,ibufp + mov $ibuf,eibuf + mov sp,argp + clr r0 +1: + movb r0,trtab(r0) + inc r0 + cmp r0,$128. + bne 1b + movb $040,trtab+014 + mov sp,ssp + mov $70.,vlist+6 + jsr pc,ctime + mov $-1,nl + mov $end,enda + clr ioff + jmp loop +makebf: + tst (r0)+ + mov (r0),r0 + cmpb (r0),$'a + bne 0f + mov $bfn1,r0 + mov r0,7f + mov r0,8f + mov r0,9f +/ mov r0,place1 +0: + sys stat; 8:bfn; stbuf + bec 2f + sys creat; 9:bfn; 600 + bec 1f +2: + incb bfn1+3 + cmpb bfn1+3,$'z + blos 0b + jmp place +1: + mov r0,ibf + mov $blockend,r0 + sub $block,r0 + cmp r0,$1024. + blos 1f + 4 +1: + mov r0,blocksize + clr -(sp) +2: + mov ibf,r0 + sys write; block; 1024. + inc (sp) + cmp (sp),nev + ble 2b + + mov (sp)+,r3 + mpy $1024.,r3 + mov r3,nextb + mov r3,first + mov ibf,r0 + sys close + sys open; 7:bfn; 2 + jes place + mov r0,ibf + mov r0,ibf1 + cmp $bfn1,7b + beq 1f + sys unlink; bfn +1: + rts pc + +ctime: + sys time + sub $18000.,r1 /5hrs for est + sbc r0 + ashc $-2,r0 + div $21600.,r0 + inc r0 + mov r0,dy +/ mov r1,fd + add $3,r0 + mov r0,r1 + sxt r0 + div $7,r0 + inc r1 + mov r1,dw +3: + mov yr,r1 + sxt r0 + div $4,r0 + mov $28.,ms+2 + tst r1 + bne 0f + mov $29.,ms+2 +0: + clr r0 +1: + cmp dy,ms(r0) + ble 2f + sub ms(r0),dy + tst (r0)+ + cmp r0,$24. + blt 1b + inc yr + mov yr,r1 + br 3b +2: + asr r0 + inc r0 + mov r0,mo + rts pc +ms: 31.;28.;31.;30.;31.;30.;31.;31.;30.;31.;30.;31. + +pnum: + clr -(sp) + clr r3 +1: + movb (r4)+,r0 + sub $'0,r0 + cmp r0,$9 + bhi 1f + inc (sp) + mpy $10.,r3 + add r0,r3 + br 1b +1: + mov r3,r0 + tst (sp)+ + beq 2f + mov r0,*(r5)+ +1: + rts r5 +2: + tst (r5)+ + br 1b + +emes1: +.even +obuf=ibuf+512. +.=ibuf+1024. +.text +loop: + clr nlflg + clr nflush + clr nb + mov ilistp,r1 + jsr pc,getch1 + mov r0,ch + cmp ilistp,r1 + beq 1f + tst ejf + beq 1f + cmp ilistp,ejl + bhi 1f + mov ilistp,ejl + inc nflush + jsr pc,newline + br loop +1: + jsr pc,getchar + tst pendt + bne 0f + tst lit + ble 1f + cmp frame,litlev + bhi 1f + dec lit + br 0f +1: + cmpb r0,cc + beq 3f + cmpb r0,c2 + beq 2f + cmpb r0,tch + beq 4f + cmpb r0,$002 + beq 6f +0: + movb r0,ch + jsr pc,text + br loop +4: + inc tflg + inc copyf +0: + jsr pc,getchar + mov r0,r5 + jsr pc,putchar + cmp r5,$'\n + bne 0b + clr tflg + clr copyf + br loop +2: + inc nb +3: + jsr pc,control +5: + jsr pc,flushi + br loop +6: + inc raw + jsr pc,get1 + movb r0,xpc + clr nlflg +0: + jsr pc,get1 + cmpb r0,xpc + beq 7f + jsr pc,pchar2 + br 0b +7: + clr raw + jbr loop + +mesg: + tst r0 + bne setsame + sys stat; ttyx; stbuf + mov stbuf+4,0f + mov 0f,1f + bic $22,0f + sys 0;7f +.data +7: sys chmod; ttyx; 0:.. +.text + rts pc +setsame: + sys 0;7f +.data +7: sys chmod; ttyx; 1:.. +.text + rts pc + +stringfl: + jsr pc,flush +string: + mov r0,-(sp) + mov r1,-(sp) + mov r2,-(sp) + mov (r5)+,r1 + mov r1,r2 + mov r1,9f +1: + tstb (r1)+ + bne 1b + dec r1 + sub r2,r1 + mov r1,1f + mov ttyod,r0 + cmp r0,ibf + beq 2f +0: + sys 0;7f +.data +7: sys write; 9:..; 1:.. +.text + bes 2f +1: + mov (sp)+,r2 + mov (sp)+,r1 + mov (sp)+,r0 + rts r5 +2: + sys creat; tmfile; 666 + bes 1b + mov r0,ttyod + br 0b + +flushi: + tst nflush + bne 1f + clr ch + tst nlflg + bne 1f + tst donef + beq 2f + cmp $ilist,ilistp + beq 1f +2: + jsr pc,getchar + br flushi +1: + rts pc + +gettchar: + tst ul + ble getchar + tst ulstate + beq 3f + tst bsc + bgt 1f + tst ulc + bgt 2f + clr ulstate + br 3f +1: + dec bsc + mov $010,r0 + rts pc +2: + dec ulc + mov $'_,r0 + rts pc +3: + jsr pc,getchar + cmp r0,$016 + beq 4f + cmp r0,$017 + beq 4f + cmp r0,$'0 + blt 1f + cmp r0,$'9 + ble 2f + cmp r0,$'A + blt 1f + cmp r0,$'Z + ble 2f + cmp r0,$'a + blt 1f + cmp r0,$'z + ble 2f +1: + tst ulc + ble 4f +3: + mov $1,ulstate + mov r0,ch + br gettchar +2: + inc bsc + inc ulc +4: + tst r0 + rts pc + +rtnch: + mov ch,r0 + clr ch + tst r0 + rts pc + +getchar: + mov r1,-(sp) +1: + jsr pc,getch1 + bmi 2f + cmpb r0,fc + bne 2f + tst copyf + bne 2f + jsr pc,setfield + br 1b +2: + mov (sp)+,r1 + tst r0 + rts pc +getch1: + tst ch + bne rtnch + mov r1,-(sp) +1: + jsr pc,getch0 + bmi 2f + tst copyf + bne 2f + cmpb r0,$030 /\w + bne 2f + jsr r5,setwd;getch0 + br 1b +2: + jsr pc,width + add r1,column + mov (sp)+,r1 + tst r0 + rts pc + +getch0: + tst ch + bne rtnch +1: + tst nlflg + beq 1f + mov $'\n,r0 + rts pc +1: + mov r1,-(sp) +1: + jsr pc,get1 + cmpb r0,eschar + bne 2f + jsr pc,get1 + jsr r5,switch; esctab + cmpb r0,$'\n + bne 3f +/ clr column + br 1b +2: + cmp r0,$033 /prefix + bne 3f + jsr pc,get1 + jsr r5,switch; pfxtab +3: + cmpb r0,$376 /comment + bne 2f +0: + jsr pc,get1 + bmi 0b + cmpb r0,$012 + bne 0b +2: + cmpb numc,r0 + bne 2f + clr r1 + jsr pc,setn + br 1b +2: + cmpb r0,$372 /mark hor place + bne 2f + tst copyf + bne 2f + mov r0,r1 + jsr pc,setn + jsr pc,findr + jeq 1b + mov column,(r1) + jbr 1b +2: + cmpb r0,$025 /text string + bne 2f + jsr pc,setstr + br 1b +2: + cmpb dolc,r0 + bne 2f + jsr pc,seta + br 1b +2: + cmpb r0,$026 /font indicator + bne 2f + jsr pc,get1 + br 1b +2: + cmpb r0,$027 /point size + bne 2f + jsr pc,eatps + br 1b +2: + cmpb r0,$021 /spead line + bne 2f + tst copyf + bne 2f + inc spread + br 1b +2: + cmpb r0,$006 /repeat + bne 2f + jsr pc,setrpt + br 1b +2: + cmp r0,$'\n + bne 3f + inc nlflg + clr column + tst ip + bne 3f + inc iline +3: + mov (sp)+,r1 + tst r0 + rts pc + +eatps: + jsr pc,get1 + cmpb r0,$'+ + beq 0f + cmpb r0,$'- + beq 0f + sub $'0,r0 + ble 1f + cmp r0,$3 + bgt 1f +0: + jsr pc,get1 +1: + rts pc + +.data +esctab: +.byte '*, 025 /text string +.byte 'n, 034 /number char +.byte '$, 020 /dollar char +eschar: +.byte '\\, 134 /backslash +.byte 'e, 013 /printable escape char +.byte 'f, 026 /font indicator +.byte 's, 027 /point size +.byte '&, 037 /filler +.byte 't, 011 /hor tab +.byte '!, 024 /transparent char +.byte 'p, 021 /spread line +.byte 'c, 005 /interrupted text +.byte 'k, 372 /mk hor +/ 014 hidden tab replacement character +.byte ' , 014 /\(space) +.byte 'x, 016 /SO (extra chars) +.byte 'y, 017 /SI (normal characters) +.byte 'l, 0177 /delete +.byte 'd, 032 /hlf (down) +.byte 'u, 035 /hlr (up) +.byte 'r, 036 /flr (reverse) +.byte 'a, 001 /leader char +.byte ':, 003 /lem char +.byte '?, 002 /raw trans +.byte '", 376 /comment +.byte 'w, 030 /width size char +.byte 0, 0 +.text + +pfxtab: + .byte '7, 036 /flr + .byte '8, 035 /hlr + .byte '9, 032 /hlf + .byte '1, 026 /set hor tabs + .byte '2, 027 /clr hor tabs + .byte 0,0 +pfxtab1: + +switch: + mov r1,-(sp) + mov (r5)+,r1 +1: + cmpb (r1)+,r0 + beq 1f + tstb (r1)+ + bne 1b + cmp r1,$pfxtab + ble 0f + cmp r1,$pfxtab1 + bgt 0f + mov $037,r0 +0: + mov (sp)+,r1 + rts r5 +1: + movb (r1)+,r0 + mov (sp)+,r1 + rts r5 + +get1: + tst nspace + ble 1f + dec nspace + mov rchar,r0 + rts pc +1: + mov r1,-(sp) +4: + tst cp + beq 2f + movb *cp,r0 + bne 1f + clr cp + br 4b +1: + inc cp + br 8f +2: + tst ap + beq 2f + movb *ap,r0 + bne 1f + clr ap + br 4b +1: + inc ap + br 8f +2: + cmp $-1,ip + bne 1f + jsr pc,rdtty + br 8f +1: + tst ip + beq 5f + jsr pc,rbf + br 8f +5: + tst donef + beq 0f + jmp done +0: + tst nx + bne 0f +3: + mov ibufp,r1 + cmp r1,eibuf + bne 3f + cmp r1,$-1 + beq 3f +0: + tst nfo + bne 2f +1: + jsr pc,nextfile + bne 3b +2: + clr nx + mov ifile,r0 + sys read; ibuf; 512. + bes 1b + tst r0 + beq 1b + mov $ibuf,r1 + add r1,r0 + mov r0,eibuf +3: + movb (r1)+,r0 + bic $!377,r0 + inc ioff + mov r1,ibufp + tst raw + bne 6f + cmpb r0,$040 + bhis 8f + mov r0,-(sp) + mov cbits,r0 + mov cbits+2,r1 + ashc (sp),r0 + bmi 0f + clr (sp) +0: + mov (sp)+,r0 +8: + tst raw1 + bne 6f + cmp r0,$004 + beq 4b + tst copyf + bne 6f + cmpb r0,$011 /tab + bne 0f + mov tabc,rchar + br 1f +0: + cmpb r0,$001 + bne 6f + mov dotc,rchar +1: + cmpb r0,fc + beq 6f + cmpb r0,padc + beq 6f + mov (sp)+,r1 + mov $tabtab,r0 + inc nspace +1: + tst (r0) + jeq get1 + cmp column,(r0)+ + bge 1b + mov -(r0),nspace + sub column,nspace + jbr get1 +6: +/get1a: br 7f + tst init + bne 7f + tst r0 + jeq 4b +7: + mov (sp)+,r1 + tst r0 + rts pc +cbits: 040743;20 /001,007-012,033 (soh,bel,bs,tab,nl,so,si,esc) +/cbits: 041743;20 /001,006-012,033 (soh,ack,bel,bs,tab,nl,so,si,esc) + +edone: + mov $stk,frame + clr ip +done: + clr app + clr ds + mov em,r0 + beq 0f + clr em + mov pc,donef + mov frame,-(sp) + jsr pc,cont1 + cmp (sp)+,frame + bne 1f +0: + tst nfo + beq 3f + clr op + clr mflg + tst woff + beq 0f + clr r0 + jsr pc,wbt +0: + clr pendnf + tst pendw + beq 0f + clr *pendw + clr pendw +0: + cmp $1,donef + beq done1 + mov $1,donef + clr ip + mov $ilist,ilistp + jsr pc,rbreak + inc nflush + mov $ilist,r0 + jsr pc,eject +1: + mov ssp,sp + jmp loop +done1: +/ tst pendb +/ bne 0b + tst nl + beq 1f + jsr pc,newline + br 1b +1: +3: +done2: + jsr pc,flush +place: + sys signal; 2; 1 + tst quiet + beq 1f + bis $10,ttym + mov ttyid,r0 + sys stty; ttys +1: + mov $1,r0 + jsr pc,mesg + mov outid,r0 + sys close + sys wait + sys exit + +nextfile: + mov ifile,r0 + beq 1f + sys close +1: + tst nx + beq 2f + mov $nextf,r0 + br 3f +2: + cmp ifp,$ifl + beq 1f + jsr pc,popf + bne nextfile + tst pc + rts pc +1: + dec argc + blt 4f + mov *argp,r0 + add $2,argp +3: + mov r0,5f + cmpb (r0)+,$'- + bne 0f + tstb (r0) + bne 0f + clr r0 + br 1f +0: + sys 0;7f +.data +7: sys open; 5:..; 0 +.text + bec 1f + sub mflg,nfo + jgt done + jsr r5,string; omes + mov 5b,8f + jmp 7f +.data +7: jsr r5,string; 8:.. + jmp 6f +.text +6: + jsr r5,string; 9f + jbr done +1: + clr iline + inc nfo + mov r0,ifile + clr ioff + rts pc +4: + sub mflg,nfo + beq 0f + tst stdi + jeq done +0: + clr iline + clr mflg + inc nfo + clr stdi + clr ifile + clr ioff + rts pc +omes: +9: <\n\0> +.even + +popf: + clr -(sp) + mov ifp,r1 + cmp r1,$ifl + beq 1f + sub $2,ifp + mov -(r1),ifile + mov [offl-ifl](r1),ioff + mov ioff,0f + bic $777,0f + mov ifile,r0 + beq 4f + sys 0;7f +.data +7: sys seek; 0:..; 0 +.text + bes 2f + mov ifile,r0 + sys read; ibuf; 512. + bes 2f + add $ibuf,r0 + mov r0,eibuf + sub ioff,0b + mov $ibuf,ibufp + mov ifile,r0 + jsr pc,ttyn + cmpb r0,$'x + bne 1f + sub 0b,ibufp + cmp ibufp,eibuf + blo 1f +2: + inc (sp) +1: + tst (sp)+ + rts pc +4: + jsr pc,restbuf + br 1b + +savebuf: + mov $ibuf,r0 + mov $xbuf,r1 + mov ibufp,xbufp + mov eibuf,xeibuf +1: + mov (r0)+,(r1)+ + cmp r0,eibuf + blo 1b + rts pc + +restbuf: + mov $xbuf,r0 + mov $ibuf,r1 + mov xbufp,ibufp + mov xeibuf,eibuf +1: + mov (r0)+,(r1)+ + cmp r1,eibuf + blo 1b + rts pc + +putchar: + bic $!377,r0 + beq 2f + tstb r0 + bmi pchar2 + cmpb r0,$013 /\e + bne 0f + tst op + bne 0f + movb eschar,r0 + br putchar +0: + movb trtab(r0),r0 + cmp r0,$' + bne 1f + inc nsp +2: + rts pc +1: + cmp r0,$'\n + bne 1f + clr nsp + clr ocol + br pchar1 +1: + mov $011,-(sp) +1: + tst nsp + beq 2f + tst slow + bne 4f + tst op + bne 4f + jsr pc,dsp + cmp nsp,r1 + blt 4f + mov $011,(sp) + cmp r1,$1 + bgt 8f + mov $040,(sp) + dec nsp + br 9f +8: + sub r1,nsp +9: + mov r0,-(sp) +3: + mov 2(sp),r0 + jsr pc,pchar1 + mov (sp)+,r0 + br 1b +4: + mov r0,-(sp) + mov $' ,r0 + jsr pc,pchar1 + mov (sp)+,r0 + dec nsp + bne 4b +2: + tst (sp)+ + cmp r0,$026 + blt 2f + cmp r0,$037 + beq 3f + bgt 2f + mov r0,-(sp) + jsr r5, switch; unpfx + cmp (sp)+,r0 + beq 2f + mov r0,-(sp) + mov $033,r0 /prefix + jsr pc,pchar1 + dec ocol + mov (sp)+,r0 +2: +pchar1: + cmp r0,$011 + bne 1f + jsr pc,dsp + br 2f +1: + jsr pc,width +2: + add r1,ocol +pchar2: + tst op + beq 1f + mov op,r1 + jsr pc,wbf + mov r1,op + br 3f +1: + tst tflg + bne 1f + cmp pn,pfrom + blt 3f + clr pfrom +1: + movb r0,*obufp + inc obufp + cmp obufp,$obuf+512. + beq flush +3: + rts pc + +dsp: + clr r1 +1: + add $8.,r1 + cmp ocol,r1 + bgt 1b + sub ocol,r1 + bne 2f + mov $8.,r1 +2: + rts pc + +unpfx: + .byte 032, '9 + .byte 035, '8 + .byte 036, '7 + .byte 031, '3 + .byte 030, '4 + .byte 026, '1 + .byte 027, '2 + .byte 0,0 + +flush: + mov obufp,r0 + sub $obuf,r0 + mov r0,0f + mov outid,r0 + sys 0;7f +.data +7: sys write; obuf; 0:0 +.text + jes place + inc toolate + mov $obuf,obufp + rts pc + +rdtty: +/ mov sp,r1 +/ sys signal; 2; rdtty1 + clr r0 + sys read; char; 1 + tst r0 + bne 2f +rdtty1: +/ mov r1,sp + jsr pc,popi +rdtty2: + clr tty + tst quiet + beq 0f + bis $10,ttym + mov ttyid,r0 + sys stty; ttys +0: + clr r0 +1: +/ sys signal; 2; place + rts pc +2: + mov char,r0 + cmpb r0,$'\n + beq 3f + mov $1,tty + br 1b +3: + inc tty + cmp tty,$3 + beq rdtty1 + br 1b + +ttyn: + mov r1,-(sp) + mov $'x,-(sp) + clr -(sp) + sys fstat; ybuf + bes 3f + mov ybuf+2,(sp) + sys open; dev; 0 + bes 3f + mov r0,r1 +1: + mov r1,r0 + sys read; ybuf; 16. + bes 2f + cmp r0,$16. + bne 2f + mov $ybuf,r0 + cmp (r0)+,(sp) + bne 1b + cmp (r0)+,$"tt + bne 1b + cmpb (r0)+,$'y + bne 1b + tstb (r0)+ + beq 1b + cmpb (r0),$'\0 + bne 1b + movb -(r0),2(sp) +2: + mov r1,r0 + sys close +3: + tst (sp)+ + movb (sp)+,r0 + mov (sp)+,r1 + rts pc +dev: +.even + +cont1: + mov r0,-(sp) + mov pc,r2 + br 0f +control: + jsr pc,getchar + mov r0,-(sp) + jsr pc,getchar + cmpb r0,$'\n + beq 8f + cmpb r0,$' / + bne 9f +8: + mov r0,ch + clr r0 +9: + swab r0 + bis (sp),r0 + clr r2 +0: + mov $contab,r1 +1: + mov (r1)+,(sp) + bic $100000,(sp) + cmp r0,(sp) + bne 4f + mov (r1),(sp) + tst -(r1) + bpl 3f + clr *nxf + tst r2 + bne 2f + jsr pc,collect +2: + jsr pc,flushi + jsr pc,pushi + beq 5f + mov (sp),ip + br 5f +3: + jmp *(sp)+ +4: + cmp (r1)+,$-1 + bne 1b +5: + tst (sp)+ + rts pc + +.data +contab: +; casead +; casebp +; casepn +
; casebr +; casecc +; casec2 +; casece +; casefi +; casein +

  • ; caseli +; casell +; casels +; casens +; casers +; casena +; casene +; casenf +; casepl +; casesp +; casesv +; casesv +; caseos +; caseta +; caseti +; casetr +
      ; caseul +; casetl +; caselt +; casehc +; casehy +; casenh +; casenm +; casenp +; casenn +; casear +; casero +; caseroc +; casenx +; caseso +; casepo +; casede +; caseds +; caseam +; caseas +; caseda +; casedi +; caserm +; casern +; caseig +; casetc +; caseec +; caseeo +; caselc +; casenc +; caseev +; caseif +; casewh +; casech +; caserd +; casetm +; casenr +; casemk +; casert +; casest +; casefl +; done +; casexh +; caseem +; casefc +; caseaf +; casepi +; casehw +bnames: .=.+512. +-1; -1 +.text diff --git a/source/s7/nroff2.s b/source/s7/nroff2.s new file mode 100644 index 0000000..7de76df --- /dev/null +++ b/source/s7/nroff2.s @@ -0,0 +1,1239 @@ +/ +/ + +/ nroff2 + +casead: + inc ad + jsr pc,skipcont + tst nlflg + bne 1f + jsr pc,getchar + cmp r0,$'r /right adj, left ragged + bne 0f + mov $2,jfomod + br 1f +0: + cmp r0,$'l /left adj, right ragged + bne 0f + clr jfomod + clr ad + br 1f +0: + cmp r0,$'c /centered adj + bne 0f + mov $1,jfomod + br 1f +0: + clr jfomod /left and right adj + inc ad +1: + rts pc + +casebr: + jsr pc,rbreak + rts pc + +casecc: + clr -(sp) + br 0f +casec2: + mov pc,-(sp) +0: + jsr pc,skipcont + jsr pc,getchar + cmp r0,$'\n + beq 2f + tst (sp) + bne 1f + mov r0,cc + br 2f +1: + mov r0,c2 +2: + mov r0,ch + tst (sp)+ + rts pc + +casece: + jsr r5,number; 0 + jsr pc,min + mov r0,-(sp) + jsr pc,rbreak + mov (sp)+,ce + rts pc + +casefi: + jsr pc,rbreak + inc fi + rts pc + +casein: + jsr pc,skipcont + tst nlflg + beq 1f + mov in1,r0 + br 2f +1: + jsr r5,number1; in + jsr pc,min +2: + mov r0,-(sp) + jsr pc,rbreak + mov in,in1 + mov (sp)+,in + tst nc + bne 1f + mov in,un + jsr pc,setnel +1: + rts pc + +caseli: + jsr r5,number; 0 + jsr pc,min + mov r0,lit + mov frame,litlev + cmp nl,$-1 + bne 0f + jsr pc,newln1 +0: + rts pc + +casell: + jsr pc,skipcont + tst nlflg + beq 1f + mov ll1,r0 + br 2f +1: + jsr r5,number1; ll + jsr pc,min +2: + mov ll,ll1 + mov r0,ll +2: + jsr pc,setnel + rts pc + +casels: + jsr pc,skipcont + tst nlflg + beq 1f + mov ls1,r0 + br 2f +1: + jsr r5,number1; ls + dec r0 + jsr pc,min + inc r0 +2: + mov r0,-(sp) +/ jsr pc,rbreak + mov ls,ls1 + mov (sp)+,ls + rts pc + +casens: + inc nls + rts pc + +casers: + clr nls + rts pc + +casena: + clr ad + rts pc + +casene: + jsr r5,number; 0 + jsr pc,min + jsr pc,need2 + rts pc + +casenf: + jsr pc,rbreak + clr fi + rts pc + +casepn: + jsr pc,skipcont + bne 1f + jsr r5,number1; pn + jsr pc,min + mov r0,npn +1: + rts pc +casebp: + mov ilistp,-(sp) + clr -(sp) + jsr pc,skipcont + bne 1f + jsr r5,number1; pn + jsr pc,min + mov r0,(sp) +1: + jsr pc,rbreak + mov (sp)+,r0 + beq 0f + mov r0,npn +0: + bne 2f + tst nls + bne 3f +2: + mov (sp),r0 + jsr pc,eject +3: + tst (sp)+ + rts pc + +casepl: + jsr pc,skipcont + tst nlflg + bne 1f + jsr r5,number1; pl + mov r0,pl + rts pc +1: + mov $66.,pl + rts pc + +casesp: + mov pc,-(sp) + br 0f +casesp1: + clr -(sp) +0: + mov r0,-(sp) + tst nb + bne 0f + jsr pc,rbreak +0: + tst nls + bne 2f + clr r0 + jsr pc,findt + tst nb + bne 1f + tst trap + bne 2f +1: + tst 2(sp) + beq 1f + jsr r5,number;0 + mov r0,(sp) +1: + cmp r1,(sp) + bge 1f + mov r1,(sp) +1: + mov (sp),r0 + ble 3f + jsr r5,nlines; newline +2: + cmp (sp)+,(sp)+ + rts pc +3: + add nl,r0 + cmp (sp)+,(sp)+ + br casert1 + +casert: + mov markline,r2 + jsr pc,skipcont + bne 0f + jsr r5,number1;nl +casert1: + mov r0,r2 +0: + tst r2 + blt 2f + cmp r2,nl + bge 2f + mov nl,r1 + mov r2,nl + sub r2,r1 + mov r1,r2 +1: + mov $036,r0 + jsr pc,putchar + dec r2 + bgt 1b + mov $015,r0 + jsr pc,putchar +2: + rts pc + +casesv: + clr r0 + jsr pc,findt + jsr r5,number; 0 + cmp r1,r0 + bge 1f + mov r0,sv + rts pc +1: + jsr r5,nlines; newline + rts pc + +caseos: + tst sv + beq 2f + clr r0 + jsr pc,findt + cmp r1,sv + bge 1f + rts pc +1: + mov sv,r0 + clr sv + jsr r5,nlines; newline +2: + rts pc + +casetr: + jsr pc,skipcont +1: + jsr pc,getchar + cmp r0,$'\n + beq 1f + mov r0,r1 + jsr pc,getchar + cmp r0,$'\n + bne 2f + mov $' ,r0 +2: + movb r0,trtab(r1) + br 1b +1: + rts pc + +caseta: + clr -(sp) + mov $tabtab,r1 +1: + jsr pc,getchar + tst nlflg + bne 1f + cmpb r0,$'+ + bne 0f + inc (sp) + br 2f +0: + cmpb r0,$'- + beq 2f + cmpb r0,$'0 + blo 1b + cmpb r0,$'9 + bhi 1b +2: + mov r0,ch + jsr pc,atoi + beq 1f + jsr pc,min + dec r0 + ble 1f + cmp r1,$tabtab + beq 0f + tst (sp) + bne 3f + cmp r0,-2(r1) + bgt 0f +3: + add -2(r1),r0 +0: + clr (sp) + mov r0,(r1)+ + cmp r1,$etabtab + blo 1b + tst -(r1) +1: + tst (sp)+ + clr (r1) + rts pc + +caseti: + jsr r5,number; in + jsr pc,min + mov r0,-(sp) + jsr pc,rbreak + mov (sp)+,un1 + jsr pc,setnel + rts pc + +caseul: + jsr r5,number; 0 + jsr pc,min + mov r0,ul + rts pc + +casetl: + jsr pc,header + rts pc + +caselt: + jsr pc,skipcont + tst nlflg + beq 1f + mov llh1,r0 + br 2f +1: + jsr r5,number1; llh + jsr pc,min +2: + mov llh,llh1 + mov r0,llh + rts pc + + +casehc: + jsr pc,skipcont + jsr pc,getchar + cmp r0,$'\n + bne 1f + movb $200,r0 +1: + mov r0,ohc + rts pc + +casetc: + jsr pc,skipcont + jsr pc,getchar + cmp r0,$'\n + bne 1f + mov $014,r0 +1: + mov r0,tabc + rts pc + +caselc: + jsr pc,skipcont + jsr pc,getchar + cmp r0,$'\n + bne 1f + mov $'.,r0 +1: + mov r0,dotc + rts pc + +casenc: + jsr pc,skipcont + jsr pc,getchar + cmp r0,$'\n + bne 1f + mov $034,r0 +1: + mov r0,numc + rts pc + +casehy: + mov $1,hyf + jsr pc,skipcont + bne 1f + jsr pc,atoi + beq 1f + jsr pc,min + mov r0,hyf +1: + rts pc + +casenh: + clr hyf + rts pc + +casenp: + jsr pc,skipcont + tst nlflg + beq 2f + clr ni + mov $1,nms + mov $1,ndf + rts pc +casenm: + clr numbmod + clr nn + jsr pc,skipcont + tst nlflg + beq 1f + rts pc +1: + inc numbmod + jsr r5,number1; lnumber + jsr pc,min + mov r0,lnumber + jsr pc,skipcont +2: + jsr r5,3f; ndf + tst ndf + bne 1f + inc ndf +1: + jsr pc,skipcont + jsr r5,3f; nms + jsr pc,skipcont + jsr r5,3f; ni + rts pc +3: + tst nlflg + bne 4f + jsr pc,atoi + beq 4f + jsr pc,min + mov r0,*(r5) +4: + tst (r5)+ + rts r5 + +casenn: + jsr r5,number; 0 + jsr pc,min + mov r0,nn + rts pc + +casear: + clr ro + rts pc + +caseroc: + mov $2,ro + rts pc +casero: + mov $1,ro + rts pc + +casenx: + jsr pc,skipcont + jsr r5,getname; nextf + inc nx + jsr pc,nextfile + inc nlflg + clr ip + clr ap + clr nspace + clr pendt + mov $ilist,ilistp + rts pc + +casepo: + jsr pc,skipcont + tst nlflg + beq 1f + mov po1,r0 + br 2f +1: + jsr r5,number1; po + jsr pc,min +2: + mov r0,-(sp) +/ jsr pc,rbreak + mov po,po1 + mov (sp)+,po + rts pc + +caseig: + inc skp + jsr pc,copyb + rts pc + +casern: +/ inc lgf + jsr pc,skipcont + jsr r5,getname;bname + beq 2f + jsr pc,findmn + beq 2f + mov oldptr,-(sp) +/ inc lgf + jsr pc,skipcont + jsr r5,getname;bname + beq 1f + jsr pc,findmn + jsr pc,clrold + mov (sp),r1 + tst -(r1) + mov (r1),(sp) + bic $77777,(sp) + mov bname,(r1) + bis (sp),(r1) +1: + tst (sp)+ +2: + rts pc + +caserm: +/ inc lgf + jsr pc,skipcont + jsr r5,getname;bname + beq 1f + jsr pc,findmn + jsr pc,clrold +1: + rts pc + +caseas: + inc app +caseds: + inc ds + br casede +caseam: + inc app +casede: + tst op + beq 1f + jsr pc,wbfl +1: +/ inc lgf + jsr pc,skipcont + jsr r5,getname; bname + bne 1f + clr r1 + br 6f +1: + clr skp + jsr pc,finds + beq 7f + tst ds + beq 0f + tst skp + bne 5f + jsr pc,copys + br 5f +0: + jsr pc,copyb +5: + jsr pc,wbfl + jsr pc,clrold + tst newptr + beq 0f + bis $100000,bname + mov bname,*newptr +0: + mov r1,-(sp) + mov apptr,r1 + beq 0f + mov $004,r0 + jsr pc,wbt +0: + mov (sp)+,r1 +6: + clr app + clr ds + rts pc +7: + tst macerr + bne 0f + jsr r5,stringfl; 8f +0: + inc macerr + cmp macerr,$1 + jeq edone + jmp done2 +/ br 6b +8: + .even + +findmn: + mov $contab,r1 +1: + mov (r1)+,r0 + bic $100000,r0 + cmp bname,r0 + beq 2f + cmp (r1)+,$-1 + bne 1b + clr r1 +2: + mov r1,oldptr + rts pc + +finds: + jsr pc,findmn + clr newptr + clr apptr + clr aplnk + tst app + beq 0f + tst oldptr + bne 5f +0: + mov $contab,r1 +1: + tst (r1)+ + beq 2f + cmp (r1)+,$-1 + bne 1b +1: + inc skp + clr r1 + rts pc +2: + jsr pc,alloc + beq 1b + tst oldptr + bne 3f +4: + tst -(r1) + bis $100000,bname + mov bname,(r1)+ + mov nextb,(r1) + br 6f +3: + tst diflg + bne 4b + mov nextb,(r1) + tst -(r1) + mov r1,newptr + br 6f +5: + tst -(r1) + bmi 1f + clr app + br 0b +1: + tst (r1)+ + clr oldptr + mov ip,-(sp) + mov (r1),ip +1: + jsr pc,rbf + tst r0 + bne 1b + mov ip,r1 + mov r1,apptr + tst diflg + bne 0f + jsr pc,incoff +0: + mov r1,nextb + mov (sp)+,ip +6: + clr app + mov nextb,r1 + rts pc + +clrold: + mov oldptr,r0 + beq 1f + mov (r0),-(sp) + clr (r0) + tst -(r0) + bmi 0f + clr (sp) +0: + clr (r0) + mov (sp)+,r0 + beq 1f + jsr pc,free +1: + rts pc + +caseda: + inc app +casedi: +/ inc lgf + clr ditf + jsr pc,skipcont + jsr r5,getname; bname + beq 1f + tst op + bne 3f + inc diflg + jsr pc,finds + beq 3f + mov r1,op + jsr pc,clrold +/ mov blss,sblss +/ mov alss,salss +/ clr blss +/ clr alss + clr dnl + br 3f +1: + tst op + beq 3f + clr r0 + jsr pc,pchar1 + jsr pc,wbfl +/ mov sblss,blss +/ mov salss,alss + clr op +3: + clr app + clr diflg + rts pc + +caseev: + jsr pc,skipcont + tst nlflg + beq 2f + cmp evp,$elist + ble 5f +1: + sub $2,evp + mov *evp,-(sp) + br 3f +2: + jsr pc,atoi + beq 6f + cmp r0,nev + bgt 6f + tst r0 + blt 6f + cmp evp,$eliste + bgt 6f + mov r0,-(sp) + mov ev,*evp + add $2,evp +3: + cmp (sp),ev + beq 4f + mov $1024.,r3 + mpy ev,r3 + mov r3,8f + mov $1024.,r3 + mpy (sp),r3 + mov r3,9f + mov ibf,r0 + sys 0;7f +.data +7: sys seek; 8:.. ; 0 +.text + mov ibf,r0 + sys write; block; 1024. + mov ibf1,r0 + sys 0;7f +.data +7: sys seek; 9:.. ; 0 +.text + mov blocksize,0f + mov ibf1,r0 + sys 0;7f +.data +7: sys read; block; 0:.. +.text +4: + mov (sp)+,ev +5: + rts pc +6: + jsr r5,string;9f + rts pc +9: +.even + +caseif: + clr -(sp) + jsr pc,skipcont + jsr pc,getchar + cmp r0,$'! + bne 1f + inc (sp) + br 2f +1: + mov r0,ch +2: + jsr pc,atoi + beq 1f + tst r0 + bgt 5f /true + br 6f /false +1: + jsr pc,getchar + cmp r0,$'e + bne 1f + bit $1,pn + bne 6f + br 5f +1: + cmp r0,$'o + bne 1f + bit $1,pn + beq 6f + br 5f +1: + cmpb r0,$'n + beq 5f +1: + tst (sp)+ + rts pc +5: + tst (sp) + bne 1b +2: + clr column + jsr pc,getchar + bmi 0f + cmpb r0,$' / + beq 2b +0: + mov r0,ch + inc nflush + br 1b +6: + tst (sp) + beq 1b + br 2b + +casewh: + clr -(sp) + jsr pc,skipcont + jsr pc,getchar + cmp r0,$'x + bne 1f + mov $-1,r0 + jsr pc,findt + add nl,r1 + sub dnl,r1 + mov r1,r0 + br 2f +1: + mov r0,ch + jsr pc,atoi + beq 4f +2: + mov r0,(sp) + jsr pc,skipcont + jsr r5,getname; bname + tstb bname + bne 1f + clr bname +1: + mov (sp),r0 + jsr pc,findn + tst r1 + beq 1f + mov bname,[mlist-nlist](r1) + br 4f +1: + mov $mlist,r1 +2: + tst (r1)+ + beq 3f + cmp r1,$mliste + bgt 4f + br 2b +3: + mov bname,-2(r1) + mov (sp),[nlist-mlist-2](r1) +4: + tst (sp)+ + rts pc + +findn: + mov $nlist,r1 +1: + cmp (r1),r0 + beq 3f +2: + tst (r1)+ + cmp r1,$nliste + bne 1b + clr r1 + rts pc +3: + tst [mlist-nlist](r1) + beq 2b + rts pc + +findm: + mov $mlist,r1 +1: + cmp (r1),bname + beq 3f +2: + tst (r1)+ + cmp r1,$mliste + bne 1b + clr r1 + rts pc +3: + sub $[mlist-nlist],r1 + rts pc + +casech: + clr -(sp) + jsr pc,skipcont + jsr pc,atoi + beq 2f + jsr pc,findn + br 3f +2: + jsr r5,getname; bname + tstb bname + beq 1f + jsr pc,findm +3: + tst r1 + beq 1f + mov r1,(sp) + jsr pc,skipcont + jsr pc,atoi + beq 2f + mov r0,*(sp) +1: + tst (sp)+ + rts pc +2: + jsr pc,getchar + tst nlflg + bne 1b + mov *(sp),r0 + beq 1b + bgt 0f + add pl,r0 + inc r0 +0: + sub nl,r0 + ble 1b + dec r0 + ble 1b + cmp dnl,r0 + bge 0f + mov dnl,r0 +0: + sub r0,*(sp) + br 1b + +casemk: + jsr pc,skipcont + beq 1f + mov nl,markline + rts pc +1: + jsr r5,getname; bname + mov bname,r0 + beq 2f + jsr pc,findr + beq 2f + mov nl,(r1) +2: + rts pc + +casetm: + inc copyf + jsr pc,skipcont + mov $bname,r1 +1: + jsr pc,getchar + bmi 1b + movb r0,(r1)+ + tst nlflg + bne 2f + cmp r1,$ename + blo 1b + movb $'\n,-1(r1) +2: + clrb (r1) + jsr r5,stringfl; bname + clr copyf + rts pc + +caserd: + jsr pc,skipcont + jsr r5,getname; bname + tst iflg + bne 1f + tst quiet + bne 2f + tstb bname + beq 5f + jsr r5,string; bname + jsr r5,string; 3f +1: + jsr pc,collect + inc tty + jsr pc,pushi + beq 6f + mov $-1,ip + rts pc +2: + bic $10,ttym + mov ttyid,r0 + sys stty; ttys + jsr pc,flush +5: + jsr r5,string;4f + br 1b +6: + jmp rdtty2 +3: <: \0> +4: <\0> /bell + .even + +caseaf: + jsr pc,skipcont + bne 3f + jsr r5,getname;bname + mov bname,r0 + beq 3f + jsr pc,findr + jsr pc,skipcont + jsr pc,getchar + mov $4f,r2 +1: + cmpb r0,(r2)+ + beq 2f + inc r2 + tstb (r2) + bne 1b +2: + movb (r2),[flist-vlist](r1) +3: + rts pc +4: +.byte '1,1 +.byte 'i,2 +.byte 'I,3 +.byte 'a,4 +.byte 'A,5 +.byte 0,0 + +casenr: + jsr pc,skipcont + bne 5f + jsr r5,getname; bname + mov bname,r0 + jsr pc,findr + mov r1,0f + beq 5f + jsr pc,skipcont + bne 5f + jmp 7f +.data +7: jsr r5,number1; 0:.. + jmp 8f +.text +8: + bne 1f + clr r0 +1: + mov r0,*0b + jsr pc,skipcont + bne 5f + jsr pc,atoi + beq 5f + mov r0,[inclist-vlist](r1) +5: + rts pc + +casefl: + jsr pc,rbreak + jsr pc,flush + rts pc + +casexh: +/ tst x.5 +/ bne 1f + inc x.5 + rts pc +/1: +/ clr x.5 +/ rts pc + +caseso: + jsr pc,skipcont + tst nlflg + bne 1f + jsr r5,getname; nextf + tstb nextf + beq 1f + sys open; nextf; 0 + bes 1f + mov ifp,r1 + cmp r1,$ifle + bhi 1f + mov r0,-(sp) + jsr pc,flushi + mov ifile,(r1) + mov (sp)+,ifile + mov ioff,[offl-ifl](r1) + add $2,ifp + clr ioff + inc nx + inc nflush + tst (r1) + bne 1f + jsr pc,savebuf +1: + rts pc + +caseeo: + clr r0 + br 1f +caseec: + jsr pc,skipcont + jsr pc,getchar + cmpb r0,$'\n + bne 1f + movb $'\\,r0 +1: + movb r0,eschar + movb r0,eschar+1 + rts pc + +casest: + 4 + +caseem: + clr em + jsr pc,skipcont + bne 1f + jsr r5,getname;bname + beq 1f + mov bname,em +1: + rts pc + +casefc: + mov $4,fc + mov $' ,padc + jsr pc,skipcont + bne 1f + jsr pc,getchar + bmi 1f + movb r0,fc + jsr pc,skipcont + bne 1f + mov ch,r0 + bmi 1f + cmpb r0,fc + beq 1f + movb r0,padc +1: + rts pc + +casepi: + tst toolate + bne 1f + jsr pc,skipcont + jsr r5,getname;bname + beq 1f + sys 42. /pipe + jes place + mov r0,pipin + mov r1,outid + sys fork + br 2f + jes place + mov $1,r0 + sys close + mov pipin,r0 + sys close +1: + inc toolate + rts pc +2: + clr r0 + sys close + mov pipin,r0 + sys 41. /dup + mov outid,r0 + sys close + sys exec;bname;args + jsr r5,string;9f + sys exit +args: bname;0 +9: +.even diff --git a/source/s7/nroff3.s b/source/s7/nroff3.s new file mode 100644 index 0000000..9e78046 --- /dev/null +++ b/source/s7/nroff3.s @@ -0,0 +1,1264 @@ +/ +/ + +/ nroff3 + +skipcont: +/ mov r2,-(sp) +0: + jsr pc,getchar +/ mov r0,r2 +/ jsr pc,alph2 +/ beq 0b +1: + cmp $' ,r0 + bne 1f + jsr pc,getchar + br 1b +1: +/ mov (sp)+,r2 + mov r0,ch + tst nlflg + rts pc + +rbreak: + jsr pc,rbreak1 + clr totout + rts pc +rbreak1: + clr trap + tst nb + beq 1f + rts pc +1: + cmp nl,$-1 + bne 1f + jsr pc,newln1 + rts pc +1: + tst nc + bne 1f + tst pendw + bne 4f + tst wch + beq 4f + jsr pc,setnel + jsr pc,movword + nop +1: + clrb *linep + clr nls + inc totout + tst lastl + bmi 1f + mov ne,lastl + br 0f +1: + mov ll,lastl +0: + tst op + bne 0f + mov po,r0 + jsr pc,space +0: + jsr pc,donum + mov un,r0 + jsr pc,space + jsr pc,jfo + mov $line,r2 +1: + movb (r2)+,r0 + cmp $' ,r0 + bne 2f + jsr pc,fill + tst nc + bne 1b + br 3f +2: + jsr pc,putchar + dec nc + bgt 1b +3: + clr nwd + clr ne + mov in,un + jsr pc,setnel + jsr pc,newline + cmp nl,hnl + ble 0f + mov nl,hnl +0: + tst trap + bne 3f + mov ls,r2 + dec r2 + clr r0 + jsr pc,findt + cmp r1,r2 + bgt 1f + mov r1,r0 + jsr r5,nlines; newline + br 3f +1: + mov r2,r0 + jsr r5,nlines;newline +3: +/ clr pendb + clr spread + rts pc +4: + jsr pc,setnel + rts pc + +jfo: + tst jfomod + beq 1f + mov fac,r0 + add fmq,r0 + beq 1f + clr fac + clr fmq + mov nel,r0 + cmp jfomod,$1 + bne 2f + asr r0 +2: + jsr pc,space +1: + rts pc + +donum: + tst numbmod + beq 2f + dec nn + blt 1f +0: + mov $3,r0 + add nms,r0 + add ni,r0 + jsr pc,space + rts pc +1: + mov lnumber,r1 + sxt r0 + mov ndf,-(sp) + dvd (sp)+,r0 + tst r1 + beq 1f + inc lnumber + br 0b +1: + clr r0 + cmp lnumber,$100. + bge 1f + inc r0 + cmp lnumber,$10. + bge 1f + inc r0 +1: + add ni,r0 + jsr pc,space + mov lnumber,r0 + jsr r5,decimal; putchar + mov nms,r0 + jsr pc,space + inc lnumber +2: + rts pc + +newline: + mov $'\n,r0 + jsr pc,putchar + tst op + beq 1f + inc dnl + rts pc +1: + tst x.5 + beq 1f + mov $032,r0 + jsr pc,putchar +1: + inc nl + cmp nl,pl + blo 3f +newln1: + clr nl + clr hnl + clr ejf + mov $ilist,ejl + tst donef + beq 2f + tst nc + bne 1f + tst wch + bne 1f + jmp done1 +1: + tst ndone + jne done1 + inc ndone + clr donef + cmp frame,$stk + bne 2f + inc nflush +2: + inc pn + tst npn + beq 1f + mov npn,pn + clr npn +1: + cmp pn,pto + ble 2f + jsr pc,flush + jmp place +2: + tst stop + beq 2f + cmp pn,pfrom + blo 2f + jsr pc,flush +/ mov sp,r1 +/ sys signal; 2; 1f + mov ttyid,r0 + sys read; char; 1 +1: +/ mov r1,sp +/ sys signal; 2; place +2: +/ cmp numbmod,$1 +/ bne 3f +/ mov $1,lnumber +3: + clr trap + jsr pc,findnl + tst r1 + beq 4f + mov [mlist-nlist](r1),r0 + mov frame,-(sp) + jsr pc,cont1 + cmp (sp)+,frame + beq 4f + inc trap +/ inc nlflg + rts pc +4: + tst ejf + beq 5f + cmp ilistp,ejl + beq newline +5: + rts pc + +findnl: + mov $nlist,r1 +1: + mov (r1),r0 + tst r0 + bpl 2f + add pl,r0 + inc r0 +2: + cmp nl,r0 + beq 4f +3: + tst (r1)+ + cmp r1,$nliste + bne 1b + clr r1 + rts pc +4: + tst [mlist-nlist](r1) + beq 3b + rts pc + +number: + jsr pc,skipcont +number1: + clr -(sp) + mov r1,-(sp) + mov r3,-(sp) + clr r3 + clr -(sp) +1: + jsr pc,getchar + cmp r0,$'+ + beq 2f + cmp r0,$'- + beq 2f + mov r0,ch +1: + jsr pc,atoi + beq 3f + mov r0,r3 + inc 6(sp) + br 3f +2: + mov r0,(sp) + br 1b +3: + tst 6(sp) + bne 1f + mov $1,r3 +1: + mov (r5)+,r0 + beq 1f + mov (r0),r0 +1: + mov (sp)+,r1 + cmp r1,$'- + bne 1f + sub r3,r0 + br 2f +1: + cmp r1,$'+ + bne 1f + add r3,r0 + br 2f +1: + mov r3,r0 +2: + mov (sp)+,r3 + mov (sp)+,r1 + tst (sp)+ + rts r5 + +eject: +/ tst ejf +/ bne 2f + inc ejf + mov r0,ejl + tst trap + bne 2f + jsr pc,newline +2: + rts pc + +storeline: + cmp linep,$line+linsiz + bhis 1f + movb r0,*linep + inc linep + jsr pc,width + add r1,ne + sub r1,nel + inc nc + rts pc +1: + tst over + bne 2f + jsr r5,stringfl; linemes +2: + inc over + rts pc +linemes: + .even + +getword: + clr -(sp) + clr -(sp) + mov pendw,r2 + bne 5f + mov $word,r2 + clr over + clr wne + clr wch + clr nhyph + clr hypedf + mov $word,wordp +1: + jsr pc,gettchar + bmi 4f + cmpb r0,$'\n + bne 0f + clr wne + clr wch + br 3f +0: + cmpb r0,ohc + bne 2f + inc hypedf + br 1b +2: + cmpb $' ,r0 + bne 2f + jsr pc,storeword + br 1b +2: +4: + mov r0,-(sp) + mov $' ,r0 +/ bis chbits,r0 + jsr pc,storeword + tst spaceflg + beq 2f + jsr pc,storeword + clr spaceflg +2: + mov (sp)+,r0 +2: + tst r0 + bmi 0f + cmpb r0,$005 + beq 6f +0: + inc 2(sp) + jsr pc,storeword + bisb (sp),-1(r2) /add in hyphen + clr (sp) +5: + jsr pc,gettchar + bmi 1f + cmpb r0,ohc + bne 1f + inc hypedf + jsr pc,gettchar + mov $200,(sp) +1: + tst r0 + bmi 2b + cmpb $' ,r0 + beq 1f + cmpb $'\n,r0 + bne 2b + cmpb -1(r2),$'. + beq 0f + cmpb -1(r2),$'! + beq 0f + cmpb -1(r2),$'? + bne 1f +0: + inc spaceflg +1: + add $2,4(sp) + clrb (r2)+ +3: + clr pendw + cmp (sp)+,(sp)+ + mov $word,wordp + jsr pc,setnel +/ jsr pc,wordout + rts pc +6: + tst (sp)+ + tst (sp)+ + beq 7f + mov r2,pendw +0: + clr nflush + jsr pc,flushi + rts pc +7: + clr wch + br 0b + +setnel: + tst nc + bne 2f + mov $line,linep + mov ll,nel + tst un1 + blt 1f + mov un1,un + mov $-1,un1 +1: + sub un,nel + clr ne + clr fac + clr fmq +2: + rts pc + +storeword: + cmp r2,$eword + bhis 1f + jsr pc,width + add r1,wne + inc wch + movb r0,(r2)+ + rts pc +1: + tst over + bne 2f + jsr r5,stringfl; wordmes +2: + inc over + rts pc +wordmes: + .even + +need: +need2: + mov r0,-(sp) + clr r0 + jsr pc,findt + cmp (sp)+,r1 + ble 1f +/ mov ilistp,r0 +/ jsr pc,eject + mov r1,r0 + clr nls + jsr r5,nlines;newline +1: + rts pc + +min: + tst r0 + bge 1f + clr r0 +1: + rts pc + +getname: + mov r1,-(sp) + mov r2,-(sp) + mov (r5),r1 + mov $namesiz,r2 +1: + jsr pc,getchar + tst nlflg + bne 2f + cmp r0,$040 + beq 2f + cmp r0,$0176 + blos 4f +2: + mov r0,ch +3: + clrb (r1)+ + mov (sp)+,r2 + mov (sp)+,r1 + tstb *(r5)+ + rts r5 +4: + movb r0,(r1)+ + dec r2 + beq 3b + br 1b + +copyb: + inc copyf + jsr pc,flushi + clr nlflg + clr -(sp) + mov $1,-(sp) +1: + jsr pc,getchar + bmi 9f + cmpb r0,$'\n + bne 2f + mov $1,(sp) + clr nlflg + br 4f +2: + cmpb r0,$'. + bne 9f + cmp (sp),$1 + bgt 3f + blt 9f + inc (sp) + br 4f +3: + tst skp + bne 0f + jsr pc,wbfl + mov 2(sp),r1 + clr r0 + jsr pc,wbt +0: + inc (sp) + br 5f +9: + clr (sp) +4: + mov r1,2(sp) + tst skp + bne 5f + jsr pc,wbf +5: + cmp (sp),$3 + bne 1b + cmp (sp)+,(sp)+ +6: + clr copyf + rts pc + +allocmes: + .even + +alloc: + mov r1,-(sp) + clr nextb + mov $blist,r1 +1: + tst (r1)+ + beq 3f + cmp r1,$eblist + blo 1b +2: + mov (sp)+,r1 + tst nextb + rts pc +3: + mov $-1,-(r1) + jsr pc,offset + cmp r1,first + blo 2b + mov r1,nextb + br 2b + +free: + mov r1,-(sp) + mov r0,r1 + beq 2f +1: + jsr pc,blistptr + tst (r1) + beq 2f + cmp (r1),$-1 + bne 3f + clr (r1) +2: + mov (sp)+,r1 + rts pc +3: + mov (r1),-(sp) + clr (r1) + mov (sp)+,r1 + br 1b + +offset: + sub $blist,r1 + ash $7,r1 + add first,r1 + rts pc + +blistptr: + mov r0,-(sp) + clr r0 + sub first,r1 + ashc $-7,r0 + bic $1,r1 + add $blist,r1 + mov (sp)+,r0 + rts pc + +wbt: + jsr pc,wbf + jsr pc,wbfl + rts pc +wbf: + tst woff + bne 0f + mov r1,woff + mov $wbuf,wbufp +0: + mov r0,*wbufp + add $2,wbufp + add $2,r1 + bit $377,r1 + bne 2f + sub $2,r1 + jsr pc,blistptr + cmp (r1),$-1 + bne 1f + jsr pc,wbfl + jsr pc,alloc + bne 0f + jsr r5,stringfl;allocmes + jmp done +0: + mov nextb,(r1) +1: + mov (r1),r1 +2: + cmp wbufp,$wbufe + bhis wbfl + rts pc +wbfl: + tst woff + beq 0f + mov wbufp,9f + sub $wbuf,9f + beq 0f + mov ibf,r0 + sys 0;7f +.data +7: sys seek; woff:..;0 +.text + mov ibf,r0 + sys 0;7f +.data +7: sys write; wbuf; 9:.. +.text + clr woff + mov $-1,roff +0: + rts pc +rbf: + mov ip,r1 + jsr pc,rbf0 + bne 0f + tst app + bne 1f + jsr pc,popi + rts pc +0: + jsr pc,incoff +1: + mov r1,ip + rts pc + +rbf0: + mov r1,-(sp) + bic $377,r1 + cmp r1,roff + beq 1f + mov r1,roff + mov ibf1,r0 + sys 0;7f +.data +7: sys seek; roff:-1 ;0 +.text + mov ibf1,r0 + sys read;rbuf;256. + tst r0 + bne 1f + tst (sp)+ + sez + rts pc +1: + mov (sp),r0 + bic $!377,r0 + mov (sp)+,r1 + mov rbuf(r0),r0 + rts pc + +incoff: + add $2,r1 + bit $377,r1 + bne 1f + sub $2,r1 + jsr pc,blistptr + mov (r1),r1 + beq 5f + cmp $-1,r1 + beq 5f +1: + rts pc +5: + jsr r5,stringfl; badmes + jmp place +badmes: + .even + +alph: + movb (r0),r2 +alph2: + cmp r2,$'A + blo 1f + cmp r2,$'Z + blos 2f + cmp r2,$'a + blo 1f + cmp r2,$'z + bhi 1f +2: + sez + rts pc +1: + clz + rts pc +rdsufb: + mov r1,-(sp) + bic $177,r1 + cmp r1,sufoff + beq 2f + mov r1,sufoff + mov suff,r0 + sys 0;7f +.data +7: sys seek; sufoff: -1; 0 +.text + mov suff,r0 + sys read; sufbuf; 128. +2: + mov (sp),r0 + bic $!177,r0 + movb sufbuf(r0),r0 + mov (sp)+,r1 + rts pc + + +atoi: + jsr pc,atoi1 + bne 1f + rts pc +1: + mov r1,-(sp) + mov r0,-(sp) +1: + jsr pc,getchar + cmp r0,$'+ + beq 4f + cmp r0,$'- + beq 5f +2: + cmp r0,$'* + bne 2f + jsr pc,atoi1 + beq 3f + mov r0,r1 + mpy (sp),r1 + mov r1,(sp) + br 1b +2: + cmp r0,$'\/ + bne 2f + jsr pc,atoi1 + beq 3f + mov r0,-(sp) + mov 2(sp),r1 + sxt r0 + dvd (sp),r0 + mov r0,2(sp) + tst (sp)+ + br 1b +2: + mov r0,ch +3: + mov (sp)+,r0 + mov (sp)+,r1 + tst pc + rts pc +4: + jsr pc,atoi1 + beq 3b + add r0,(sp) + br 1b +5: + jsr pc,atoi1 + beq 3b + sub r0,(sp) + br 1b + +atoi1: + clr -(sp) + mov r3,-(sp) + clr -(sp) + clr r3 + jsr pc,getchar + cmp r0,$'- + bne 2f + inc (sp) +1: + jsr pc,getchar +2: + sub $'0,r0 + cmp r0,$9 + bhi 1f + inc 4(sp) + mpy $10.,r3 + add r0,r3 + br 1b +1: + add $'0,r0 + mov r0,ch + bne 0f + mov $' ,ch +0: + tst (sp)+ + beq 1f + neg r3 +1: + mov r3,r0 + mov (sp)+,r3 + tst (sp)+ + rts pc + +findt: + mov r0,-(sp) + mov $-1,-(sp) + mov $nlist,r1 +1: + tst [mlist-nlist](r1) + bne 3f +2: + tst (r1)+ + cmp r1,$nliste + ble 1b + br 8f +3: + mov (r1),r0 + tst 2(sp) + bmi 6f /- traps + beq 4f /all traps + tst (r1) /+ traps + bmi 2b +4: + tst (r1) + bpl 5f + mov pl,r0 + inc r0 + add (r1),r0 +5: + sub nl,r0 + ble 2b + cmp r0,(sp) + bhis 2b + mov r0,(sp) + br 2b +6: + tst (r1) + bpl 2b + br 4b +8: + mov (sp),r1 + bpl 9f + mov pl,r1 + sub nl,r1 +9: + cmp (sp)+,(sp)+ + rts pc + +findr: + mov $rlist,r1 +1: + tst (r1) + beq 2f + cmp (r1)+,r0 + beq 3f + cmp r1,$rliste + blos 1b + tst numerr + bne 0f + jsr r5,stringfl; 9f +0: + inc numerr +/ clr r1 +/ rts pc + cmp numerr,$1 + jeq edone + jmp done2 +2: + mov r0,(r1) + br 4f +3: + tst -(r1) +4: + add $[vlist-rlist],r1 + rts pc +9: + .even + +setn0: + clr -(sp) + clr -(sp) + mov $1,nform + jbr setn1 +setn: + mov r1,-(sp) + clr -(sp) + clr temp + jsr pc,get1 + cmpb r0,$'+ + bne 1f + inc (sp) +0: + jsr pc,get1 +1: + cmpb r0,$'\\ + bne 1f +3: + jsr pc,get1 + jsr r5,switch;esctab + cmpb r0,dolc + bne 1f + jsr pc,seta + br 0b +1: + tst temp + bne 2f + bic $!177,r0 + cmpb r0,$'( + bne 1f + inc temp + jsr pc,get1 +2: + bic $!177,r0 + cmpb r0,$'\\ + beq 3b + mov r0,-(sp) + jsr pc,get1 + bic $!177,r0 + swab r0 + bis (sp)+,r0 +1: + cmpb 2(sp),$372 + beq 5f /exit if called by \k + clr nform + cmp r0,$".v + bne 0f + mov ls,r0 + br setn1 +0: + cmp r0,$".p + bne 0f + mov pl,r0 + br setn1 +0: + cmp r0,$".t + bne 0f + clr r0 + jsr pc,findt + mov r1,r0 + br setn1 +0: + cmp r0,$".o + bne 0f + mov po,r0 + br setn1 +0: + cmp r0,$".l + bne 0f + mov ll,r0 + br setn1 +0: + cmp r0,$".i + bne 0f + mov in,r0 + br setn1 +0: + cmp r0,$".$ + bne 0f + mov *frame,r0 + br setn1 +0: + cmp r0,$".x + bne 0f + mov evp,r0 + br setn1 +0: + cmp r0,$".c + bne 0f + mov iline,r0 + br setn1 +0: + cmp r0,$".h + bne 0f + mov hnl,r0 + br setn1 +0: + cmp r0,$".n + bne 0f + mov lastl,r0 + br setn1 +0: + jsr pc,findr + tst r1 + beq 5f + tst (sp) + beq 1f + add [inclist-vlist](r1),(r1) +1: + mov (r1),r0 + mov [flist-vlist](r1),nform +setn1: + mov r4,-(sp) + mov $cbuf,r4 + tst r0 + bge 1f + movb $'-,(r4)+ + neg r0 +1: + jsr r5,fnumb0;wrc + clrb (r4) + mov (sp)+,r4 + mov $cbuf,cp +5: + tst (sp)+ + mov (sp)+,r1 + rts pc + +wrc: + cmp r4,$stk + bhis 1f + movb r0,(r4)+ +1: + rts pc + +seta: + jsr pc,get1 + cmp r0,$'\\ + bne 1f + jsr pc,get1 + jsr r5,switch;esctab + cmp r0,numc + bne 1f + clr r1 + jsr pc,setn + br seta +1: + sub $060,r0 + ble 2f + cmp r0,$9. + bgt 2f + cmp r0,*frame + bgt 2f + asl r0 + add frame,r0 + add $stksiz-2,r0 + mov (r0),ap +2: + rts pc + + stksiz = 16. +pushi: + clr r0 + mov enda,-(sp) + sub $stksiz,(sp) + cmp nxf,(sp)+ + blo 0f + jsr pc,setbrk + beq 2f + br pushi +0: + mov nxf,r0 + tst (r0)+ /nargs + mov frame,(r0)+ + mov ip,(r0)+ + mov nspace,(r0)+ + clr nspace + mov rchar,(r0)+ + clr rchar + mov pendt,(r0)+ + mov ap,(r0)+ + mov ch,(r0)+ + clr ch + clr ap + clr pendt + mov nxf,frame + tst *nxf + bne 1f + add $stksiz,nxf + br 2f +1: + mov r1,nxf +2: + tst r0 + rts pc + +popi: + cmp frame,$stk + beq 1f + mov frame,r0 + mov r0,nxf + clr (r0)+ + mov (r0)+,frame + mov (r0)+,ip + mov (r0)+,nspace + mov (r0)+,rchar + mov (r0)+,pendt + mov (r0)+,ap + mov (r0)+,r0 +/ cmp frame,litlev +/ bhis 1f +/ clr lit +1: + rts pc + +setbrk: + tst noset + bne 2f + mov enda,-(sp) + add $516.,(sp) + bic $777,(sp) + mov (sp)+,0f + sys 0;7f +.data +7: sys break; 0:.. +.text + bes 1f + mov 0b,enda + sub $2,enda + clz + rts pc +1: + inc noset +2: + sez + rts pc + +collect: + inc copyf + jsr pc,skipcont + clr *nxf + mov nxf,r2 + add $stksiz,r2 + mov r2,r1 + add $18.,r1 + mov r1,-(sp) + mov nxf,-(sp) + cmp r1,enda + blo 1f + jsr pc,setbrk + beq 7f +1: + clr quote + cmp r2,2(sp) + beq 9f + jsr pc,skipcont + tst nlflg + bne 9f + mov r1,(r2)+ + jsr pc,getchar + cmp r0,$'" + bne 3f + inc quote +2: + jsr pc,getchar +3: + tst nlflg + bne 8f + tst quote + bne 4f + cmp r0,$' / + beq 8f + br 5f +4: + cmp r0,$'" + bne 5f + jsr pc,getchar + cmpb r0,$'" + bne 8f +5: + movb r0,(r1)+ + mov enda,-(sp) + sub $4,(sp) + cmp r1,(sp)+ + blo 2b + jsr pc,setbrk + beq 6f + br 2b +8: + mov r0,ch +6: + clrb (r1)+ + tst nlflg + bne 9f + tst noset + beq 1b +9: + mov (sp),nxf + sub nxf,r2 + sub $stksiz,r2 + asr r2 + mov r2,*nxf + bit $1,r1 + beq 7f + inc r1 +7: + clr copyf + cmp (sp)+,(sp)+ + rts pc diff --git a/source/s7/nroff4.s b/source/s7/nroff4.s new file mode 100644 index 0000000..52f9bce --- /dev/null +++ b/source/s7/nroff4.s @@ -0,0 +1,937 @@ +/ +/ + +/ nroff4 + +text: + inc nflush + cmp nl,$-1 + bne 0f + jsr pc,newln1 + rts pc +0: + clr ulstate + jsr pc,setnel + tst ce + bne nofill + tst fi + beq nofill + tst pendw + bne 7f + tst pendt + bne 8f + inc pendt + tst x + bne 0f +1: + jsr pc,getchar + bmi 1f + cmpb r0,$' / + beq 3f + cmpb r0,tabc + bne 1f +3: + inc x + br 1b +1: + tst nlflg + bne 6f + mov r0,ch + tst x + beq 2f +0: + jsr pc,rbreak + tst nc + bne 5f + tst wch + bne 5f + add x,un + clr x + jsr pc,setnel + tst trap + bne 5f +2: + tst x + bne 0b + tst nlflg + beq 2f +6: + clr nflush + clr x + clr pendt + clr ch + mov $1,r0 + jsr pc,casesp1 + rts pc +8: + tst x + bne 0b +2: + tst spread + bne 1f + tst pendw + bne 0f + tst wch + bne 3f +0: +7: + jsr pc,getword + br 4f +3: + jsr pc,movword + bne 2b + tst nlflg + beq 1f + clr pendt +1: + jsr pc,adjust + tst trap + beq 2b + tst nlflg + beq 5f +4: + clr pendt + tst pendw + bne 5f + dec ul + bge 5f + clr ul +5: + clr nflush + rts pc + +nofill: + tst pendnf + bne 1f + clr over + jsr pc,rbreak + tst trap + bne 3f + tst nlflg + bne 6b + clr fac + clr fmq + mov $1000,nwd +1: + jsr pc,gettchar + bmi 0f + cmpb r0,$'\n + beq 1f + cmpb r0,ohc + beq 1b + cmpb r0,$005 + beq 4f +0: + jsr pc,storeline + br 1b +1: + tst ce + ble 2f + dec ce + mov nel,r0 + asr r0 + bpl 1f + clr r0 +1: + add r0,un +2: + tst nc + bne 0f + mov $037,r0 + jsr pc,storeline +0: + jsr pc,rbreak + dec ul + bpl 3f + clr ul +3: + clr nflush + clr pendnf + rts pc +4: + inc pendnf + clr nflush + jsr pc,flushi + rts pc + +adjust: + mov r2,-(sp) + mov r3,-(sp) + clr r2 + clr r3 + tst ad + beq 1f + mov nwd,r0 + dec r0 + ble 1f + mov nel,r3 + ble 1f + dvd r0,r2 +1: + mov r3,fac + mov r2,fmq + mov (sp)+,r3 + mov (sp)+,r2 + mov $-1,lastl + jsr pc,rbreak1 + clr spread + rts pc + +fill: + mov fmq,r0 +1: + inc r0 + dec nc + cmpb (r2)+,$' + beq 1b + dec r2 + bit $1,totout + beq 2f + inc fac + cmp fac,nwd + blt 1f + inc r0 + br 1f +2: + dec fac + bmi 1f + inc r0 +1: + jsr pc,space + movb (r2),r0 + rts pc + +movword: + mov wordp,r4 + tst nwd + bne 2f +1: + movb (r4)+,r0 + cmp r0,$' + bne 1f + dec wch + jsr pc,width + sub r1,wne + br 1b +1: + dec r4 +2: + cmp wne,nel + ble 1f + tst nwd + beq 2f + cmp nel,$4 + blt 1f + cmp wch,$5 /don't do 4 char words + ble 1f +2: + bit $2,hyf + beq 0f + tst op + bne 0f + clr r0 + jsr pc,findt + dec r1 + ble 1f +0: + jsr pc,hyphen +1: + clr nhyph + mov wch,-(sp) +1: + movb (r4)+,r0 + cmp r0,$'- + bne 2f + movb (r4),r2 + jsr pc,alph2 + bne 2f + bisb $200,(r4) +2: + tst r0 + bpl 2f + bic $!177,r0 + mov r4,r3 + sub $3,r3 + cmp r3,$word + blo 2f + movb (r3),r2 + bic $!177,r2 + jsr pc,alph2 + bne 2f +3: + mov r0,-(sp) + clr r0 + jsr pc,storeline + mov (sp)+,r0 + inc nhyph +2: + jsr pc,width + sub r1,wne + jsr pc,storeline + dec wch + bne 1b + tst nel + blt 1f + inc nwd + tst (sp)+ + clz + rts pc +1: + mov linep,r3 +1: + tst nhyph + bne 2f + tst nwd + beq 3f + cmp wch,(sp) + beq 4f +2: + movb -(r3),r0 + bne 2f + dec nhyph + bne 5f + tst nwd + beq 6f +5: + tst nel + ble 2f +6: + cmpb -1(r3),$'- + beq 3f + movb $'-,(r3) + dec nel + inc ne + br 3f +2: + dec nc + tstb (r3) + beq 1b + jsr pc,width + sub r1,ne + add r1,nel + inc wch + dec r4 + add r1,wne + br 1b +3: + inc nwd +4: + mov r4,wordp + bicb $!177,(r4) + tst (sp)+ + sez + rts pc + + +width: + mov r0,-(sp) + cmpb r0,$014 + bne 0f + mov $1,r1 + br 3f +0: + cmpb r0,$013 + bne 0f + movb eschar,r0 +0: + bic $!177,r0 + cmp r0,ohc + beq 2f + tst r0 + beq 2f + cmp r0,$0177 + beq 2f + cmp r0,$010 + bne 1f + mov $-1,r1 + br 3f +1: + cmp $' ,r0 + bgt 2f + mov $1,r1 + br 3f +2: + clr r1 +3: + mov (sp)+,r0 + rts pc +setwd: + mov column,-(sp) + clr column + mov r2,-(sp) + clr -(sp) + jsr pc,*(r5) + mov r0,r2 +1: + jsr pc,*(r5) + bmi 0f + cmpb r0,r2 + beq 2f +0: + tst nlflg + bne 2f + jsr pc,width + add r1,(sp) + br 1b +2: + mov (sp)+,r0 + jsr pc,setn0 + mov (sp)+,r2 + mov (sp)+,column + tst (r5)+ + rts r5 + +header: +/headin: + clr nls + jsr pc,skipcont + mov $'',r2 + tst op + beq 1f + jsr pc,wbfl +1: + jsr pc,alloc + bne 0f + rts pc +0: + mov nextb,r1 +2: + mov r1,headp + jsr pc,getchar + bmi 3f + cmpb r0,$'\n + beq 2f + mov r0,r2 +1: + jsr pc,getchar + bmi 3f + cmpb r0,$'\n + beq 2f +0: + cmpb r0,r2 + bne 3f + mov $004,r0 +3: + jsr pc,wbf + br 1b +2: + mov $004,r0 + jsr pc,wbf + mov $004,r0 + jsr pc,wbf + clr r0 + jsr pc,wbt + +/headout: + clr -(sp) + mov headp,r2 + jsr r5,headseg; width + mov r0,-(sp) + jsr r5,headseg; width + mov r0,-(sp) + jsr r5,headseg; width + mov r0,-(sp) + tst op + bne 1f + mov po,r0 + jsr pc,space +1: + mov headp,r2 + jsr r5,headseg; putchar + mov llh,r0 + add 6(sp),r0 + sub 2(sp),r0 + asr r0 + sub 4(sp),r0 + mov r0,-(sp) + tst 4(sp) + bne 1f + tst 2(sp) + beq 2f +1: + jsr pc,space +2: + jsr r5,headseg; putchar + mov llh,r0 + sub (sp)+,r0 + sub (sp)+,r0 + sub (sp)+,r0 + sub (sp)+,r0 + add (sp)+,r0 + tst -10(sp) + beq 1f + jsr pc,space + jsr r5,headseg; putchar +1: + jsr pc,newline + cmp nl,hnl + ble 0f + mov nl,hnl +0: + mov headp,r0 + jsr pc,free + rts pc + +headseg: + clr -(sp) +1: + mov r1,-(sp) + mov r2,r1 + jsr pc,rbf0 + jsr pc,incoff + mov r1,r2 + mov (sp)+,r1 + tst r0 + beq 1f + bmi 0f + cmpb r0,$004 + beq 1f + cmpb r0,$'% + beq 2f +0: + jsr pc,*(r5) + add r1,(sp) + br 1b +2: + mov $'%,r0 + jsr pc,findr + mov [flist-vlist](r1),nform + mov pn,r0 + clr r1 + jsr pc,fnumb + add r1,(sp) + br 1b +1: + mov (sp)+,r0 + tst (r5)+ + rts r5 + +space: + jsr r5,nlines;putchar + rts pc + +nlines: + mov r0,-(sp) +1: + dec (sp) + blt 1f + mov $' ,r0 + jsr pc,*(r5) + br 1b +1: + cmp (r5)+,(sp)+ + rts r5 + +decimal: + jsr pc,decml + tst (r5)+ + rts r5 + +decml: + mov r2,-(sp) + mov r3,-(sp) + jsr pc,decml1 + mov (sp)+,r3 + mov (sp)+,r2 + rts pc + +decml1: + mov r1,-(sp) + clr r2 + mov r0,r3 + dvd $10.,r2 + mov r3,-(sp) + mov r2,r0 + beq 1f + jsr pc,decml1 + mov r1,2(sp) +1: + mov (sp)+,r0 + add $'0,r0 + jsr pc,*(r5) + add (sp)+,r1 + rts pc + +roman0: + jsr pc,roman + tst (r5)+ + rts r5 +roman: + tst r0 + beq decml + mov r2,-(sp) + mov r3,-(sp) + cmp ro,$2 + bne 1f + mov $cones,onesp + mov $cfives,fivesp + br 2f +1: + mov $ones,onesp + mov $fives,fivesp +2: + jsr pc,roman1 + mov (sp)+,r3 + mov (sp)+,r2 + rts pc +roman1: + clr r2 + mov r0,r3 + bne .+4 + rts pc + mov r1,-(sp) + dvd $10.,r2 + mov r3,-(sp) + mov r2,r0 + inc onesp + inc fivesp + jsr pc,roman1 + mov r1,2(sp) + dec onesp + dec fivesp + clr r2 + mov (sp)+,r3 + dvd $5.,r2 + cmp r3,$4 + bne 1f + movb *onesp,r0 + jsr pc,*(r5) + add r1,(sp) + tst r2 + beq 2f + inc onesp + movb *onesp,r0 + dec onesp + br 3f +2: + movb *fivesp,r0 +3: + jsr pc,*(r5) + add (sp)+,r1 + rts pc +1: + tst r2 + beq 2f + movb *fivesp,r0 + jsr pc,*(r5) + add r1,(sp) +2: + dec r3 + blt 1f + movb *onesp,r0 + jsr pc,*(r5) + add r1,(sp) + br 2b +1: + mov (sp)+,r1 + rts pc + +abc0: + jsr pc,abc + tst (r5)+ + rts r5 +abc: + mov r2,-(sp) + mov r3,-(sp) + mov r0,r3 + bne 0f + mov $'0,r0 + jsr pc,*(r5) + br 1f +0: + dec r3 + jsr pc,abc1 +1: + mov (sp)+,r3 + mov (sp)+,r2 + rts pc +abc1: + clr r2 + dvd $26.,r2 + mov r3,-(sp) + mov r2,r3 + beq 1f + dec r3 + jsr pc,abc1 +1: + cmp ro,$2 + beq 1f + add $'a,(sp) + br 2f +1: + add $'A,(sp) +2: + mov (sp)+,r0 + jsr pc,*(r5) + rts pc + +fnumb0: + jsr pc,fnumb + tst (r5)+ + rts r5 +fnumb: + mov ro,-(sp) + mov nform,ro + bne 0f + mov (sp),ro + br 1f +0: + dec ro +1: + tst ro + bne 1f + jsr pc,decml + br 2f +1: + cmp ro,$2 + bgt 1f + jsr pc,roman + br 2f +1: + sub $2,ro + jsr pc,abc +2: + mov (sp)+,ro + rts pc + +/wordout: +/ tst index +/ beq 1f +/ mov wch,0f +/ beq 1f +/ mov indid,r0 +/ sys write; word; 0:.. +/ mov indid,r0 +/ sys write; 8f; 1 +/ mov indid,r0 +/ jsr r5,numb; pn +/ mov indid,r0 +/ sys write; 8f; 1 +/ mov nl,char +/ inc char +/ mov indid,r0 +/ jsr r5,numb; char +/ mov indid,r0 +/ sys write; 9f; 1 +/1: +/ rts pc +/8: 011 /tab +/9: <\n\0> +/ .even +/numb: +/ mov r2,-(sp) +/ mov r3,-(sp) +/ mov *(r5)+,r3 +/ mov r0,r1 +/ jsr pc,numb1 +/ mov (sp)+,r3 +/ mov (sp)+,r2 +/ rts r5 +/numb1: +/ clr r2 +/ dvd $10.,r2 +/ mov r3,-(sp) +/ mov r2,r3 +/ beq 1f +/ jsr pc,numb1 +/1: +/ add $'0,(sp) +/ mov (sp)+,char +/ mov r1,r0 +/ sys write; char; 1 +/ rts pc + +setstr: + clr -(sp) + clr -(sp) +0: + jsr pc,get1 + bmi 3f + bic $!177,r0 + cmpb r0,$'\\ + bne 1f +4: + jsr pc,get1 + jsr r5,switch;esctab + cmpb r0,dolc + bne 2f + jsr pc,seta + br 0b +2: + cmpb r0,numc + bne 1f + clr r1 + jsr pc,setn + br 0b +1: + tst 2(sp) + bne 5f + bic $!177,r0 + cmpb r0,$'( + bne 1f + inc 2(sp) + jsr pc,get1 + bic $!177,r0 + cmpb r0,$'\\ + beq 4b +5: + mov r0,-(sp) + jsr pc,get1 + bic $!177,r0 + swab r0 + bis (sp)+,r0 +1: + mov $contab,r1 +1: + mov (r1)+,(sp) + bic $100000,(sp) + cmp r0,(sp) + beq 2f + cmp (r1)+,$-1 + bne 1b + br 3f +2: + mov (r1),(sp) + tst -(r1) + bpl 3f + clr *nxf + jsr pc,pushi + mov (sp),ip +3: + cmp (sp)+,(sp)+ + rts pc + +copys: + inc copyf + jsr pc,skipcont + bne 2f + jsr pc,getchar + bmi 0f + cmpb r0,$'" + bne 0f +1: + jsr pc,getchar + tst nlflg + bne 2f +0: + jsr pc,wbf + br 1b +2: + clr r0 + jsr pc,wbt + clr copyf + rts pc + +setrpt: + inc copyf + inc raw1 + jsr pc,get1 + dec copyf + dec raw1 + mov r0,r1 + jsr pc,get1 + cmpb r0,$006 + beq 1f +0: + movb r0,rchar + movb r1,nspace + cmpb r1,$377 + bne 1f + clr nspace +1: + rts pc + +setfield: + clr npad + mov r1,-(sp) + mov r2,-(sp) + mov r3,-(sp) + mov r4,-(sp) + clr r4 + clr -(sp) + jsr pc,width + sub r1,column /start + mov column,-(sp) + mov $tabtab,r0 +1: + tst (r0) + beq 4f + cmp (sp),(r0)+ + bge 1b + mov -(r0),2(sp) + sub (sp),2(sp) /h + mov $fbuf,r2 +1: + jsr pc,getch1 + bmi 0f + cmpb r0,padc + bne 2f + jsr pc,width + sub r1,column + inc npad + mov r2,-(sp) + add $2,r2 +2: + cmpb r0,fc + beq 3f + cmpb r0,$'\n + bne 0f + mov $012,r4 + clr nlflg + br 3f +0: + movb r0,(r2)+ + cmp r2,$efbuf-6 + blo 1b +3: + tst npad + bne 0f + inc npad + mov r2,-(sp) + add $3,r2 +0: + movb r4,(r2)+ + clrb (r2)+ + jsr pc,width + sub r1,column + mov npad,r1 + asl r1 + add sp,r1 + mov (r1),-(sp) + sub column,(r1) /-s + mov (sp)+,column + add 2(r1),(r1) /h-s + mov (r1),r1 + mov r1,r2 + sxt r0 + div npad,r0 + mov $014,r3 /unpaddable sp + tst r2 + bpl 1f + neg r0 + neg r1 + mov $010,r3 +1: + mov (sp)+,r2 + movb $006,(r2)+ + movb r0,(r2)+ + movb r3,(r2) + tst r1 + beq 0f + incb -1(r2) + dec r1 +0: + tstb -(r2) + bne 0f + movb $377,(r2) +0: + dec npad + bgt 1b + mov $fbuf,cp +4: + cmp (sp)+,(sp)+ + mov (sp)+,r4 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r1 + rts pc diff --git a/source/s7/nroff5.s b/source/s7/nroff5.s new file mode 100644 index 0000000..62f4938 --- /dev/null +++ b/source/s7/nroff5.s @@ -0,0 +1,434 @@ +/ +/ + +/ hyp1 -- driver + +hyphen: + tst hypedf + bne 3f + tst hyf + beq 3f + inc hypedf + mov wordp,r0 + clr nhyph +1: + jsr pc,punct + bne 1f + inc r0 + br 1b +1: + jsr pc,alph + bne 3f + mov r0,wordstart +1: + inc r0 + jsr pc,alph + beq 1b + dec r0 + mov r0,hstart +1: + inc r0 + tstb (r0) + beq 2f + jsr pc,punct + bne 3f + br 1b +2: + mov hstart,wordend + jsr pc,exword + beq 0f + jsr r5,suffix + tst exf + bne 0f + jsr r5,digram +0: + bit $4,hyf + beq 0f + mov wordend,r0 + bicb $!177,-1(r0) +0: + mov wordstart,r0 + bicb $!177,1(r0) + bit $10,hyf + beq 3f + bicb $!177,2(r0) +3: + rts pc + +casehw: + jsr pc,skipcont + bne 2f + mov nexth,r1 + cmp r1,$ehbuf-2 + bhis 3f +1: + jsr pc,getchar + bmi 1f + cmpb r0,$' / + beq 4f + cmpb r0,$012 + beq 1f + movb r0,(r1)+ + cmp r1,$ehbuf-2 + blo 1b + br 3f +1: + clrb (r1)+ + mov r1,nexth + clrb (r1)+ +2: + rts pc +3: + jsr r5,string;hmess + clrb *nexth + br 2b +4: + jsr pc,1b + br casehw +hmess: +.even + +exword: + clr exf + clr -(sp) + mov r1,-(sp) + mov r2,-(sp) + mov r3,-(sp) + mov r4,-(sp) + mov $hbuf,r2 + mov hstart,r0 + cmpb (r0)+,(r0)+ +0: + mov r2,8(sp) + mov wordstart,r1 + tstb (r2) + beq 4f +1: + movb (r2)+,r4 + cmpb r4,$'- + beq 1b + movb (r1)+,r3 +/ tstb r3 +/ bne 2f + cmp r1,r0 + blo 2f + tstb r4 + beq 3f +2: + tstb r4 + bne 2f +/ tstb (r1) + tstb -1(r0) + bne 2f + cmpb r3,$'s + beq 3f +2: + tstb r4 + beq 0b +/ tstb r3 +/ beq 2f + cmp r1,r0 + bhis 2f + cmpb r4,r3 + beq 1b +2: + tstb (r2)+ + bne 2b + br 0b +3: + mov wordstart,r1 + mov 8(sp),r2 + clr 8(sp) + inc exf +1: + tstb (r1)+ + cmpb (r2)+,$'- + bne 0f + bisb $200,-1(r1) + tstb (r2)+ +0: + tstb (r2) + bne 1b +4: + mov (sp)+,r4 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r1 + tst (sp)+ + rts pc + +punct: + tst old + bne 4f + cmpb (r0),$010 + beq 0f + movb (r0),r2 + jsr pc,alph2 + beq 0f + sez + rts pc +0: + clz + rts pc +4: + mov $3f,r2 +1: + cmpb (r0),(r2)+ + beq 2f + tstb (r2) + bne 1b + clz +2: + rts pc +3: < .,()"\'`\0> /should be more +.even +maplow: + cmp r2,$'a + bhis 1f + add $'a-'A,r2 +1: + rts pc + +vowel: + cmpb r2,$'a + beq 1f + cmpb r2,$'e + beq 1f + cmpb r2,$'i + beq 1f + cmpb r2,$'o + beq 1f + cmpb r2,$'u + beq 1f + cmpb r2,$'y + beq 1f + cmpb r2,$'A + beq 1f + cmpb r2,$'E + beq 1f + cmpb r2,$'I + beq 1f + cmpb r2,$'O + beq 1f + cmpb r2,$'U + beq 1f + cmpb r2,$'Y +1: + rts pc + +checkvow: + mov r0,-(sp) +1: + movb -(r0),r2 + jsr pc,vowel + beq 1f + jsr pc,alph + beq 1b + mov (sp)+,r0 + clz + rts r5 +1: + mov (sp)+,r0 + sez + rts r5 + +/ hyp2 -- suffix and digram + +digram: + mov hstart,r0 +1: + jsr pc,alph + bne 3f + jsr pc,vowel + beq 1f + dec r0 + br 1b +1: + mov r0,hstart +1: + movb -(r0),r2 + jsr pc,alph2 + bne 3f + jsr pc,vowel + bne 1b + clr maxdig + mov r0,nhstart +1: + mov $1,r3 + movb -1(r0),r2 + jsr pc,alph2 + beq 2f + movb (r0),r2 + mov $'a,r1 + jsr r5,dilook; bxh + br 4f +2: + movb -2(r0),r2 + mov $xxh,0f + jsr pc,alph2 + beq 2f + mov $bxxh,0f +2: + movb -1(r0),r1 + movb (r0),r2 + jmp 7f +.data +7: + jsr r5,dilook; 0:xxh + jmp 8f +.text +8: +4: + movb (r0)+,r1 + movb (r0),r2 + jsr r5,dilook; xhx + movb (r0),r1 + movb 1(r0),r2 + jsr r5,dilook; hxx + cmp r3,maxdig + blos 2f + mov r3,maxdig + mov r0,maxloc +2: + cmp r0,hstart + blo 1b + mov nhstart,hstart + cmp maxdig,thresh + blo digram + bisb $200,*maxloc + inc nhyph +/ mov maxdig,*octbufp +/ inc octcnt +/ add $2,octbufp + br digram +3: + rts r5 + +dilook: + mov r4,-(sp) + bic $!177,r2 + bic $!177,r1 + jsr pc,maplow + sub $'a,r2 + cmp r2,$'z-'a + bhi 3f + mov r2,r4 + mov r1,r2 + jsr pc,maplow + sub $'a,r2 + cmp r2,$'z-'a + bhi 3f + mov r3,-(sp) + mov r2,r3 + mpy $13.,r3 + clr r2 + clc + ror r4 + adc r2 + add r3,r4 + add (r5)+,r4 + movb (r4),r4 + tst r2 + bne 1f + asr r4 + asr r4 + asr r4 + asr r4 +1: + bic $!17,r4 + mov r4,r3 + mpy (sp)+,r3 + br 4f +3: + clr r3 + tst (r5)+ +4: + mov (sp)+,r4 + rts r5 + +suffix: + mov hstart,r0 + jsr pc,alph + bne 4f + jsr pc,maplow + sub $'a,r2 + asl r2 + mov suftab(r2),-(sp) + bic $!37777,(sp) + beq 3f +1: + mov hstart,r0 + mov (sp),r1 + jsr pc,rdsuf + movb (r1),r3 + beq 3f + bic $!17,r3 + add r3,(sp) + add r1,r3 +2: + movb -(r3),r2 + cmp r3,r1 + ble 2f + bic $!177,r2 + mov r2,-(sp) + movb -(r0),r2 + jsr pc,maplow + cmp r2,(sp)+ + bne 1b + br 2b +2: + mov hstart,r0 + tst (sp)+ + movb (r1),r3 + bic $!17,r3 + add r1,r3 + bitb $200,(r1)+ + bne 1f +2: + dec r0 + cmp r3,r1 + ble 2f + tstb -(r3) + bpl 2b +1: + mov r0,hstart + dec hstart + bitb $100,-1(r1) + bne 2b + jsr r5,checkvow + bne 4f + bisb $200,(r0) + br 2b +2: + bitb $40,-(r1) + bne 4f + jsr pc,exword + bne suffix + br 4f +/ beq suffix +/ br 4f +3: + tst (sp)+ +4: + rts r5 + +rdsuf: + mov r0,-(sp) + mov suff,nfile + mov 4(sp),r1 + jsr pc,rdsufb + mov $sufb,r2 + movb r0,(r2)+ + mov r0,r3 + bic $!17,r3 +1: + dec r3 + blt 1f + inc r1 + jsr pc,rdsufb + movb r0,(r2)+ + br 1b +1: + mov $sufb,r1 + mov (sp)+,r0 + rts pc diff --git a/source/s7/nroff8.s b/source/s7/nroff8.s new file mode 100644 index 0000000..7bf04c9 --- /dev/null +++ b/source/s7/nroff8.s @@ -0,0 +1,256 @@ +/ +/ + +/ nroff8 + +.data +nexth: hbuf +outid: 1 +init: 1 +slow: 1 +nflush: 0 +nev: 2 +ev: 0 +nextb: .=.+2 +evp: elist +pto: 9999. +po: 0 +po1: 0 +npn: 0 +pl: 66. +obufp: obuf +wbufp: wbuf +thresh: 240 +suffil: + +ones: + +fives: + +cones: +cfives: +ttyx: +tmfile: +bfn: + +bfn1: +/indf: + .even +ttyid: 0 +ttyod: 2 +ilistp: +frame: stk +nxf: stk+12. +dolc: 020 +tch: 024 +ifp: ifl +namesiz = 88. +bname: +nextf: +nextf1: .=nextf+namesiz +ename: .=.+2 +fc: 004 + +block: /environment block +totout: .=.+2 +ls: 1 +ls1: 1 +ll: 65. +ll1: 65. +llh: 65. +llh1: 65. +ad: 1 +nms: 1 +ndf: 1 +fi: 1 +cc: '. +c2: '' +ohc: 200 +hyf: 1 +hypedf: 0 +un1: -1 +tabc: 014 +dotc: '. +numc: 034 +tabtab: 8.;16.;24.;32.;40.;48.;56.;64.;72. + 80.;88.;96.;104.;112.;120.;128.;136.;144.;152.;160. + .=.+44. + .even +etabtab: +fac: .=.+2 +fmq: .=.+2 +ne: .=.+2 +nel: .=.+2 +lastl: 0 +jfomod: .=.+2 +wordp: .=.+2 +spaceflg: .=.+2 +linep: .=.+2 +wordend: .=.+2 +wordstart: .=.+2 +wne: .=.+2 +nc: .=.+2 +nb: .=.+2 +lnumber: .=.+2 +numbmod: .=.+2 +nwd: .=.+2 +nn: .=.+2 +ni: .=.+2 +ul: .=.+2 +ce: .=.+2 +rchar: .=.+2 +nspace: .=.+2 +in: .=.+2 +in1: .=.+2 +un: .=.+2 +wch: .=.+2 +x: .=.+2 +/pendb: .=.+2 +pendt: .=.+2 +pendw: .=.+2 +spread: .=.+2 +word: .=.+200. +eword: .=.+2 +stbuf: +linsiz = 600. +line: .=.+linsiz +blockend: .=.+2 +dummy: .=block+1024. + +.bss +bss: +hnl: .=.+2 +iline: .=.+2 +exf: .=.+2 +hbuf: .=.+128. +ehbuf: +ndone: .=.+2 +ttys: .=.+4 +ttym: .=.+2 +nform: .=.+2 +toolate: .=.+2 +pipin: .=.+2 +npad: .=.+2 +padc: .=.+2 +fbuf: .=.+252. +efbuf: .=.+4 +em: .=.+2 +old: .=.+2 +raw: .=.+2 +raw1: .=.+2 +xpc: .=.+2 +copyf: .=.+2 +aplnk: .=.+2 +apptr: .=.+2 +app: .=.+2 +blist: .=.+512. +eblist: .=.+2 +diflg: .=.+2 +ditf: .=.+2 +first: .=.+2 +macerr: .=.+2 +numerr: .=.+2 +newptr: .=.+2 +oldptr: .=.+2 +rbuf: .=.+256. +wbuf: .=.+256. +wbufe: .=.+2 +mflg: .=.+2 +iflg: .=.+2 +pendnf: .=.+2 +over: .=.+2 +temp: .=.+2 +nfo: .=.+2 +ds: .=.+2 +markline: .=.+2 +litlev: .=.+2 +lit: .=.+2 +ioff: .=.+2 +ifl: .=.+8. +ifle: .=.+2 +offl: .=.+10. +noset: .=.+2 +quote: .=.+2 +x.5: .=.+2 +/index: .=.+2 +stdi: .=.+2 +/indid: .=.+2 +sv: .=.+2 +tty: .=.+2 +quiet: .=.+2 +trap: .=.+2 +nls: .=.+2 +elist: .=.+18. +eliste: .=.+2 +rlist: .=.+158. +rliste: .=.+2 +vlist: +pn: .=.+2 +nl: .=.+2 +dnl: .=.+2 +yr: .=.+2 +mo: .=.+2 +dy: .=.+2 +dw: .=.+2 +column: .=.+2 + .=.+144. +inclist: .=.+160. +flist: .=.+160. +nlist: .=.+28. +nliste: .=.+2 +mlist: .=.+28. +mliste: .=.+2 +donef: .=.+2 +ssp: .=.+2 +stop: .=.+2 +nx: .=.+2 +ibf: .=.+2 +ibf1: .=.+2 +skp: .=.+2 +ejf: .=.+2 +/ejf1: .=.+2 +ejl: .=.+2 +ip: .=.+2 +cp: .=.+2 +ap: .=.+2 +op: .=.+2 +tflg: .=.+2 +ocol: .=.+2 +nlflg: .=.+2 +ch: .=.+2 +maxdig: .=.+2 +maxloc: .=.+2 +hstart: .=.+2 +nhstart: .=.+2 +nhyph: .=.+2 +argc: .=.+2 +argp: .=.+2 +ibufp: .=.+2 +xbufp: .=.+2 +xbuf: .=.+514. +eibuf: .=.+2 +xeibuf: .=.+2 +ulstate: .=.+2 +ulc: .=.+2 +bsc: .=.+2 +nsp: .=.+2 +ro: .=.+2 +pfrom: .=.+2 +onesp: .=.+2 +fivesp: .=.+2 +suff: .=.+2 +sufb: .=.+20. +sufbuf: .=.+128. +suftab: .=2*26.+. +ifile: .=.+2 +char: .=.+2 +nfile: .=.+2 +headp: .=.+2 +trtab: .=.+128. +blocksize: .=.+2 +enda: .=.+2 +ybuf: +cbuf: .=.+34. +ilist: +stk: .=.+60. +end: diff --git a/source/s7/roff1.s b/source/s7/roff1.s new file mode 100644 index 0000000..7bb4eed --- /dev/null +++ b/source/s7/roff1.s @@ -0,0 +1,566 @@ +/ +/ + +/ roff1 -- text formatter + + .globl ttyn + nop = 000240 + signal = 48. + +ibuf: /init code in ibuf+obuf + cmp sp,$end + bhi 1f + jsr r5,string; emes1 + sys exit +1: + clr r0 + jsr pc,mesg + sys signal; 1; place + sys signal; 2; place + jsr pc,makebf + sys open; suffil; 0 + bes 1f + mov r0,suff + sys seek; 20; 0 + bes 1f + mov suff,r0 + sys read; suftab; 2*26. +1: + clr r0 + mov (sp)+,argc + dec argc + bne 1f + jmp place +1: + tst (sp)+ + mov (sp),r4 + cmpb (r4)+,$'+ + bne 2f + jsr r5,pnum; pfrom + br 3f +2: + cmpb -1(r4),$'- + bne 2f + cmpb (r4),$'s + bne 0f + inc stop + br 3f +0: + cmpb (r4),$'h + bne 0f + clr slow + br 3f +0: + jsr r5,pnum; pto +3: + dec argc + bgt 1b +2: + mov $nop,get1a + mov $ibuf,ibufp + mov $ibuf,eibuf + mov sp,argp + jsr pc,topbot + clr r0 +1: + movb r0,trtab(r0) + inc r0 + cmp r0,$128. + bne 1b + jsr pc,rbreak + jsr pc,istop + jmp loop +makebf: + sys stat; bfn; stbuf + bec 2f + sys creat; bfn; 400 + bec 1f +2: + incb bfn+8 + cmpb bfn+8,$'z + blos makebf + jmp place +1: + mov r0,ibf + sys write; sufbuf;128. + sys open; bfn;0 + mov r0,ibf1 + rts pc + +string: + mov (r5)+,r1 + mov r1,r2 + mov r1,0f +1: + tstb (r1)+ + bne 1b + sub r2,r1 + mov r1,1f + mov $1,r0 + sys write; 0:..; 1:.. + rts r5 + +emes1: +xxx: +.even +obuf=ibuf+512. +.=ibuf+1024. +loop: + clr nlflg + jsr pc,getchar + cmpb r0,cc + beq 2f + movb r0,ch + jsr pc,text + br loop +2: + jsr pc,control + jsr pc,flushi + br loop + +mesg: + tst r0 + bne setsame + jsr pc,ttyn + movb r0,ttyx+8. + sys stat; ttyx; stbuf + mov stbuf+4,0f + mov 0f,1f + bic $22,0f + sys chmod; ttyx; 0:.. + rts pc +setsame: + sys chmod; ttyx; 1:.. + rts pc + +pnum: + mov r4,ibufp + mov $37777,eibuf + jsr r5,number1; 0 + mov r0,*(r5)+ + clr ch + rts r5 + +flushi: + clr ch + tst nlflg + bne 1f + jsr pc,getchar + br flushi +1: + rts pc + +gettchar: + tst ul + ble getchar + tst ulstate + beq 3f + tst bsc + bgt 1f + tst ulc + bgt 2f + clr ulstate + br 3f +1: + dec bsc + mov $010,r0 + rts pc +2: + dec ulc + mov $'_,r0 + rts pc +3: + jsr pc,getchar + cmp r0,$'0 + blt 1f + cmp r0,$'9 + ble 2f + cmp r0,$'A + blt 1f + cmp r0,$'Z + ble 2f + cmp r0,$'a + blt 1f + cmp r0,$'z + ble 2f +1: + tst ulc + bgt 3f + rts pc +3: + mov $1,ulstate + mov r0,ch + br gettchar +2: + inc bsc + inc ulc + rts pc + +getchar: + mov ch,r0 + beq 1f + clr ch + rts pc +1: + tst nlflg + beq 1f + mov $'\n,r0 + rts pc +1: + jsr pc,get1 + cmp r0,$'\\ + bne 2f + jsr pc,get1 + jsr r5,switch; esctab + br 3f +2: + cmp r0,$033 /prefix + bne 3f + jsr pc,get1 + jsr r5,switch; pfxtab +3: + cmp r0,$'\n + bne 3f + inc nlflg + clr column +3: + mov r1,-(sp) + jsr pc,width + add r1,column + mov (sp)+,r1 + rts pc + +esctab: + .byte 'd, 032 /hlf (down) + .byte 'u, 035 /hlr (up) + .byte 'r, 036 /flr (reverse) + .byte 'x, 016 /SO (extra chars) + .byte 'y, 017 /SI (normal characters) + .byte 'l, 0177 /delete + .byte 't, 011 /hor tab + .byte 'a, 0100 /at sign + .byte 'n, 043 /number sign + .byte '\\, 134 /backslash + .byte 0, 0 + +pfxtab: + .byte '7, 036 /flr + .byte '8, 035 /hlr + .byte '9, 032 /hlf + .byte '4, 030 /brs + .byte '3, 031 /rrs + .byte '1, 026 /set hor tabs + .byte '2, 027 /clr hor tabs + .byte 0,0 +pfxtab1: + +switch: + mov r1,-(sp) + mov (r5)+,r1 +1: + cmpb (r1)+,r0 + beq 1f + tstb (r1)+ + bne 1b + cmp r1,$pfxtab + ble 0f + cmp r1,$pfxtab1 + bgt 0f + mov $037,r0 +0: + mov (sp)+,r1 + rts r5 +1: + movb (r1)+,r0 + mov (sp)+,r1 + rts r5 + +get1: + tst nspace + ble 1f + dec nspace + mov tabc,r0 + rts pc +1: + mov r1,-(sp) +4: + tst ip + beq 5f + jsr pc,rbf + br 6f +5: + tst nx + bne 0f + mov ibufp,r1 + cmp r1,eibuf + bne 3f +0: + mov ifile,r0 + bne 2f +1: + jsr pc,nextfile +2: + clr nx + sys read; ibuf; 512. + bes done + tst r0 + beq 1b + mov $ibuf,r1 + add r1,r0 + mov r0,eibuf +3: + movb (r1)+,r0 + mov r1,ibufp +1: + cmp r0,$011 /tab + bne 6f + mov (sp)+,r1 + mov $tabtab,r0 + inc nspace +1: + tstb (r0) + beq get1 + cmpb column,(r0)+ + bge 1b + movb -(r0),nspace + sub column,nspace + br get1 +6: +get1a: br 7f + tst r0 + beq 4b +7: + mov (sp)+,r1 + rts pc + +nextfile: + mov ifile,r0 + beq 1f + sys close +1: + tst nx + beq 2f + mov $nextf,0f + br 3f +2: + dec argc + blt done + mov *argp,0f + add $2,argp +3: + sys open; 0:..; 0 + bes done + mov r0,ifile + rts pc + +done: + jsr pc,rbreak + jsr pc,eject + jsr pc,flush +place: + sys signal; 2; 1 + mov $1,r0 + jsr pc,mesg + sys unlink; bfn + sys exit + + rts pc + +putchar: + cmp pn,pfrom + blt 2f + clr pfrom + bic $!177,r0 + beq 2f + movb trtab(r0),r0 + cmp r0,$' + bne 1f + inc nsp +2: + rts pc +1: + cmp r0,$'\n + bne 1f + clr nsp + clr ocol + br 2f +1: + tst nsp + beq 2f + tst slow + bne 4f + jsr pc,dsp + cmp nsp,r1 + blt 4f + mov $011,3f+2 + cmp r1,$1 + bgt 8f + mov $040,3f+2 + dec nsp + br 9f +8: + sub r1,nsp +9: + mov r0,-(sp) +3: + mov $011,r0 + jsr pc,pchar1 + mov (sp)+,r0 + br 1b +4: + mov r0,-(sp) + mov $' ,r0 + jsr pc,pchar1 + mov (sp)+,r0 + dec nsp + bne 4b +2: + cmp r0,$026 + blt 2f + cmp r0,$037 + beq 3f + bgt 2f + mov r0,-(sp) + jsr r5, switch; unpfx + cmp (sp)+,r0 + beq 2f + mov r0,-(sp) + mov $033,r0 /prefix + jsr pc,pchar1 + dec ocol + mov (sp)+,r0 +2: +pchar1: + cmp r0,$011 + bne 1f + jsr pc,dsp + br 2f +1: + jsr pc,width +2: + add r1,ocol + movb r0,*obufp + inc obufp + cmp obufp,$obuf+128. + beq flush +3: + rts pc + +dsp: + clr r1 +1: + add $8.,r1 + cmp ocol,r1 + bgt 1b + sub ocol,r1 + bne 2f + mov $8.,r1 +2: + rts pc + + +unpfx: + .byte 032, '9 + .byte 035, '8 + .byte 036, '7 + .byte 031, '3 + .byte 030, '4 + .byte 026, '1 + .byte 027, '2 + .byte 0,0 + +flush: + mov obufp,r0 + sub $obuf,r0 + mov r0,0f + mov $1,r0 + sys write; obuf; 0:0 + mov $obuf,obufp + rts pc + +control: + jsr pc,getchar + mov r0,-(sp) + jsr pc,getchar + swab r0 + bis (sp),r0 + mov $contab,r1 +1: + mov (r1)+,(sp) + bic $100000,(sp) + cmp r0,(sp) + bne 4f + mov (r1),(sp) + tst -(r1) + bpl 3f + jsr pc,flushi + cmp ilistp,$iliste + bgt 5f + mov ip,*ilistp + add $2,ilistp + mov (sp),ip + br 5f +3: + jmp *(sp)+ +4: + cmp (r1)+,$-1 + bne 1b +5: + tst (sp)+ + rts pc + +contab: + ; casead + ; casebp +
      ; casebr + ; casecc + ; casece + ; caseds + ; casefi + ; casein + ; caseix +
    • ; caseli + ; casell + ; casels + ; casena + ; casene + ; casenf + ; casepa + ; casebl + ; casepl + ; casesk + ; casesp + ; casess + ; caseta + ; caseti + ; casetr +
        ; caseul + ; caseun + ; casehe + ; casehx + ; casefo + ; caseeh + ; caseoh + ; caseef + ; caseof + ; casem1 + ; casem2 + ; casem3 + ; casem4 + ; casehc + ; casehy + ; casen1 + ; casen2 + ; casenn + ; caseni + ; casejo + ; casear + ; casero + ; casenx + ; casepo + ; casede + ; caseig + ; casetc + ; casemk +bnames: .=.+100. + -1; -1 diff --git a/source/s7/roff2.s b/source/s7/roff2.s new file mode 100644 index 0000000..1a890ed --- /dev/null +++ b/source/s7/roff2.s @@ -0,0 +1,404 @@ +/ +/ + +/ roff2 -- runoff + +casead: + jsr pc,rbreak + inc ad + rts pc + + rts pc + +casebr: + jsr pc,rbreak + rts pc + +casecc: + jsr pc,skipcont + jsr pc,getchar + cmp r0,$'\n + beq 1f + movb r0,cc +1: + mov r0,ch + rts pc + +casece: + jsr pc,rbreak + jsr r5,number; 0 + jsr pc,min + mov r0,ce + jsr pc,need + rts pc + +caseds: + jsr pc,rbreak + mov $2,ls + rts pc + +casefi: + jsr pc,rbreak + inc fi + rts pc + +casein: + jsr pc,rbreak + jsr r5,number; in + jsr pc,min + mov r0,in + mov r0,un + rts pc + +caseix: + jsr r5,number; in + jsr pc,min + mov r0,in + rts pc + +caseli: + jsr r5,number; 0 + mov r0,-(sp) +1: + dec (sp) + blt 1f + jsr pc,flushi + clr nlflg + jsr pc,text + br 1b +1: + tst (sp)+ + rts pc + +casell: + jsr r5,number; ll + jsr pc,min + mov r0,ll + rts pc + +casels: + jsr pc,rbreak + jsr pc,skipcont + jsr pc,getchar + cmp r0,$'\n + bne 1f + mov ls1,ls + rts pc +1: + mov r0,ch + jsr r5,number1; ls + dec r0 + jsr pc,min + inc r0 + mov r0,ls + mov r0,ls1 + rts pc + +casena: + jsr pc,rbreak + clr ad + rts pc + +casene: + jsr r5,number; 0 + jsr pc,min + jsr pc,need + rts pc + +casenf: + jsr pc,rbreak + clr fi + rts pc + +casepa: +casebp: + jsr pc,rbreak + jsr pc,eject + jsr pc,skipcont + tst nlflg + bne 1f + jsr r5,number; pn + jsr pc,min + mov r0,pn +1: + rts pc + +casebl: + jsr pc,rbreak + jsr r5,number; 0 + jsr pc,min + mov r0,-(sp) + jsr pc,need2 +1: + dec (sp) + blt 1f + mov $' ,r0 + jsr pc,storeline + jsr pc,rbreak + br 1b +1: + tst (sp)+ + rts pc + +casepl: + jsr r5,number; pl + mov r0,pl + jsr pc,topbot + rts pc + +casesk: + jsr r5,number; 0 + jsr pc,min + mov r0,skip + rts pc + +casesp: + jsr pc,rbreak + jsr r5,number; 0 + jsr r5,nlines; nline + rts pc + +casess: + jsr pc,rbreak + mov $1,ls + rts pc + +casetr: + jsr pc,skipcont +1: + jsr pc,getchar + cmp r0,$'\n + beq 1f + mov r0,r1 + jsr pc,getchar + cmp r0,$'\n + bne 2f + mov $' ,r0 +2: + movb r0,trtab(r1) + br 1b +1: + rts pc + +caseta: + mov $tabtab,r1 +1: + jsr r5,number; 0 + jsr pc,min + dec r0 + ble 1f + movb r0,(r1)+ + br 1b +1: + clrb (r1)+ + rts pc + +caseti: + jsr pc,rbreak + jsr r5,number; in + jsr pc,min + mov r0,un + rts pc + +caseul: + jsr r5,number; 0 + jsr pc,min + mov r0,ul + rts pc + +caseun: + jsr r5,number; 0 + sub in,r0 + neg r0 + jsr pc,min + mov r0,un + rts pc + +casehx: + tst hx + beq 1f + clr hx + br 2f +1: + inc hx +2: + jsr pc,topbot + rts pc + +casehe: + jsr r5,headin; ehead + mov ehead,ohead + rts pc +casefo: + jsr r5,headin; efoot + mov efoot,ofoot + rts pc + +caseeh: + jsr r5,headin; ehead + rts pc + +caseoh: + jsr r5,headin; ohead + rts pc + +caseef: + jsr r5,headin; efoot + rts pc + +caseof: + jsr r5,headin; ofoot + rts pc + +casem1: + jsr r5,number; ma1 + jsr pc,min + mov r0,ma1 + br 1f + +casem2: + jsr r5,number; ma2 + jsr pc,min + mov r0,ma2 + br 1f + +casem3: + jsr r5,number; ma3 + jsr pc,min + mov r0,ma3 + br 1f + +casem4: + jsr r5,number; ma4 + jsr pc,min + mov r0,ma4 +1: + jsr pc,topbot + rts pc + +casehc: + jsr pc,skipcont + jsr pc,getchar + cmp r0,$'\n + bne 1f + movb $200,r0 +1: + mov r0,ohc + rts pc + +casetc: + jsr pc,skipcont + jsr pc,getchar + cmp r0,$'\n + bne 1f + mov $' ,r0 +1: + mov r0,tabc + rts pc + +casehy: + jsr r5,number; 0 + mov r0,hyf + rts pc + +casen1: + jsr pc,rbreak + mov $1,numbmod + br 1f +casen2: + jsr pc,rbreak + mov $2,numbmod +1: + clr nn + jsr r5,number; 0 + tst r0 + ble 1f + mov r0,lnumber + rts pc +1: + clr numbmod + rts pc + +casenn: + jsr r5,number; 0 + jsr pc,min + mov r0,nn + rts pc + +caseni: + jsr r5,number; ni + jsr pc,min + mov r0,ni + rts pc + +casejo: + jsr r5,number; 0 + mov r0,jfomod + rts pc + +casear: + clr ro + rts pc + +casero: + inc ro + rts pc + +casenx: + jsr pc,skipcont + jsr r5,getname; nextf + inc nx + jsr pc,nextfile + inc nlflg + clr ip + mov $ilist,ilistp + rts pc + +casepo: + jsr pc,rbreak + jsr r5,number; po + jsr pc,min + mov r0,po + rts pc + +casede: + tst ip + bne 5f + jsr pc,skipcont + jsr r5,getname; bname + clr skp + mov $contab,r1 + clr -(sp) +1: + mov (r1)+,(sp) + beq 2f + bic $100000,(sp) + cmp bname,(sp) + bne 3f +2: + bis $100000,bname + mov nextb,(r1) + mov bname,-(r1) + br 4f +3: + cmp (r1)+,$-1 + bne 1b + inc skp +4: + tst (r1)+ + jsr pc,copyb + tst (sp)+ +5: + rts pc + +caseig: + inc skp + jsr pc,copyb + rts pc + +casemk: + jsr pc,rbreak + mov $002,r0 /stx + jsr pc,putchar + rts pc + diff --git a/source/s7/roff3.s b/source/s7/roff3.s new file mode 100644 index 0000000..8696026 --- /dev/null +++ b/source/s7/roff3.s @@ -0,0 +1,485 @@ +/ +/ + +/roff3 -- runoff + +skipcont: + jsr pc,getchar + mov r0,r2 + jsr pc,alph2 + beq skipcont +1: + cmp $' ,r0 + bne 1f + jsr pc,getchar + br 1b +1: + mov r0,ch + rts pc + +rbreak: + tst nc + ble 4f + clrb *linep + inc totout + mov ls,r0 + dec r0 + jsr r5,nlines; nline + tst pl + beq 4f + cmp nl,bl + bne 1f +3: + jsr pc,eject +1: + tst nl + bne 3f + mov ma1,r0 + jsr r5,nlines; newline + bit $1,pn + bne 1f + jsr r5,headout; ehead + br 2f +1: + jsr r5,headout; ohead +2: + mov ma2,r0 + jsr r5,nlines; newline + dec skip + bge 3b +3: + mov po,r0 + jsr pc,space + jsr pc,donum + mov un,r0 + jsr pc,space + jsr pc,jfo + mov $line,r2 +1: + movb (r2)+,r0 + cmp $' ,r0 + bne 2f + jsr pc,fill + tst nc + bne 1b + br 3f +2: + jsr pc,putchar + dec nc + bgt 1b +3: + jsr pc,newline + clr nwd + clr ne + mov in,un +4: + jsr pc,setnel + rts pc + +jfo: + tst jfomod + beq 1f + mov fac,r0 + add fmq,r0 + beq 1f + clr fac + clr fmq + mov nel,r0 + cmp jfomod,$1 + bne 2f + asr r0 +2: + jsr pc,space +1: + rts pc + +donum: + tst numbmod + beq 2f + dec nn + blt 1f + mov $5,r0 + add ni,r0 + jsr pc,space + rts pc +1: + clr r0 + cmp lnumber,$100. + bge 1f + inc r0 + cmp lnumber,$10. + bge 1f + inc r0 +1: + add ni,r0 + jsr pc,space + mov lnumber,r0 + jsr r5,decimal; putchar + mov $2,r0 + jsr pc,space + inc lnumber +2: + rts pc + + +newline: + mov $'\n,r0 + jsr pc,putchar + inc nl + rts pc + +nline: + mov nl,r0 + beq 1f + cmp r0,bl + beq 1f + jsr pc,newline +1: + rts pc + +number: + jsr pc,skipcont +number1: + mov r1,-(sp) + mov r3,-(sp) + clr r3 + clr -(sp) + clr -(sp) +1: + jsr pc,getchar + cmp r0,$'+ + beq 2f + cmp r0,$'- + beq 2f + sub $'0,r0 + cmp r0,$9. + bhi 3f + inc (sp) + mpy $10.,r3 + add r0,r3 + br 1b +2: + mov r0,2(sp) + br 1b +3: + add $'0,r0 + mov r0,ch + mov (sp)+,r0 + bne 1f + mov $1,r3 + mov r3,r0 +1: + mov (r5)+,r0 + beq 1f + mov (r0),r0 +1: + mov (sp)+,r1 + cmp r1,$'- + bne 1f + sub r3,r0 + br 2f +1: + cmp r1,$'+ + bne 1f + add r3,r0 + br 2f +1: + mov r3,r0 +2: + mov (sp)+,r3 + mov (sp)+,r1 + rts r5 + +eject: + tst pl + beq 1f + tst nl + beq 1f + mov pl,r0 + sub nl,r0 + sub ma4,r0 + sub hx,r0 + jsr r5,nlines; newline + bit $1,pn + bne 2f + jsr r5,headout; efoot + br 3f +2: + jsr r5,headout; ofoot +3: + cmp numbmod,$1 + bne 3f + mov $1,lnumber +3: + mov ma4,r0 + jsr r5,nlines; newline + clr nl + inc pn +1: + cmp pn,pto + ble 1f + jsr pc,flush + jmp place +1: +istop: + tst stop + beq 2f + cmp pn,pfrom + blo 2f + jsr pc,flush +/ mov sp,r1 +/ sys signal; 2; 1f + clr r0 + sys read; garb; 1 +1: +/ mov r1,sp +/ sys signal; 2; place +2: + rts pc + + +storeline: + cmp linep,$line+linsiz + bhis 1f + movb r0,*linep + inc linep + jsr pc,width + add r1,ne + sub r1,nel + inc nc +1: + rts pc + +getword: + mov $word,r2 + clr wne + clr wch + clr nhyph + clr hypedf + mov $word,wordp + clr -(sp) +1: + jsr pc,gettchar + cmp r0,$'\n + beq 3f + cmp r0,ohc + bne 2f + inc hypedf + br 1b +2: + cmp $' ,r0 + bne 2f + jsr pc,storeword + br 1b +2: + mov r0,-(sp) + mov $' ,r0 + jsr pc,storeword + tst spaceflg + beq 2f + jsr pc,storeword + clr spaceflg +2: + mov (sp)+,r0 +2: + jsr pc,storeword + bisb (sp),-1(r2) /add in hyphen + clr (sp) + jsr pc,gettchar + cmp r0,ohc + bne 1f + inc hypedf + jsr pc,gettchar + mov $200,(sp) +1: + cmp $' ,r0 + beq 1f + cmp $'\n,r0 + bne 2b + cmpb -1(r2),$'. + bne 1f + inc spaceflg +1: + add $2,2(sp) +1: + clrb (r2)+ +3: + tst (sp)+ + mov $word,wordp + tst nc + bne 1f + jsr pc,setnel +1: + rts pc + +setnel: + mov $line,linep + mov ll,nel + sub un,nel + clr ne + clr fac + clr fmq + rts pc + +storeword: + jsr pc,width + add r1,wne + inc wch + movb r0,(r2)+ + rts pc + +need: + mov r0,r3 + mpy ls,r3 + mov r3,r0 +need2: + add nl,r0 + cmp r0,bl + ble 1f + jsr pc,eject +1: + rts pc + +min: + tst r0 + bge 1f + clr r0 +1: + rts pc + +getname: + mov r1,-(sp) + mov r2,-(sp) + mov (r5)+,r1 + mov $18.,r2 +1: + jsr pc,getchar + cmp r0,$041 + blt 2f + cmp r0,$0176 + ble 4f +2: + mov r0,ch +3: + clrb (r1)+ + mov (sp)+,r2 + mov (sp)+,r1 + rts r5 +4: + movb r0,(r1)+ + dec r2 + beq 3b + br 1b + +copyb: + mov (r1),r1 + jsr pc,flushi + clr nlflg + mov $1,-(sp) +1: + jsr pc,getchar + cmp r0,$'\n + bne 2f + mov $1,(sp) + clr nlflg + br 4f +2: + cmp r0,$'. + bne 9f + cmp (sp),$1 + bgt 3f + blt 9f + inc (sp) + br 4f +3: + dec r1 + clr r0 + inc (sp) + br 4f +9: + clr (sp) +4: + tst skp + bne 5f + jsr pc,wbf +5: + cmp (sp),$3 + bne 1b + tst (sp)+ + tst skp + bne 6f + mov r1,nextb +6: + rts pc + +popi: + cmp ilistp,$ilist + beq 1f + sub $2,ilistp + mov *ilistp,ip +1: + rts pc + +wbf: + mov r0,char + mov r1,offb + mov ibf,r0 + sys seek; offb:..;0 + mov ibf,r0 + sys write; char;1 + inc r1 + cmp ibf1,ofile + bne 1f + mov $-1,ofile +1: + rts pc +rbf: + mov ip,r1 + mov ibf1,nfile + jsr pc,rdsufb + tstb r0 + bne 2f + jsr pc,popi + rts pc +2: + inc ip + rts pc + +alph: + movb (r0),r2 +alph2: + cmp r2,$'A + blo 1f + cmp r2,$'Z + blos 2f + cmp r2,$'a + blo 1f + cmp r2,$'z + bhi 1f +2: + sez + rts pc +1: + clz + rts pc + +rdsufb: + mov r1,-(sp) + bic $77,r1 + cmp r1,sufoff + bne 1f + cmp nfile,ofile + beq 2f +1: + mov r1,sufoff + mov nfile,ofile + mov nfile,r0 + sys seek; sufoff: -1; 0 + mov nfile,r0 + sys read; sufbuf; 512. +2: + mov (sp),r0 + bic $!77,r0 + movb sufbuf(r0),r0 + mov (sp)+,r1 + rts pc diff --git a/source/s7/roff4.s b/source/s7/roff4.s new file mode 100644 index 0000000..2972597 --- /dev/null +++ b/source/s7/roff4.s @@ -0,0 +1,516 @@ +/ +/ + +/ roff4 -- runoff + +text: +/ inc tottext + clr ulstate + clr wch + clr wne + tst ce + bne nofill + tst fi + beq nofill + jsr pc,getchar +2: + mov r0,ch + cmp $' ,r0 + bne 2f + jsr pc,rbreak +1: + jsr pc,getchar + cmp $' ,r0 + bne 2b + inc un + br 1b +2: + cmp r0,$'\n + bne 2f + jsr pc,rbreak + clr ch + jsr pc,nline + br 4f +2: + tst wch + bne 3f + jsr pc,getword + br 4f +3: + jsr pc,movword + bne 2b + jsr pc,adjust + br 2b +4: + dec ul + bge 1f + clr ul +1: + rts pc + +nofill: + jsr pc,rbreak +1: + jsr pc,gettchar + cmp r0,$'\n + beq 1f + jsr pc,width + add r1,ne + jsr pc,storeline + br 1b +1: + tst ce + ble 2f + dec ce + mov nel,r0 + asr r0 + bpl 1f + clr r0 +1: + add r0,un + tst numbmod + beq 2f + add $2,un +2: + clr fac + clr fmq + mov $1000,nwd + mov $' ,r0 + jsr pc,storeline + jsr pc,rbreak + dec ul + bpl 2f + clr ul +2: + rts pc + +adjust: + mov r2,-(sp) + mov r3,-(sp) + clr r2 + clr r3 + tst ad + beq 1f + mov nwd,r0 + dec r0 + ble 1f + mov nel,r3 + ble 1f + dvd r0,r2 +1: + mov r3,fac + mov r2,fmq + mov (sp)+,r3 + mov (sp)+,r2 + jsr pc,rbreak + rts pc + +fill: + mov fmq,r0 +1: + inc r0 + dec nc + cmpb (r2)+,$' + beq 1b + dec r2 + bit $1,totout + beq 2f + inc fac + cmp fac,nwd + blt 1f + inc r0 + br 1f +2: + dec fac + bmi 1f + inc r0 +1: + jsr pc,space + movb (r2),r0 + rts pc + +movword: + mov wch,wordend + mov wordp,r4 + add r4,wordend + tst nwd + bne 2f +1: + movb (r4)+,r0 + cmp r0,$' + bne 1f + dec wch + jsr pc,width + sub r1,wne + br 1b +1: + dec r4 +2: + cmp wne,nel + ble 1f + cmp nel,$4 + ble 1f + mov ls,r0 + add nl,r0 + cmp r0,bl + bgt 2f + mov ls,r0 + asl r0 + add nl,r0 + cmp r0,bl + bgt 1f +2: + jsr pc,hyphen +1: + clr nhyph + mov wch,-(sp) +1: + movb (r4)+,r0 + cmp r0,$'- + bne 2f + movb (r4),r2 + jsr pc,alph2 + bne 2f + bisb $200,(r4) +2: + tst r0 + bpl 2f + bic $!177,r0 + mov r4,r3 + sub $4,r3 + cmp r3,$word + blo 2f + movb (r3),r2 + bic $!177,r2 + jsr pc,alph2 + beq 3f + cmp nel,$2 + ble 2f +3: + mov r0,-(sp) + clr r0 + jsr pc,storeline + mov (sp)+,r0 + inc nhyph +2: + jsr pc,width + sub r1,wne + jsr pc,storeline + dec wch + bne 1b + tst nel + blt 1f + inc nwd + tst (sp)+ + clz + rts pc +1: + mov linep,r3 +1: + tst nhyph + bne 2f + tst nwd + beq 3f + cmp wch,(sp) + beq 4f +2: + movb -(r3),r0 + bne 2f + dec nhyph + bne 5f + tst nwd + beq 6f +5: + tst nel + ble 2f +6: + cmpb -1(r3),$'- + beq 3f + movb $'-,(r3) + dec nel + inc ne + br 3f +2: + dec nc + tstb (r3) + beq 1b + jsr pc,width + sub r1,ne + add r1,nel + inc wch + dec r4 + add r1,wne + br 1b +3: + inc nwd +4: + mov r4,wordp + bicb $!177,(r4) + cmp r4,$word + bge 4f + 4 +4: + tst (sp)+ + sez + rts pc + +topbot: + mov pl,r0 + bne 1f + clr bl + rts pc +1: + sub ma3,r0 + sub ma4,r0 + sub hx,r0 + mov r0,bl + mov ma1,r0 + add ma2,r0 + add hx,r0 + cmp r0,bl + blt 1f + mov $2,r0 + mov r0,ma1 + mov r0,ma2 + mov r0,ma3 + mov r0,ma4 + mov $66.,pl + br topbot +1: + cmp nl,bl + ble 1f + mov bl,nl +1: + rts pc + +width: + cmp r0,ohc + beq 2f + tst r0 + beq 2f + cmp r0,$0177 + beq 2f + cmp r0,$010 + bne 1f + mov $-1,r1 + rts pc +1: + cmp $' ,r0 + bgt 2f + mov $1,r1 + rts pc +2: + clr r1 + rts pc + +headin: + jsr pc,skipcont + mov nextb,r1 + mov r1,*(r5)+ + jsr pc,gettchar + cmp r0,$'\n + beq 2f + mov r0,r2 +1: + jsr pc,gettchar + cmp r0,$'\n + beq 2f + cmp r0,r2 + bne 3f + clr r0 +3: + jsr pc,wbf + br 1b +2: + clr r0 + jsr pc,wbf + mov r1,nextb + mov ll,llh + rts r5 + +headout: + tst hx + bne 0f + tst (r5)+ + rts r5 +0: + clr -(sp) + mov *(r5),r2 + mov ibf1,nfile + jsr r5,headseg; width + mov r0,-(sp) + jsr r5,headseg; width + mov r0,-(sp) + jsr r5,headseg; width + mov r0,-(sp) + mov po,r0 + jsr pc,space + tst numbmod + beq 1f + mov $5,r0 + add ni,r0 + mov r0,6(sp) +1: + mov *(r5)+,r2 + jsr r5,headseg; putchar + mov llh,r0 + add 6(sp),r0 + sub 2(sp),r0 + asr r0 + sub 4(sp),r0 + bge 1f + clr r0 +1: + mov r0,-(sp) + jsr pc,space + jsr r5,headseg; putchar + mov llh,r0 + sub (sp)+,r0 + sub (sp)+,r0 + sub (sp)+,r0 + sub (sp)+,r0 + add (sp)+,r0 + jsr pc,space + jsr r5,headseg; putchar + jsr pc,newline + rts r5 + +headseg: + clr -(sp) +1: + mov r1,-(sp) + mov r2,r1 + inc r2 + jsr pc,rdsufb + mov (sp)+,r1 + tstb r0 + beq 1f + cmp r0,$'% + beq 2f + jsr pc,*(r5) + add r1,(sp) + br 1b +2: + mov pn,r0 + clr r1 + tst ro + beq 2f + mov $ones,onesp + mov $fives,fivesp + jsr pc,roman + add r1,(sp) + br 1b +2: + jsr pc,decml + add r1,(sp) + br 1b +1: + mov (sp)+,r0 + tst (r5)+ + rts r5 + +space: + jsr r5,nlines; putchar + rts pc + +nlines: + mov r0,-(sp) +1: + dec (sp) + blt 1f + mov $' ,r0 + jsr pc,*(r5) + br 1b +1: + cmp (r5)+,(sp)+ + rts r5 + +decimal: + jsr pc,decml + tst (r5)+ + rts r5 + +decml: + mov r2,-(sp) + mov r3,-(sp) + jsr pc,decml1 + mov (sp)+,r3 + mov (sp)+,r2 + rts pc + +decml1: + mov r1,-(sp) + clr r2 + mov r0,r3 + dvd $10.,r2 + mov r3,-(sp) + mov r2,r0 + beq 1f + jsr pc,decml + mov r1,2(sp) +1: + mov (sp)+,r0 + add $'0,r0 + jsr pc,*(r5) + add (sp)+,r1 + rts pc + +roman: + mov r2,-(sp) + mov r3,-(sp) + jsr pc,roman1 + mov (sp)+,r3 + mov (sp)+,r2 + rts pc +roman1: + clr r2 + mov r0,r3 + bne .+4 + rts pc + mov r1,-(sp) + dvd $10.,r2 + mov r3,-(sp) + mov r2,r0 + inc onesp + inc fivesp + jsr pc,roman + mov r1,2(sp) + dec onesp + dec fivesp + clr r2 + mov (sp)+,r3 + dvd $5.,r2 + cmp r3,$4 + bne 1f + movb *onesp,r0 + jsr pc,*(r5) + add r1,(sp) + tst r2 + beq 2f + inc onesp + movb *onesp,r0 + dec onesp + br 3f +2: + movb *fivesp,r0 +3: + jsr pc,*(r5) + add (sp)+,r1 + rts pc +1: + tst r2 + beq 2f + movb *fivesp,r0 + jsr pc,*(r5) + add r1,(sp) +2: + dec r3 + blt 1f + movb *onesp,r0 + jsr pc,*(r5) + add r1,(sp) + br 2b +1: + mov (sp)+,r1 + rts pc + diff --git a/source/s7/roff5.s b/source/s7/roff5.s new file mode 100644 index 0000000..790a990 --- /dev/null +++ b/source/s7/roff5.s @@ -0,0 +1,294 @@ +/ +/ + +/ hyp1 -- driver + +hyphen: + tst hypedf + bne 3f + tst hyf + beq 3f + inc hypedf + mov wordp,r0 + clr nhyph +1: + jsr pc,punct + bne 1f + inc r0 + br 1b +1: + jsr pc,alph + bne 3f +1: + inc r0 + jsr pc,alph + beq 1b + dec r0 + mov r0,hstart +1: + inc r0 + tstb (r0) + beq 2f + jsr pc,punct + bne 3f + br 1b +2: + jsr r5,suffix + jsr r5,digram +3: + rts pc + + +punct: + tst old + bne 4f + cmpb (r0),$010 + beq 0f + movb (r0),r2 + jsr pc,alph2 + beq 0f + sez + rts pc +0: + clz + rts pc +4: + mov $3f,r2 +1: + cmpb (r0),(r2)+ + beq 2f + tstb (r2) + bne 1b + clz +2: + rts pc +3: < .,()"\'`\0> /should be more +.even +maplow: + cmp r2,$'a + bhis 1f + add $'a-'A,r2 +1: + rts pc + +vowel: + cmp r2,$'a + beq 1f + cmp r2,$'e + beq 1f + cmp r2,$'i + beq 1f + cmp r2,$'o + beq 1f + cmp r2,$'u + beq 1f + cmp r2,$'y +1: + rts pc + +checkvow: + mov r0,-(sp) +1: + movb -(r0),r2 + jsr pc,vowel + beq 1f + jsr pc,alph + beq 1b + mov (sp)+,r0 + clz + rts r5 +1: + mov (sp)+,r0 + sez + rts r5 + +/ hyp2 -- suffix and digram + +digram: + mov hstart,r0 +1: + jsr pc,alph + bne 3f + jsr pc,vowel + beq 1f + dec r0 + br 1b +1: + mov r0,hstart +1: + movb -(r0),r2 + jsr pc,alph2 + bne 3f + jsr pc,vowel + bne 1b + clr maxdig + mov r0,nhstart +1: + mov $1,r3 + movb -1(r0),r2 + jsr pc,alph2 + beq 2f + movb (r0),r2 + mov $'a,r1 + jsr r5,dilook; bxh + br 4f +2: + movb -2(r0),r2 + mov $xxh,0f + jsr pc,alph2 + beq 2f + mov $bxxh,0f +2: + movb -1(r0),r1 + movb (r0),r2 + jsr r5,dilook; 0:xxh +4: + movb (r0)+,r1 + movb (r0),r2 + jsr r5,dilook; xhx + movb (r0),r1 + movb 1(r0),r2 + jsr r5,dilook; hxx + cmp r3,maxdig + blos 2f + mov r3,maxdig + mov r0,maxloc +2: + cmp r0,hstart + blo 1b + mov nhstart,hstart + cmp maxdig,thresh + blo digram + bisb $200,*maxloc + inc nhyph +/ mov maxdig,*octbufp +/ inc octcnt +/ add $2,octbufp + br digram +3: + rts r5 + +dilook: + mov r4,-(sp) + bic $!177,r2 + bic $!177,r1 + jsr pc,maplow + sub $'a,r2 + cmp r2,$'z-'a + bhi 3f + mov r2,r4 + mov r1,r2 + jsr pc,maplow + sub $'a,r2 + cmp r2,$'z-'a + bhi 3f + mov r3,-(sp) + mov r2,r3 + mpy $13.,r3 + clr r2 + clc + ror r4 + adc r2 + add r3,r4 + add (r5)+,r4 + movb (r4),r4 + tst r2 + bne 1f + asr r4 + asr r4 + asr r4 + asr r4 +1: + bic $!17,r4 + mov r4,r3 + mpy (sp)+,r3 + br 4f +3: + clr r3 + tst (r5)+ +4: + mov (sp)+,r4 + rts r5 + +suffix: + mov hstart,r0 + jsr pc,alph + bne 4f + jsr pc,maplow + sub $'a,r2 + asl r2 + mov suftab(r2),-(sp) + bic $!37777,(sp) + beq 3f +1: + mov hstart,r0 + mov (sp),r1 + jsr pc,rdsuf + movb (r1),r3 + beq 3f + bic $!17,r3 + add r3,(sp) + add r1,r3 +2: + movb -(r3),r2 + cmp r3,r1 + ble 2f + bic $!177,r2 + mov r2,-(sp) + movb -(r0),r2 + jsr pc,maplow + cmp r2,(sp)+ + bne 1b + br 2b +2: + mov hstart,r0 + tst (sp)+ + movb (r1),r3 + bic $!17,r3 + add r1,r3 + bitb $200,(r1)+ + bne 1f +2: + dec r0 + cmp r3,r1 + ble 2f + tstb -(r3) + bpl 2b +1: + mov r0,hstart + dec hstart + bitb $100,-1(r1) + bne 2b + jsr r5,checkvow + bne 4f + bisb $200,(r0) + br 2b +2: + bitb $40,-(r1) + beq suffix + br 4f +3: + tst (sp)+ +4: + rts r5 + +rdsuf: + mov r0,-(sp) + mov suff,nfile + mov 4(sp),r1 + jsr pc,rdsufb + mov $sufb,r2 + movb r0,(r2)+ + mov r0,r3 + bic $!17,r3 +1: + dec r3 + blt 1f + inc r1 + jsr pc,rdsufb + movb r0,(r2)+ + br 1b +1: + mov $sufb,r1 + mov (sp)+,r0 + rts pc diff --git a/source/s7/roff7.s b/source/s7/roff7.s new file mode 100644 index 0000000..8b52a04 --- /dev/null +++ b/source/s7/roff7.s @@ -0,0 +1,121 @@ +/ +/ + +/ hyp4 -- digram tables + +bxh: +.byte 060,000,040,000,040,000,000,040,000,000,040,000,040 + +hxx: +.byte 006,042,041,123,021,024,063,042,002,043,021,001,022 +.byte 140,000,200,003,260,006,000,160,007,000,140,000,320 +.byte 220,000,160,005,240,010,000,100,006,000,200,000,320 +.byte 240,000,120,003,140,000,000,240,010,000,220,000,160 +.byte 042,023,041,040,040,022,043,041,030,064,021,000,041 +.byte 100,000,140,000,220,006,000,140,003,000,200,000,000 +.byte 200,000,120,002,220,010,000,160,006,000,140,000,320 +.byte 020,000,020,000,020,000,000,020,000,000,020,000,000 +.byte 043,163,065,044,022,043,104,042,061,146,061,000,007 +.byte 100,000,140,000,040,000,000,100,000,000,120,000,000 +.byte 140,000,040,011,060,004,001,120,003,000,140,000,040 +.byte 200,000,100,000,140,000,000,140,000,000,140,000,240 +.byte 200,000,140,000,160,000,000,220,000,000,140,000,240 +.byte 200,000,140,000,160,000,000,220,000,000,060,000,240 +.byte 021,043,041,121,040,023,042,003,142,042,061,001,022 +.byte 120,000,140,010,140,010,000,140,002,000,120,000,120 +.byte 000,000,000,000,360,000,000,000,000,000,160,000,000 +.byte 100,000,040,005,120,000,000,100,000,000,060,000,140 +.byte 140,040,100,001,240,041,000,242,000,002,140,000,100 +.byte 240,000,120,002,200,000,000,320,007,000,240,000,340 +.byte 101,021,041,020,040,005,042,121,002,021,201,000,020 +.byte 160,000,100,000,140,000,000,160,006,000,220,000,140 +.byte 140,000,020,001,020,000,000,100,001,000,300,000,000 +.byte 000,000,000,000,000,000,000,000,000,000,000,000,000 +.byte 106,041,040,147,040,000,063,041,001,102,160,002,002 +.byte 300,000,040,017,140,017,000,240,000,000,140,000,120 + +bxxh: +.byte 005,150,153,062,062,246,152,127,146,203,310,017,206 +.byte 100,000,120,000,140,000,000,100,000,000,120,000,060 +.byte 100,000,040,000,060,000,000,060,000,000,220,000,040 +.byte 100,000,120,000,200,000,000,100,000,000,140,000,060 +.byte 043,142,046,140,062,147,210,131,046,106,246,017,111 +.byte 060,000,020,000,060,000,000,040,000,000,100,000,000 +.byte 060,000,040,000,040,000,000,040,000,000,100,000,040 +.byte 100,000,100,000,100,000,000,040,000,000,100,000,140 +.byte 066,045,145,140,000,070,377,030,130,103,003,017,006 +.byte 040,000,040,000,020,000,000,040,000,000,100,000,000 +.byte 200,000,020,000,140,000,000,120,000,000,120,000,040 +.byte 120,000,040,000,060,000,000,060,000,000,160,000,040 +.byte 120,000,040,000,120,000,000,040,000,000,160,000,040 +.byte 120,000,020,000,140,000,000,120,000,000,140,000,040 +.byte 051,126,150,140,060,210,146,006,006,165,003,017,244 +.byte 120,000,040,000,160,000,000,140,000,000,060,000,140 +.byte 000,000,000,000,000,000,000,000,000,000,000,000,000 +.byte 140,000,140,000,060,000,000,100,000,000,140,000,020 +.byte 120,000,020,000,060,000,000,060,000,000,060,000,040 +.byte 140,000,020,000,100,000,000,140,000,000,140,000,020 +.byte 070,125,051,162,120,105,126,104,006,044,000,017,052 +.byte 140,000,020,000,140,000,000,060,000,000,060,000,040 +.byte 020,000,000,000,020,000,000,000,000,000,000,000,060 +.byte 140,000,160,000,200,000,000,140,000,000,000,000,240 +.byte 065,042,060,200,000,210,222,146,006,204,220,012,003 +.byte 240,000,020,000,120,000,000,200,000,000,200,000,240 + +xhx: +.byte 032,146,042,107,076,102,042,146,202,050,006,000,051 +.byte 036,377,057,013,057,366,377,057,001,377,057,000,040 +.byte 037,377,020,000,100,022,377,057,362,116,100,000,017 +.byte 057,377,057,031,137,363,377,037,362,270,077,000,117 +.byte 074,142,012,236,076,125,063,165,341,046,047,000,024 +.byte 020,017,075,377,040,001,377,017,001,204,020,000,040 +.byte 057,017,057,340,140,362,314,117,003,302,100,000,057 +.byte 057,357,077,017,100,366,314,057,342,346,037,000,060 +.byte 252,145,072,157,377,165,063,066,164,050,363,000,362 +.byte 000,000,020,000,020,000,000,017,000,000,020,000,000 +.byte 117,017,237,377,200,354,125,110,004,257,000,000,300 +.byte 057,367,054,357,157,216,314,114,217,353,053,000,057 +.byte 077,213,077,077,177,317,377,114,377,352,077,000,076 +.byte 077,213,077,077,157,177,377,054,377,352,117,000,075 +.byte 125,230,065,216,057,066,063,047,345,126,011,000,033 +.byte 057,377,051,360,120,361,273,056,001,256,057,000,060 +.byte 000,000,000,000,000,000,000,000,000,000,000,000,000 +.byte 076,310,056,310,137,174,273,055,335,266,033,000,155 +.byte 077,157,057,360,057,063,042,024,077,206,020,000,040 +.byte 057,037,077,360,100,365,377,037,362,176,050,000,026 +.byte 167,146,042,112,077,110,062,254,366,052,377,000,163 +.byte 060,000,040,000,120,000,377,060,012,000,037,000,257 +.byte 037,232,157,361,040,003,125,010,001,256,000,000,340 +.byte 377,377,377,377,377,377,377,377,377,377,377,017,277 +.byte 253,315,257,216,377,206,146,306,371,126,232,000,004 +.byte 057,012,100,360,160,360,000,040,000,017,157,000,176 + +xxh: +.byte 045,150,154,162,042,246,210,147,152,103,230,017,206 +.byte 100,000,040,000,140,000,000,100,000,021,120,017,060 +.byte 100,000,040,002,140,320,000,060,000,001,220,017,040 +.byte 100,001,120,001,241,000,000,100,000,020,140,017,060 +.byte 023,162,046,142,022,207,210,131,052,106,250,017,110 +.byte 060,000,042,000,160,000,000,040,000,212,100,017,000 +.byte 140,000,040,002,140,000,000,120,000,040,120,017,040 +.byte 100,000,100,000,140,001,021,140,000,046,100,017,140 +.byte 066,045,025,201,020,130,146,030,130,103,025,017,006 +.byte 100,000,040,000,020,000,000,040,000,000,200,017,000 +.byte 200,000,020,001,140,000,000,140,000,000,120,017,040 +.byte 120,026,042,020,140,161,042,143,000,022,162,017,040 +.byte 121,042,060,020,140,200,000,123,000,021,220,017,041 +.byte 121,042,060,120,140,200,000,123,000,021,160,017,041 +.byte 051,126,150,141,060,210,146,066,026,165,026,017,247 +.byte 120,000,040,003,160,000,000,140,000,021,100,017,140 +.byte 000,000,000,000,200,000,000,000,000,000,000,017,000 +.byte 141,023,122,040,160,143,042,142,000,047,143,017,020 +.byte 120,000,040,006,140,060,000,141,000,026,100,017,040 +.byte 140,000,020,007,100,000,000,140,000,001,140,017,020 +.byte 110,125,051,162,120,125,127,104,006,104,000,017,052 +.byte 140,000,040,000,160,000,000,140,000,000,060,017,000 +.byte 040,005,020,000,040,313,231,030,000,140,000,017,056 +.byte 140,000,160,000,200,000,000,140,000,000,000,017,240 +.byte 065,042,060,040,000,206,231,146,006,224,220,017,004 +.byte 240,000,020,000,140,000,000,220,000,000,200,017,141 + +.even diff --git a/source/s7/roff8.s b/source/s7/roff8.s new file mode 100644 index 0000000..80eeb89 --- /dev/null +++ b/source/s7/roff8.s @@ -0,0 +1,126 @@ +/ +/ + +/ roff5 -- runoff + +slow: 1 +pto: 9999. +po: 0 +ls: 1 +ls1: 1 +pn: 1 +ma1: 2 +ma2: 2 +ma3: 1 +ma4: 3 +ll: 65. +llh: 65. +hx: 1 +pl: 66. +ad: 1 +fi: 1 +cc: '. +ohc: 200 +hyf: 1 +hypedf: 0 +obufp: obuf +thresh: 240 +tabc: ' +tabtab: + .byte 8.,16.,24.,32.,40.,48.,56.,64.,72.,0 +suffil: + +ones: + +fives: + +ttyx: +bfn: + .even +ofile: -1 +nextb: 4 +ilistp: ilist + +.bss +old: .=.+2 +stop: .=.+2 +garb: .=.+2 +bname: +nextf: .=.+20. +nx: .=.+2 +ibf: .=.+2 +ibf1: .=.+2 +skp: .=.+2 +ip: .=.+2 +ilist: .=.+8. +iliste: .=.+2 +column: .=.+2 +ocol: .=.+2 +nspace: .=.+2 +fac: .=.+2 +fmq: .=.+2 +nhl: .=.+2 +nel: .=.+2 +jfomod: .=.+2 +wordp: .=.+2 +nlflg: .=.+2 +/tottext: .=.+2 +/totcon: .=.+2 +spaceflg: .=.+2 +ch: .=.+2 +linep: .=.+2 +undflg: .=.+2 +wordend: .=.+2 +maxdig: .=.+2 +maxloc: .=.+2 +totout: .=.+2 +hstart: .=.+2 +nhstart: .=.+2 +nhyph: .=.+2 +argc: .=.+2 +argp: .=.+2 +ibufp: .=.+2 +eibuf: .=.+2 +wne: .=.+2 +nl: .=.+2 +bl: .=.+2 +nc: .=.+2 +ne: .=.+2 +lnumber: .=.+2 +numbmod: .=.+2 +skip: .=.+2 +nwd: .=.+2 +ulstate: .=.+2 +ulc: .=.+2 +bsc: .=.+2 +nsp: .=.+2 +nn: .=.+2 +ro: .=.+2 +pfrom: .=.+2 +ni: .=.+2 +onesp: .=.+2 +fivesp: .=.+2 +ul: .=.+2 +ce: .=.+2 +in: .=.+2 +un: .=.+2 +wch: .=.+2 +suff: .=.+2 +sufb: .=.+20. +sufbuf: .=.+512. +suftab: .=.+[2*26.] +ifile: .=.+2 +char: .=.+2 +nfile: .=.+2 +ehead: .=.+2 +ohead: .=.+2 +efoot: .=.+2 +ofoot: .=.+2 +trtab: .=.+128. +word: .=.+200. + +stbuf: +linsiz = 500. +line: .=.+linsiz +end: + diff --git a/source/s7/run b/source/s7/run new file mode 100644 index 0000000..78f75b6 --- /dev/null +++ b/source/s7/run @@ -0,0 +1,21 @@ +as suftab.s +strip a.out +cmp a.out /usr/lib/suftab +cp a.out /usr/lib/suftab + +as roff?.s +ld -s a.out -l +cmp a.out /usr/bin/roff +cp a.out /usr/bin/roff + +as nroff[1-5].s roff7.s nroff8.s +ld -s -n a.out +cmp a.out /usr/bin/nroff +cp a.out /usr/bin/nroff + +yacc ne.g +cc -s -O -n ne*.c -ly +cmp a.out /usr/bin/neqn +cp a.out /usr/bin/neqn + +rm y.tab.c *.o a.out diff --git a/source/s7/suftab.s b/source/s7/suftab.s new file mode 100644 index 0000000..c4d7b93 --- /dev/null +++ b/source/s7/suftab.s @@ -0,0 +1,561 @@ +/ suftab - suffix table + +suftab: + sufa+20 + 0 + sufc+20 + sufd+20 + sufe+20 + suff+20 + sufg+20 + sufh+20 + sufi+20 + 0 + sufk+20 + sufl+20 + sufm+20 + sufn+20 + sufo+20 + sufp+20 + 0 + sufr+20 + sufs+20 + suft+20 + 0 + 0 + 0 + 0 + sufy+20 + 0 + +sufa: +.byte 2,200+'t /-TA +.byte 2,200+'s /-SA +.byte 3,200+'t,'r /-TRA +.byte 3,200+'d,'r /-DRA +.byte 3,200+'b,'r /-BRA +.byte 2,200+'p /-PA +.byte 2,200+'n /-NA +.byte 2,200+'m /-MA +.byte 3,200+'p,'l /-PLA +.byte 2,200+'l /-LA +.byte 2,200+'k /-KA +.byte 3,200+'t,'h /-THA +.byte 3,200+'s,'h /-SHA +.byte 2,200+'g /-GA +.byte 2,200+'d /-DA +.byte 2,200+'c /-CA +.byte 2,200+'b /-BA +.byte 0 +sufc: +.byte 4,'e,'t,200+'i /ET-IC +.byte 7,'a,'l,200+'i,'s,200+'t,'i /AL-IS-TIC +.byte 4,'s,200+'t,'i /S-TIC +.byte 4,'p,200+'t,'i /P-TIC +.byte 5,200+'l,'y,'t,200+'i /-LYT-IC +.byte 4,'o,'t,200+'i /OT-IC +.byte 5,'a,'n,200+'t,'i /AN-TIC +.byte 4,'n,200+'t,'i /N-TIC +.byte 4,'c,200+'t,'i /C-TIC +.byte 4,'a,'t,200+'i /AT-IC +.byte 4,'h,200+'n,'i /H-NIC +.byte 3,'n,200+'i /N-IC +.byte 3,'m,200+'i /M-IC +.byte 4,'l,200+'l,'i /L-LIC +.byte 4,'b,200+'l,'i /B-LIC +.byte 4,200+'c,'l,'i /-CLIC +.byte 3,'l,200+'i /L-IC +.byte 3,'h,200+'i /H-IC +.byte 3,'f,200+'i /F-IC +.byte 3,'d,200+'i /D-IC +.byte 3,200+'b,'i /-BIC +.byte 3,'a,200+'i /A-IC +.byte 3,200+'m,'a /-MAC +.byte 3,'i,200+'a /I-AC +.byte 0 +sufd: +.byte 4,200+'w,'o,'r /-WORD +.byte 4,200+'l,'o,'r /-LORD +.byte 4,200+'f,'o,'r /-FORD +.byte 4,200+'y,'a,'r /-YARD +.byte 4,200+'w,'a,'r /-WARD +.byte 5,200+'g,'u,'a,'r /-GUARD +.byte 4,200+'t,'a,'r /-TARD +.byte 5,200+'b,'o,'a,'r /-BOARD +.byte 4,200+'n,'a,'r /-NARD +.byte 5,200+'l,'i,'a,'r /-LIARD +.byte 4,200+'i,'a,'r /-IARD +.byte 4,200+'g,'a,'r /-GARD +.byte 4,200+'b,'a,'r /-BARD +.byte 3,200+'r,'o /-ROD +.byte 4,200+'w,'o,'o /-WOOD +.byte 4,200+'h,'o,'o /-HOOD +.byte 4,200+'m,'o,'n /-MOND +.byte 4,200+'t,'e,'n /-TEND +.byte 5,200+'s,'t,'a,'n /-STAND +.byte 4,200+'l,'a,'n /-LAND +.byte 4,200+'h,'a,'n /-HAND +.byte 4,200+'h,'o,'l /-HOLD +.byte 4,200+'f,'o,'l /-FOLD +.byte 5,200+'f,'i,'e,'l /-FIELD +.byte 3,200+'v,'i /-VID +.byte 3,200+'c,'i /-CID +.byte 4,200+'s,'a,'i /-SAID +.byte 4,200+'m,'a,'i /-MAID +.byte 4,'t,200+'t,'e /T-TED +.byte 3,'t,200+'e /T-ED +.byte 4,200+'d,'r,'e /-DRED +.byte 4,200+'c,'r,'e /-CRED +.byte 4,200+'b,'r,'e /-BRED +.byte 5,'v,200+'e,'l,'e /V-ELED +.byte 100+4,'a,'l,200+'e /AL/ED +.byte 140+3,200+'e,'e //EED +.byte 40+5,'e,'d,200+'d,'e /ED-DED +.byte 4,'d,200+'d,'e /D-DED +.byte 40+4,'e,'d,200+'e /ED-ED +.byte 3,'d,200+'e /D-ED +.byte 5,200+'d,'u,'c,'e /-DUCED +.byte 300+2,'e /E/D +.byte 5,200+'s,'t,'e,'a /-STEAD +.byte 4,200+'h,'e,'a /-HEAD +.byte 0 +sufe: +.byte 5,'a,'r,200+'i,'z /AR-IZE +.byte 5,'a,'n,200+'i,'z /AN-IZE +.byte 5,'a,'l,200+'i,'z /AL-IZE +.byte 6,200+'a,'r,'d,200+'i,'z /-ARD-IZE +.byte 5,200+'s,'e,'l,'v /-SELVE +.byte 5,200+'k,'n,'i,'v /-KNIVE +.byte 5,200+'l,'i,'e,'v /-LIEVE +.byte 100+3,200+'q,'u //QUE +.byte 7,'o,'n,200+'t,'i,'n,200+'u /ON-TIN-UE +.byte 3,200+'n,'u /-NUE +.byte 3,200+'d,'u /-DUE +.byte 300+2,'u /U/E +.byte 300+5,'q,'u,'a,'t / QUAT/E +.byte 4,'u,200+'a,'t /U-ATE +.byte 5,200+'s,'t,'a,'t /-STATE +.byte 4,200+'t,'a,'t /-TATE +.byte 6,200+'t,'o,'r,200+'a,'t /-TOR-ATE +.byte 5,'e,'n,200+'a,'t /EN-ATE +.byte 4,200+'m,'a,'t /-MATE +.byte 5,200+'h,'o,'u,'s /-HOUSE +.byte 5,200+'c,'l,'o,'s /-CLOSE +.byte 4,'i,200+'o,'s /I-OSE +.byte 4,200+'w,'i,'s /-WISE +.byte 5,'a,'s,200+'u,'r /AS-URE +.byte 40+4,200+'s,'u,'r /-SURE +.byte 6,200+'f,'i,'g,200+'u,'r /-FIG-URE +.byte 40+3,200+'t,'r /-TRE +.byte 5,200+'s,'t,'o,'r /-STORE +.byte 4,200+'f,'o,'r /-FORE +.byte 5,200+'w,'h,'e,'r /-WHERE +.byte 3,200+'d,'r /-DRE +.byte 3,200+'c,'r /-CRE +.byte 3,200+'b,'r /-BRE +.byte 5,200+'s,'c,'o,'p /-SCOPE +.byte 4,'y,200+'o,'n /Y-ONE +.byte 5,200+'s,'t,'o,'n /-STONE +.byte 5,200+'p,'h,'o,'n /-PHONE +.byte 4,200+'g,'o,'n /-GONE +.byte 4,'e,200+'o,'n /E-ONE +.byte 40+4,200+'e,'n,'n /-ENNE +.byte 40+5,'a,200+'r,'i,'n /A-RINE +.byte 5,200+'c,'l,'i,'n /-CLINE +.byte 4,200+'l,'i,'n /-LINE +.byte 4,200+'s,'o,'m /-SOME +.byte 4,200+'c,'o,'m /-COME +.byte 4,200+'t,'i,'m /-TIME +.byte 3,200+'z,'l /-ZLE +.byte 3,200+'t,'l /-TLE +.byte 3,200+'s,'l /-SLE +.byte 3,200+'p,'l /-PLE +.byte 5,200+'v,'i,'l,'l /-VILLE +.byte 4,'c,'k,200+'l /CK-LE +.byte 3,200+'k,'l /-KLE +.byte 3,200+'g,'l /-GLE +.byte 3,200+'f,'l /-FLE +.byte 3,200+'d,'l /-DLE +.byte 3,200+'c,'l /-CLE +.byte 5,200+'p,'a,200+'b,'l /-PA-BLE +.byte 5,'f,'a,200+'b,'l /FA-BLE +.byte 5,200+'c,'a,200+'b,'l /-CA-BLE +.byte 6,200+'s,'t,'a,'b,'l /-STABLE +.byte 4,200+'a,'b,'l /-ABLE +.byte 3,200+'b,'l /-BLE +.byte 4,200+'d,'a,'l /-DALE +.byte 4,200+'m,'a,'l /-MALE +.byte 4,200+'s,'a,'l /-SALE +.byte 4,200+'l,'i,'k /-LIKE +.byte 340+5,'g,200+'u,'a,'g /-G/UAGE +.byte 5,200+'r,'i,'a,'g /-RIAGE +.byte 5,'e,'r,200+'a,'g /ER-AGE +.byte 4,'m,200+'a,'g /M-AGE +.byte 4,'k,200+'a,'g /K-AGE +.byte 4,'d,200+'a,'g /D-AGE +.byte 4,200+'w,'i,'f /-WIFE +.byte 5,200+'k,'n,'i,'f /-KNYFE +.byte 3,200+'s,'e /-SEE +.byte 4,200+'f,'r,'e /-FREE +.byte 340+2,'e /EE +.byte 4,200+'w,'i,'d /-WIDE +.byte 4,200+'t,'i,'d /-TIDE +.byte 4,200+'s,'i,'d /-SIDE +.byte 6,200+'q,'u,'e,'n,'c /-QUENCE +.byte 7,200+'f,'l,'u,200+'e,'n,'c /-FLU-ENCE +.byte 40+6,'e,'s,200+'e,'n,'c /ES-ENCE +.byte 6,'e,'r,200+'e,'n,'c /ER-ENCE +.byte 5,'i,200+'e,'n,'c /I-ENCE +.byte 40+5,200+'s,'a,'n,'c /-SANCE +.byte 6,'e,'r,200+'a,'n,'c /ER-ANCE +.byte 6,'a,'r,200+'a,'n,'c /AR-ANCE +.byte 5,200+'n,'a,'n,'c /-NANCE +.byte 7,200+'b,'a,'l,200+'a,'n,'c /-BAL-ANCE +.byte 5,'i,200+'a,'n,'c /I-ANCE +.byte 7,200+'j,'u,'s,200+'t,'i,'c /-JUS-TICE +.byte 5,200+'s,'t,'i,'c /-STICE +.byte 5,200+'p,'i,'e,'c /-PIECE +.byte 5,200+'p,'l,'a,'c /-PLACE +.byte 340+1 //E +.byte 0 +suff: +.byte 5,200+'p,'r,'o,'o /-PROOF +.byte 4,200+'s,'e,'l /-SELF +.byte 3,200+'r,'i /-RIF +.byte 40+4,200+'l,'i,'e /-LIEF +.byte 0 +sufg: +.byte 3,200+'l,'o /-LOG +.byte 4,200+'l,'o,'n /-LONG +.byte 5,'t,200+'t,'i,'n /T-TING +.byte 6,200+'s,'t,'r,'i,'n / -STRING +.byte 5,'r,200+'r,'i,'n /R-RING +.byte 5,'p,200+'p,'i,'n /P-PING +.byte 5,'n,200+'n,'i,'n /N-NING +.byte 5,'m,200+'m,'i,'n /M-MING +.byte 5,'l,200+'l,'i,'n / L-LING +.byte 5,200+'z,'l,'i,'n /-ZLING +.byte 5,200+'t,'l,'i,'n /-TLING +.byte 40+5,'s,200+'l,'i,'n /S-LING +.byte 5,'r,200+'l,'i,'n /R-LING +.byte 5,200+'p,'l,'i,'n /-PLING +.byte 6,'n,200+'k,'l,'i,'n /N-KLING +.byte 5,'k,200+'l,'i,'n /K-LING +.byte 5,200+'g,'l,'i,'n /-GLING +.byte 5,200+'f,'l,'i,'n /-FLING +.byte 5,200+'d,'l,'i,'n /-DLING +.byte 5,200+'c,'l,'i,'n /-CLING +.byte 5,200+'b,'l,'i,'n /-BLING +.byte 6,'y,200+'t,'h,'i,'n /Y-THING +.byte 7,'e,'e,'t,'h,200+'i,'n /EETH-ING +.byte 6,'e,200+'t,'h,'i,'n /E-THING +.byte 5,'g,200+'g,'i,'n /G-GING +.byte 5,'d,200+'d,'i,'n /D-DING +.byte 5,'b,200+'b,'i,'n /B-BING +.byte 3,200+'i,'n /-ING +.byte 0 +sufh: +.byte 5,200+'m,'o,'u,'t /-MOUTH +.byte 5,200+'w,'o,'r,'t /-WORTH +.byte 4,200+'w,'i,'t /-WITH +.byte 5,'t,200+'t,'i,'s /T-TISH +.byte 5,'e,200+'t,'i,'s /E-TISH +.byte 5,'p,200+'p,'i,'s /P-PISH +.byte 5,'r,200+'n,'i,'s /R-NISH +.byte 5,'n,200+'n,'i,'s /N-NISH +.byte 5,200+'p,'l,'i,'s /-PLISH +.byte 5,200+'g,'u,'i,'s / -GUISH +.byte 5,200+'g,'l,'i,'s / -GLISH +.byte 5,'b,200+'l,'i,'s / B-LISH +.byte 5,'g,200+'g,'i,'s /G-GISH +.byte 5,'d,200+'d,'i,'s /D-DISH +.byte 3,200+'i,'s /-ISH +.byte 5,200+'g,'r,'a,'p /-GRAPH +.byte 7,200+'b,'o,'r,200+'o,'u,'g /-BOR-OUGH +.byte 5,200+'b,'u,'r,'g /-BURGH +.byte 4,200+'v,'i,'c /-VICH +.byte 3,200+'n,'a /-NAH +.byte 3,200+'l,'a /-LAH +.byte 4,200+'m,'i,200+'a /-MI-AH +.byte 0 +sufi: +.byte 3,200+'t,'r /-TRI +.byte 3,200+'c,'h /-CHI +.byte 200+3,'i,'f /IF-I +.byte 200+3,'e,'d /ED-I +.byte 5,200+'a,'s,'c,'i /-ASCII +.byte 0 +sufk: +.byte 4,200+'w,'o,'r /-WORK +.byte 4,200+'m,'a,'r /-MARK +.byte 4,200+'b,'o,'o /-BOOK +.byte 4,200+'w,'a,'l /-WALK +.byte 5,200+'c,'r,'a,'c /-CRACK +.byte 4,200+'b,'a,'c /-BACK +.byte 0 +sufl: +.byte 3,200+'f,'u /-FUL +.byte 5,'s,200+'w,'e,'l /S-WELL +.byte 4,200+'t,'e,'l /-TELL +.byte 5,200+'s,'h,'e,'l /-SHELL +.byte 5,200+'s,'t,'a,'l /-STALL +.byte 4,200+'s,'t,'a /-STAL +.byte 4,200+'b,'a,'l /-BALL +.byte 3,'v,200+'e /V-EL +.byte 3,'u,200+'e /U-EL +.byte 3,'k,200+'e /K-EL +.byte 4,'t,'h,200+'e /TH-EL +.byte 5,'t,'c,'h,200+'e /TCH-EL +.byte 3,'a,200+'e /A-EL +.byte 140+4,200+'q,'u,'a //QUAL +.byte 40+3,'u,200+'a /U-AL +.byte 3,200+'t,'a /-TAL +.byte 4,'u,'r,200+'a /UR-AL +.byte 40+5,'g,200+'o,200+'n,'a /G-O-NAL +.byte 4,'o,'n,200+'a /ON-AL +.byte 3,200+'n,'a /-NAL +.byte 4,200+'t,'i,'a /-TIAL +.byte 4,200+'s,'i,'a /-SIAL +.byte 40+5,200+'t,'r,'i,200+'a /-TRI-AL +.byte 4,'r,'i,200+'a /RI-AL +.byte 4,200+'n,'i,200+'a /-NI-AL +.byte 4,200+'d,'i,200+'a /-DI-AL +.byte 4,200+'c,'i,'a /-CIAL +.byte 3,200+'g,'a /-GAL +.byte 4,200+'m,'e,'a /-MEAL +/.byte 40+4,200+'r,'e,200+'a /-RE-AL +.byte 40+4,200+'r,'e,'a /-REAL +.byte 6,'c,200+'t,'i,200+'c,'a /C-TI-CAL +.byte 5,200+'s,'i,200+'c,'a /-SI-CAL +.byte 4,200+'i,200+'c,'a /-I-CAL +.byte 3,200+'c,'a /-CAL +.byte 3,200+'b,'a /-BAL +.byte 6,200+'n,'o,200+'m,'i,200+'a /-NO-MI-AL +.byte 0 +sufm: +.byte 3,200+'n,'u /-NUM +.byte 5,'o,200+'r,'i,200+'u /O-RI-UM +.byte 40+3,'i,200+'u /I-UM +.byte 40+3,'e,200+'u /E-UM +.byte 5,'i,'v,200+'i,'s /IV-ISM +.byte 4,200+'t,'i,'s /-TISM +.byte 5,'i,200+'m,'i,'s /I-MISM +.byte 5,'a,'l,200+'i,'s /AL-ISM +.byte 40+4,'e,200+'i,'s /E-ISM +.byte 40+4,'a,200+'i,'s /A-ISM +.byte 4,200+'r,'o,'o /-ROOM +.byte 3,200+'d,'o /-DOM +.byte 3,200+'h,'a /-HAM +.byte 6,200+'a,200+'r,'i,'t,'h /-A-RITHM +.byte 5,200+'r,'i,'t,'h /-RITHM +.byte 0 +sufn: +.byte 4,200+'t,'o,'w /-TOWN +.byte 4,200+'d,'o,'w /-DOWN +.byte 4,200+'t,'u,'r /-TURN +.byte 5,200+'s,'p,'o,'o /-SPOON +.byte 4,200+'n,'o,'o /-NOON +.byte 4,200+'m,'o,'o /-MOON +.byte 11,'a,'l,200+'i,200+'z,'a,200+'t,'i,'o /AL-I-ZA-TION +.byte 7,200+'i,200+'z,'a,200+'t,'i,'o /-I-ZA-TION +.byte 7,'l,200+'i,200+'a,200+'t,'i,'o /L-I-A-TION +.byte 4,200+'t,'i,'o /-TION +.byte 40+5,'s,200+'s,'i,'o /S-SION +.byte 4,200+'s,'i,'o /-SION +.byte 4,'n,200+'i,'o /N-ION +.byte 4,200+'g,'i,'o /-GION +.byte 4,200+'c,'i,'o /-CION +.byte 3,200+'c,'o /-CON +.byte 3,200+'t,'o /-TON +.byte 3,200+'s,'o /-SON +.byte 3,200+'r,'i /-RIN +.byte 3,200+'p,'i /-PIN +.byte 3,200+'n,'i /-NIN +.byte 3,200+'m,'i /-MIN +.byte 3,200+'l,'i /-LIN +.byte 3,200+'k,'i /-KIN +.byte 5,200+'s,'t,'e,'i /-STEIN +.byte 4,200+'t,'a,'i /-TAIN +.byte 5,'g,'h,'t,200+'e /GHT-EN +.byte 5,200+'w,'o,'m,200+'e /-WOM-EN +.byte 3,200+'m,'e /-MEN +.byte 4,'o,200+'k,'e /O-KEN +.byte 3,'k,200+'e /K-EN +.byte 4,200+'t,'e,'e /-TEEN +.byte 4,200+'s,'e,'e /-SEEN +.byte 40+3,200+'s,'a /-SAN +.byte 5,200+'w,'o,'m,200+'a /-WOM-AN +.byte 3,200+'m,'a /-MAN +.byte 4,200+'t,'i,'a /-TIAN +.byte 4,200+'s,'i,'a /-SIAN +.byte 40+4,'e,200+'i,'a /E-IAN +.byte 4,200+'c,'i,'a /-CIAN +.byte 300+3,'i,'a /IA/N +.byte 5,200+'c,'l,'e,'a /-CLEAN +.byte 4,200+'m,'e,'a /-MEAN +.byte 40+3,'e,200+'a /E-AN +.byte 0 +sufo: +.byte 5,200+'m,'a,'c,200+'r /-MAC-RO +.byte 0 +sufp: +.byte 5,200+'g,'r,'o,'u /-GROUP +.byte 2,200+'u /-UP +.byte 4,200+'s,'h,'i /-SHIP +.byte 4,200+'k,'e,'e /-KEEP +.byte 0 +sufr: +.byte 4,200+'z,'a,'r /-ZARR +.byte 300+2,'r /R/R +.byte 3,200+'t,'o /-TOR +.byte 40+3,200+'s,'o /-SOR +.byte 40+4,200+'r,'i,200+'o /-RI-OR +.byte 4,'i,'z,200+'e /IZ-ER +.byte 5,200+'c,'o,'v,200+'e /-COV-ER +.byte 4,'o,200+'v,'e /O-VER +.byte 4,200+'e,'v,200+'e /-EV-ER +.byte 8.,200+'c,'o,'m,200+'p,'u,'t,200+'e /-COM-PUT-ER +.byte 40+5,'u,'s,200+'t,'e /US-TER +.byte 5,'o,'s,'t,200+'e /OST-ER +.byte 40+5,200+'a,'c,200+'t,'e /-AC-TER +.byte 6,200+'w,'r,'i,'t,200+'e /-WRIT-ER +.byte 40+5,'i,'s,200+'t,'e /IS-TER +.byte 40+5,'e,'s,200+'t,'e /ES-TER +.byte 40+5,'a,'s,200+'t,'e /AS-TER +.byte 4,200+'s,'t,'e /-STER +.byte 5,'a,'r,200+'t,'e /AR-TER +.byte 4,'r,'t,200+'e /RT-ER +.byte 40+5,'m,200+'e,200+'t,'e /M-E-TER +.byte 5,200+'w,'a,200+'t,'e /-WA-TER +.byte 3,'r,200+'e /R-ER +.byte 4,'o,'p,200+'e /OP-ER +.byte 5,200+'p,'a,200+'p,'e /-PA-PER +.byte 4,'w,'n,200+'e /WN-ER +.byte 40+4,'s,200+'n,'e /S-NER +.byte 4,'o,'n,200+'e /ON-ER +.byte 4,'r,'m,200+'e /RM-ER +.byte 3,200+'m,'e /-MER +.byte 4,'l,'l,200+'e /LL-ER +.byte 5,'d,200+'d,'l,'e /D-DLER +.byte 4,200+'b,'l,'e /-BLER +.byte 3,'k,200+'e /K-ER +.byte 5,'n,200+'t,'h,'e /N-THER +.byte 6,200+'f,'a,200+'t,'h,'e /-FA-THER +.byte 6,'e,'i,200+'t,'h,'e /EI-THER +.byte 4,'t,'h,200+'e /TH-ER +.byte 4,'s,'h,200+'e /SH-ER +.byte 4,200+'p,'h,'e /-PHER +.byte 4,'c,'h,200+'e /CH-ER +.byte 4,'d,'g,200+'e /DG-ER +.byte 4,'r,'d,200+'e /RD-ER +.byte 6,'o,'u,'n,'d,200+'e /OUND-ER +.byte 4,'l,'d,200+'e /LD-ER +.byte 4,'i,'d,200+'e /ID-ER +.byte 5,200+'d,'u,'c,200+'e /-DUC-ER +.byte 4,'n,'c,200+'e /NC-ER +.byte 100+2, 200+'e / /ER +.byte 3,200+'s,'a /-SAR +.byte 40+6,'a,'c,200+'u,200+'l,'a /AC-U-LAR +.byte 40+6,'e,'c,200+'u,200+'l,'a /EC-U-LAR +.byte 40+6,'i,'c,200+'u,200+'l,'a /IC-U-LAR +.byte 40+6,'e,'g,200+'u,200+'l,'a /EG-U-LAR +.byte 0 +sufs: +.byte 40+4,'u,200+'o,'u /U-OUS +.byte 5,200+'t,'i,'o,'u /-TIOUS +.byte 5,200+'g,'i,'o,'u /-GIOUS +.byte 5,200+'c,'i,'o,'u /-CIOUS +.byte 40+4,'i,200+'o,'u /I-OUS +.byte 5,200+'g,'e,'o,'u /-GEOUS +.byte 5,200+'c,'e,'o,'u /-CEOUS +.byte 4,'e,200+'o,'u /E-OUS +.byte 140+2,200+'u //US +.byte 4,200+'n,'e,'s /-NESS +.byte 4,200+'l,'e,'s /-LESS +.byte 140+2,200+'s //SS +.byte 40+5,'p,200+'o,200+'l,'i /P-O-LIS +.byte 140+2,200+'i //IS +.byte 100+3,200+'x,'e /X/ES +.byte 100+3,200+'s,'e /S/ES +.byte 100+4,'s,'h,200+'e /SH/ES +.byte 100+4,'c,'h,200+'e /CH/ES +.byte 300+1 //S +.byte 0 +suft: +.byte 6,'i,'o,'n,200+'i,'s /ION-IST +.byte 5,'i,'n,200+'i,'s /IN-IST +.byte 5,'a,'l,200+'i,'s /AL-IST +.byte 6,'l,200+'o,200+'g,'i,'s /L-O-GIST +.byte 5,'h,'t,200+'e,'s /HT-EST +.byte 4,'i,200+'e,'s /I-EST +.byte 5,'g,200+'g,'e,'s /G-GEST +.byte 4,'g,200+'e,'s /G-EST +.byte 5,'d,200+'d,'e,'s /D-DEST +.byte 4,'d,200+'e,'s /D-EST +.byte 4,200+'c,'a,'s /-CAST +.byte 5,200+'h,'e,'a,'r /-HEART +.byte 4,200+'f,'o,'o /-FOOT +.byte 3,'i,200+'o /I-OT +.byte 5,200+'f,'r,'o,'n /-FRONT +.byte 5,200+'p,'r,'i,'n /-PRINT +.byte 4,200+'m,'e,'n /-MENT +.byte 5,200+'c,'i,'e,'n /-CIENT +.byte 4,'i,200+'a,'n /I-ANT +.byte 6,200+'w,'r,'i,'g,'h /-WRIGHT +.byte 6,200+'b,'r,'i,'g,'h /-BRIGHT +.byte 6,200+'f,'l,'i,'g,'h /-FLIGHT +.byte 6,200+'w,'e,'i,'g,'h /-WEIGHT +.byte 5,200+'s,'h,'i,'f /-SHIFT +.byte 5,200+'c,'r,'a,'f /-CRAFT +.byte 40+4,'d,'g,200+'e /DG-ET +.byte 4,200+'g,'o,'a /-GOAT +.byte 4,200+'c,'o,'a /-COAT +.byte 4,200+'b,'o,'a /-BOAT +.byte 4,200+'w,'h,'a /-WHAT +.byte 4,200+'c,'u,'i /-CUIT +.byte 0 +sufy: +.byte 40+4,'e,'s,200+'t /ES-TY +.byte 40+5,'q,'u,'i,200+'t /QUI-TY +.byte 4,200+'t,'i,200+'t /-TI-TY +.byte 40+5,'o,'s,200+'i,200+'t /OS-I-TY +.byte 4,200+'s,'i,200+'t /-SI-TY +.byte 5,'i,'n,200+'i,200+'t /IN-I-TY +.byte 4,'n,'i,200+'t /NI-TY +.byte 40+10,'f,'a,200+'b,'i,'l,200+'i,200+'t /FA-BIL-I-TY +.byte 10,200+'c,'a,200+'b,'i,'l,200+'i,200+'t /-CA-BIL-I-TY +.byte 10,200+'p,'a,200+'b,'i,'l,200+'i,200+'t /-PA-BIL-I-TY +.byte 6,200+'b,'i,'l,200+'i,200+'t /-BIL-I-TY +.byte 3,'i,200+'t /I-TY +.byte 4,200+'b,'u,'r /-BUR-Y +.byte 4,200+'t,'o,200+'r /-TO-RY +.byte 5,200+'q,'u,'a,'r /-QUAR-Y +.byte 40+4,'u,200+'a,'r /U-ARY +.byte 7,200+'m,'e,'n,200+'t,'a,200+'r /-MEN-TA-RY +.byte 6,'i,'o,'n,200+'a,'r /ION-ARY +.byte 4,'i,200+'a,'r /I-ARY +.byte 4,'n,200+'o,200+'m /N-O-MY +.byte 3,200+'p,'l /-PLY +.byte 4,'g,200+'g,'l /G-GLY +.byte 5,200+'p,'a,200+'b,'l /-PA-BLY +.byte 5,'f,'a,200+'b,'l /FA-BLY +.byte 5,200+'c,'a,200+'b,'l /-CA-BLY +.byte 4,200+'a,'b,'l /-ABLY +.byte 3,200+'b,'l /-BLY +.byte 2,200+'l /-LY +.byte 3,200+'s,'k /-SKY +.byte 40+6,'g,200+'r,'a,200+'p,'h /G-RA-PHY +.byte 4,'l,200+'o,200+'g /L-O-GY +.byte 2,200+'f /-FY +.byte 3,200+'n,'e /-NEY +.byte 3,200+'l,'e /-LEY +.byte 4,'c,'k,200+'e /CK-EY +.byte 3,200+'k,'e /-KEY +.byte 4,200+'b,'o,'d /-BODY +.byte 5,200+'s,'t,'u,'d /-STUDY +.byte 340+4,'e,'e,'d /EEDY +.byte 2,200+'b /-BY +.byte 3,200+'w,'a /-WAY +.byte 3,200+'d,'a /-DAY +.byte 0 +.even diff --git a/source/salloc/alloc1.s b/source/salloc/alloc1.s new file mode 100644 index 0000000..271a2b9 --- /dev/null +++ b/source/salloc/alloc1.s @@ -0,0 +1,198 @@ +.globl plausible +.globl lookchar +.globl wc +.globl seekchar +.globl putchar +.globl allocate +.globl release +.globl stats +.globl w,r,a,l +.globl bufchar +.globl copy +.globl getbuf +.globl swap +.globl fixct +/ +/ routine to copy the contents of one string +/ to another. +/ +/ mov source,r0 +/ mov dest,r1 +/ jsr pc,copy +/ mov r1,... +/ +/ on return, r1 points to the new string and should +/ be saved. r0 is preserved. +/ +copy: + mov r0,-(sp) + mov r2,-(sp) + mov r3,-(sp) + jsr pc,wc +1: jsr pc,reset + mov w(r0),r2 + sub a(r0),r2 /W-A + mov l(r1),r3 + sub a(r1),r3 /L-A + cmp r2,r3 + ble 1f + jsr pc,release + mov r2,r0 + jsr pc,allocate + mov 4(sp),r0 +/ +1: mov a(r1),w(r1) /rewind w pointer + mov a(r0),-(sp) +/ +4: mov (sp),0f + mov afi,r0 + sys seek;0:.. ;0 /set input pointer + cmp r2,$512. + ble 2f + mov $512.,r3 /# output this time + mov r3,0f + mov r3,3f + add r3,(sp) + sub r3,r2 /# left to output + br 1f +/ +2: mov r2,0f + mov r2,3f + mov r2,r3 + clr r2 +/ +1: mov afi,r0 + sys read;b1;0:.. + bes bad + cmp r0,r3 + bne bad + mov afout,r0 + mov (r1),0f + add r3,(r1) + sys seek;0:.. ;0 + sys write;b1;3:.. + bes bad + tst r2 + bgt 4b + tst (sp)+ + mov 4(sp),r0 /restore r0 +/ +/ fix up read ptr of new string +/ +1: mov r(r0),r2 + sub a(r0),r2 + add a(r1),r2 + mov r2,r(r1) +/ +/ restore and return +/ + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r0 + rts pc +/ +bad: mov $1,r0 + sys write;1f;2f-1f + 4 +1: +2: .even +/ +/ +wc: + mov r1,-(sp) + mov r2,-(sp) + mov r3,-(sp) + clr r3 +1: + cmp r3,nbuf + bge 1f + mov r3,r2 + asl r2 + tst w1(r2) + ble 2f + mov r3,r1 + ashc $9.,r1 + bic $777,r1 + add $b1,r1 + jsr pc,clean +2: + inc r3 + br 1b +1: + jsr pc,whead + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r1 + rts pc +swap: + mov w(r1),-(sp) + mov w(r0),w(r1) + mov (sp),w(r0) + mov r(r1),(sp) + + mov r(r0),r(r1) + mov (sp),r(r0) + mov a(r1),(sp) + mov a(r0),a(r1) + mov (sp),a(r0) + mov l(r1),(sp) + mov l(r0),l(r1) + mov (sp)+,l(r0) + rts pc +/ +/ +/ +/ +/ +/ mov position,r0 +/ mov ...,r1 +/ jsr pc,seekchar +/ +seekchar: + mov r1,-(sp) + mov r0,-(sp) +1: + mov (sp),r0 + add a(r1),r0 + cmp r0,l(r1) + bhi 3f + mov r0,r(r1) + cmp r0,w(r1) + blo 1f + mov r0,w(r1) + br 1f +3: + mov (sp),r0 + jsr pc,allocate + mov 2(sp),r0 + jsr pc,copy + jsr pc,swap + jsr pc,release + mov 2(sp),r1 + br 1b +1: + mov (sp)+,r0 + mov (sp)+,r1 + rts pc +/ +reset: + mov r3,-(sp) + mov r2,-(sp) + clr r3 +1: + cmp r3,nbuf + bge 1f + mov r3,r2 + asl r2 + mov $-1.,w1(r2) + clr b1s(r2) + clr b1e(r2) + clr u1(r2) + inc r3 + br 1b +1: + clr flag + mov (sp)+,r2 + mov (sp)+,r3 + rts pc +/ diff --git a/source/salloc/alloc2.s b/source/salloc/alloc2.s new file mode 100644 index 0000000..298b5b8 --- /dev/null +++ b/source/salloc/alloc2.s @@ -0,0 +1,242 @@ +/ +/ routine to read from disc to a buffer +/ wcing the buffer if necessary +/ mov disc addr,r0 +/ mov buffer addr,r2 +/ jsr pc,getb +/ on return r0 = addr of byte in buffer +/ +getb: + mov r3,-(sp) + mov r1,-(sp) + mov r0,-(sp) + mov r2,r3 + asr r3 + mov r3,r1 + ashc $9.,r1 + bic $777,r1 + add $b1,r1 + tst w1(r2) / w + ble 1f + + jsr pc,clean + +1: mov (sp),r0 + bic $777,r0 /get lowest multiple of 512. + mov r0,0f + mov r0,b1s(r2) /set start + mov afi,r0 + sys seek;0:..;0 + mov r1,0f + sys read;0:..;512. + + mov b1s(r2),b1e(r2) + add $512.,b1e(r2) / set end + clr w1(r2) /clear w + mov (sp)+,r0 + sub b1s(r2),r0 + add r1,r0 / set r0=byte addr in buffer + mov (sp)+,r1 + mov (sp)+,r3 + rts pc +/ +/ +/ routine to wc a buffer +/ mov buffer addr,r2 +/ mov buffer addr+6,r1 beginning of buffer +/ jsr pc,clean +/ +clean: + mov r0,-(sp) + mov b1s(r2),0f + mov afout,r0 + sys seek;0:..;0 + mov r1,0f + sys write;0:..;512. + + clr w1(r2) /clear w + mov (sp)+,r0 + rts pc +/ +/ routine to get buffer addr of byte whose disc +/ addr is in r0 - also returns addr of write +/ flag for buffer in r2 +/ mov disc addr,r0 +/ jsr pc,bufchar +/ mov (r0),r0 for read +/ inc (r2) for write must inc w +/ c-bit set if char not in either buffer +/ +bufchar: + mov r1,-(sp) + mov r3,-(sp) + clr r3 +1: + mov r3,r2 + asl r2 + cmp r0,b1s(r2) + blo 2f + cmp r0,b1e(r2) + bhis 2f + sub b1s(r2),r0 + mov r3,r1 + ashc $9.,r1 + bic $777,r1 + add r1,r0 + add $b1,r0 + mov (sp)+,r3 + mov (sp)+,r1 + clc + rts pc +2: + inc r3 + cmp r3,nbuf + blt 1b + mov (sp)+,r3 + mov (sp)+,r1 + sec + rts pc +/ +/ routine to get a buffer +/ mov disc addr,r0 +/ jsr pc,getbuf +/ mov (r0),r0 (for read) +/ inc (r2) must inc w for w +/ +getbuf: + mov r4,-(sp) + mov r3,-(sp) + mov $2,r3 + clr r2 + mov $1,r4 +1: + cmp r4,nbuf + bge 1f + cmp u1(r3),u1(r2) + bhis 2f + mov r3,r2 +2: + inc r4 + add $2.,r3 + br 1b +1: + mov r2,r3 + jsr pc,getb + add $stats+6.,r3 + inc (r3) + mov (sp)+,r3 + mov (sp)+,r4 + rts pc +/ +/ routine to look at next character from string +/ pointed to by r1; character returned in r0 +/ c-bit set if character not available (end of file) +/ r1 is preserved +/ +/ mov ...,r1 +/ jsr pc,lookchar +/ movb r0,... +/ +lookchar: + mov r2,-(sp) + jsr pc,plausible + cmp w(r1),r(r1) /W,R + blos noch + mov r(r1),r0 + jsr pc,bufchar + bec 2f + jsr pc,getbuf +/ +2: + inc flag + bne 2f + jsr pc,fixct + br 1f +2: + mov flag,u1(r2) +1: + mov (sp)+,r2 + movb (r0),r0 + tst r0 /clears c-bit + rts pc +/ +noch: + mov (sp)+,r2 + clr r0 + sec + rts pc +/ +/ +/ routine to put a character into the string +/ pointed to by r1; character in r0 +/ r0 is preserved; r1 points to the string +/ after return and must be saved. +/ +/ movb ch,r0 +/ mov ...,r1 +/ jsr pc,putchar +/ mov r1,... +/ +putchar: + mov r2,-(sp) + mov r1,-(sp) + mov r0,nchar + jsr pc,plausible +1: cmp w(r1),l(r1) /W,L + blt 3f + mov w(r1),r0 + inc r0 + sub a(r1),r0 /W-A+1 + jsr pc,allocate + mov (sp),r0 + jsr pc,copy + jsr pc,swap + jsr pc,release + mov (sp),r1 +/ +3: mov w(r1),r0 + jsr pc,bufchar + bec 2f + jsr pc,getbuf +2: movb nchar,(r0) + mov $1,w1(r2) + + mov nchar,r0 /to preserve r0 for user + inc w(r1) + inc flag + bne 2f + jsr pc,fixct + br 1f +2: + mov flag,u1(r2) +1: + mov (sp)+,r1 + mov (sp)+,r2 + rts pc + +/ +/ +fixct: + mov r1,-(sp) + mov r3,-(sp) + mov nbuf,r1 + mov nbuf,flag +2: + mov r1,u1(r2) + dec r1 + bge 1f + mov (sp)+,r3 + mov (sp)+,r1 + rts pc +1: + clr r2 + mov $2,r3 +1: + cmp r3,nbuf2 + bge 2b + cmp u1(r3),u1(r2) + blo 2f + mov r3,r2 +2: + add $2,r3 + br 1b diff --git a/source/salloc/alloc3.s b/source/salloc/alloc3.s new file mode 100644 index 0000000..580accd --- /dev/null +++ b/source/salloc/alloc3.s @@ -0,0 +1,432 @@ +.globl flag +.globl b1, w1, u1, b1s, b1e +/ here to allocate a new block +/ +/ +/ mov ...,r0 +/ jsr pc,allocate +/ mov r1,... +/ +/ requested size in bytes in r0 +/ pointer to header of allocated block returned in r1 +/ r0 is preserved +/ +/ convert to words, adjust for header, round up +/ to a power of two +/ +/ each block has a four-word header +/ W - write ptr (also used as link ptr in frlist) +/ R - read ptr +/ A - pointer to head of data +/ L - ptr to (end+1) of data +hsz=1024. +numb=4. +numb2=2*numb +w=0 +r=2 +a=4 +l=6 +/ +allocate: + mov r0,-(sp) + mov r2,-(sp) + mov r3,-(sp) + tst stats + bne 1f + jsr pc,initl +1: + inc stats + dec r0 + bmi 1f + jsr pc,log2 + inc r0 +1: asl r0 + mov r0,-(sp) +/ +/ look on free list for block of required size +/ +zzz: + mov (sp),r0 + tst frlist(r0) + beq xxx +/ +/ found it, allocate and return +/ + mov frlist(r0),r1 + add $hblk,r1 + mov (r1),frlist(r0) + mov a(r1),r0 + mov r0,w(r1) + mov r0,r(r1) + tst (sp)+ + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r0 +/ jsr pc,whead + rts pc +/ +/ no block of required size +/ look for larger block +/ +xxx: + tst (r0)+ + cmp r0,$frend-frlist + bhis www + tst frlist(r0) + bne yyy + br xxx +/ +/ there are no larger blocks; must garbage collect +/ +www: jsr pc,collect + tst r0 + bne zzz +/ +/ out of space +/ + mov $1,r0 + sys write; 1f; 2f-1f + 4 +1: +2: .even +/ +/ split larger block into two smaller pieces and +/ link together as smaller blocks in the free list. +/ +yyy: + mov hblk,r3 /get free header block + beq www + mov frlist(r0),r1 + add $hblk,r1 + mov w(r1),frlist(r0) + mov r3,w(r1) + add $hblk,r3 + mov exp2-2(r0),r2 + add a(r1),r2 + mov w(r3),hblk + mov l(r1),l(r3) + mov r2,l(r1) /L + mov r2,a(r3) + clr w(r3) /W' + mov r1,r2 + sub $hblk,r2 + mov r2,frlist-2(r0) + br zzz +/ +/ +/ here to release a block +/ +/ mov ...,r1 +/ jsr pc,release +/ +/ pointer to block in r1 +/ +release: +/ +/ discover that this is a plausible pointer +/ + mov r0,-(sp) + jsr pc,preposterous +/ +/ find free list index and link block to that entry +/ + inc stats+2 + mov frlist(r0),w(r1) + clr r(r1) + sub $hblk,r1 + mov r1,frlist(r0) + clr r1 /self-defense +/ jsr pc,whead + mov (sp)+,r0 + rts pc +/ +/ +/ jsr pc,collect +/ +/ coalesce free storage by rejoining paired blocks +/ on the free list. +/ zero is returned in r0 if no paired blocks were found. +/ +collect: + mov r1,-(sp) + mov r2,-(sp) + mov r3,-(sp) + mov r4,-(sp) + clr useful + inc stats+4. + clr r0 /start with smallest blocks + /r0 contains frlist index +loop1: mov $frlist,r1 + add r0,r1 +/ +/ try next list member at this level +/ +loop2: mov (r1),r3 + beq advance /list is empty + add $hblk,r3 + tst (r3) /W + beq advance /only one list element +/ +/ calculate address of buddy +/ + mov a(r3),r4 + sub headsz,r4 + bit exp2(r0),r4 + beq 2f + bic exp2(r0),r4 + br 1f +2: bis exp2(r0),r4 +1: add headsz,r4 +/ +/ and search for him +/ +loop3: + cmp a(r3),r4 + beq coal + mov r3,r2 + mov w(r3),r3 + tst r3 + beq nocoal + add $hblk,r3 + br loop3 +/ +/ have found a pair; remove both blocks from list, +/ coalesce them, and put them on next higher list +/ +coal: inc useful + mov w(r3),w(r2) /remove him from list + mov (r1),r2 + add $hblk,r2 + mov r3,r4 + mov w(r2),w(r1) /remove other one + cmp a(r2),a(r4) + bgt 1f + mov r2,-(sp) + mov r4,r2 + mov (sp)+,r4 +1: mov hblk,(r2) + clr r(r2) + mov headsz,a(r2) + mov headsz,l(r2) + sub $hblk,r2 + mov r2,hblk + add exp2(r0),l(r4) /L + clr r(r4) + mov frlist+2(r0),w(r4) + sub $hblk,r4 + mov r4,frlist+2(r0) + br loop2 +/ +/ no buddy found, try next block on this list +/ +nocoal: + mov (r1),r1 + add $hblk,r1 + br loop2 +/ +/ advance to next free list +/ +advance: + tst (r0)+ + cmp r0,$frend-frlist + blo loop1 + mov useful,r0 +/ +/ restore registers and return +/ + mov (sp)+,r4 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,r1 + rts pc +/ +/ routine to find integer part of log2(x) +/ +/ jsr pc,log2 +/ +/ r0 = log2(r0) +/ +log2: + mov $15.,-(sp) + tst r0 + beq 2f +1: + asl r0 + bcs 2f + dec (sp) + br 1b +2: + mov (sp)+,r0 + rts pc +/ + 0 +exp2: + 1;2;4;10;20;40;100;200;400;1000;2000;4000; + 10000;20000;40000;100000 +/ +/ routine to discover whether r1 points to +/ a plausible header - to avoid ruination. +/ +/ r1 is preserved and r0 gets a suitable index for frlist +/ +/ jsr pc,preposterous +/ +plausible: + cmp r1,$strbuf + blo botch + cmp r1,$strend + bhis botch + rts pc +/ +/ +botch: + mov r0,-(sp) + mov $1,r0 + sys write; 1f; 2f-1f + 4 +1: +2: .even +/ +/ +preposterous: + cmp r1,$strbuf + blo botch + cmp r1,$strend + bhis botch + cmp a(r1),headsz /A + blo botch + cmp l(r1),datadr /L + bhi botch + mov l(r1),r0 /L + sub a(r1),r0 /A + mov r0,-(sp) + jsr pc,log2 + asl r0 + cmp exp2(r0),(sp) + bne botch + mov r0,(sp) + mov frlist(r0),r0 +1: beq 1f + add $hblk,r0 + cmp r0,r1 + beq botch + mov (r0),r0 + br 1b +1: mov (sp)+,r0 + rts pc +/ +/ +whead: + mov r0,-(sp) + mov afout,r0 + sys seek;0;0 /write pointer to 0 + sys write;hblk;hsz + mov (sp)+,r0 + rts pc +/ +datasz: 16384. +headsz: hsz +nbuf: numb +nbuf2: numb2 + +b1s: .=.+numb2 +b1e: .=.+ numb2 +w1: .=.+ numb2 +u1: .=.+ numb2 +b1 = . +/ +initl: + mov r0,-(sp) + mov r2,-(sp) + sys open;asmem; 1 /open for write + bec 2f + sys creat;asmem; 606 + bes err2 +2: + mov r0,afout +1: + sys open; asmem; 0 /open for read + bes err2 + mov r0,afi +1: + br gargs +/ +err2: + mov $1,r0 + sys write; 1f; 2f-1f + 4 +1: +2: +asmem: + + .even +/ +gargs: + mov $headers,r2 + mov r2,r0 + sub $hblk,r0 + mov r0,hblk +1: + add $8,r0 + mov r0,(r2) + add $8,r2 + cmp r2,$strend-8. + blo 1b + clr -8(r2) +/ + mov headsz,datadr + add datasz,datadr +/ + mov $frlist,r0 +1: clr (r0)+ + cmp r0,$frend + blo 1b + + mov hblk,r2 + add $hblk,r2 + mov (r2),hblk + clr w(r2) + mov headsz,a(r2) + mov datadr,l(r2) + mov datasz,r0 + jsr pc,log2 + asl r0 + cmp r0,$frend-frlist + blo 9f; 4; 9: + sub $hblk,r2 + mov r2,frlist(r0) +/ +/ install plausible pointers to make octal dumps look ok +/ + mov $hblk,r1 +1: mov (r1),r1 + beq 1f + add $hblk,r1 + mov headsz,a(r1) + mov headsz,l(r1) + br 1b +/ +1: mov afout,r0 + sys write;hblk;hsz + jsr pc,reset + mov (sp)+,r2 + mov (sp)+,r0 + rts pc +. = b1 + [512.*numb] +/ +.bss + +flag: .=.+2 +stats: .=.+18. +useful: .=.+2 +afi: .=.+2 +afout: .=.+2 +datadr: .=.+2 +hblk: .=.+2 /must remain here - pointer to free header +frlist: .=hblk+34. +frend: +headers: +strbuf: .=hblk+hsz +strend: +nchar: .=.+2 +end: diff --git a/source/salloc/altch.s b/source/salloc/altch.s new file mode 100644 index 0000000..dc0577b --- /dev/null +++ b/source/salloc/altch.s @@ -0,0 +1,63 @@ +.globl alterchar +.globl plausible +.globl stats +.globl allocate, release +.globl copy +.globl bufchar, getbuf +.globl swap +.globl w, r, a, l +.globl w1, flag, u1, fixct +/ +/ routine to rewrite the character pointer to by +/ read pointer. The read pointer is advanced. +/ the string is extended if necessary. +/ there is no error return. +/ +/ movb ch,r0 +/ mov ...,r1 +/ jsr pc,alterchar +/ mov r1,... +/ +alterchar: + mov r2,-(sp) + mov r1,-(sp) + mov r0,nchar + jsr pc,plausible + inc stats+8. +1: cmp r(r1),l(r1) /W,L + blt 3f + mov l(r1),r0 + inc r0 + sub a(r1),r0 /W-A+1 + jsr pc,allocate + mov (sp),r0 + jsr pc,copy + jsr pc,swap + jsr pc,release + mov (sp),r1 +/ +3: mov r(r1),r0 + jsr pc,bufchar + bec 2f + jsr pc,getbuf + +2: movb nchar,(r0) + mov nchar,r0 /to preserve r0 for user + inc r(r1) + mov $1,w1(r2) + cmp r(r1),w(r1) + ble 3f + mov r(r1),w(r1) +3: + inc flag + bne 1f + jsr pc,fixct + br 2f +1: + mov flag,u1(r2) +2: + mov (sp)+,r1 + mov (sp)+,r2 + rts pc +/ +nchar: .=.+2 diff --git a/source/salloc/bsp.s b/source/salloc/bsp.s new file mode 100644 index 0000000..e539cb6 --- /dev/null +++ b/source/salloc/bsp.s @@ -0,0 +1,20 @@ +.globl backspace +.globl lookchar +.globl w, r, a, l +/ +/ routine to read a string backwards +/ the read pointer is decremented before reading +/ +/ mov ...,r1 +/ jsr pc,backspace +/ mov r0,... +/ +backspace: + cmp a(r1),r(r1) + bhis nochc + dec r(r1) + jsr pc,lookchar + rts pc +nochc: clr r0 + sec + rts pc diff --git a/source/salloc/bword.s b/source/salloc/bword.s new file mode 100644 index 0000000..4d448f6 --- /dev/null +++ b/source/salloc/bword.s @@ -0,0 +1,31 @@ +.globl backword +.globl lookchar +.globl w, r, a, l +/ +/ +/ routine to get words backwards from string +/ +/ mov ...,r1 +/ jsr pc,backword +/ mov r0,... +/ +backword: + cmp a(r1),r(r1) + bhis nochw + dec r(r1) + jsr pc,lookchar + movb r0,nchar+1 + cmp a(r1),r(r1) + bhis nochw + dec r(r1) + jsr pc,lookchar + movb r0,nchar + mov nchar,r0 + rts pc +/ +nochw: + clr r0 + sec + rts pc +/ +nchar: .=.+2 diff --git a/source/salloc/getch.s b/source/salloc/getch.s new file mode 100644 index 0000000..72e994d --- /dev/null +++ b/source/salloc/getch.s @@ -0,0 +1,19 @@ +.globl getchar +.globl lookchar +.globl w, r, a, l +/ +/ +/ routine to read next character from string +/ pointer to by r1; character returned in r0 +/ c-bit set if character not availiable (eof) +/ +/ mov ...,r1 +/ jsr pc,getchar +/ movb r0,... +/ +getchar: + jsr pc,lookchar + bes 1f + inc r(r1) + tst r0 +1: rts pc diff --git a/source/salloc/getwd.s b/source/salloc/getwd.s new file mode 100644 index 0000000..4023ec8 --- /dev/null +++ b/source/salloc/getwd.s @@ -0,0 +1,56 @@ +.globl getword +.globl putword +.globl lookword +.globl alterword +.globl alterchar +.globl putchar +.globl lookchar +.globl w, r, a, l +/ +/ routine to put a word onto the string +/ mov ...,r1 +/ mov ...,r0 +/ jsr pc,putword +putword: + jsr pc,putchar + swab r0 + jsr pc,putchar + swab r0 + rts pc +/ +/ +/ routine to look at a word from the string +/ mov ...,r1 +/ jsr pc,lookword +/ mov r0,... +lookword: + jsr pc,lookchar + bes 1f + movb r0,nchar + inc r(r1) + jsr pc,lookchar + bes 1f + movb r0,nchar+1 + dec r(r1) + mov nchar,r0 +1: rts pc +/ +/ +/ routine to get a word from the strng +/ +getword: + jsr pc,lookword + bes 1f + add $2,r(r1) +1: rts pc +/ +/ +/ routine to alter a word in the string +/ +alterword: + jsr pc,alterchar + swab r0 + jsr pc,alterchar + swab r0 + rts pc +nchar: .=.+2 diff --git a/source/salloc/length.s b/source/salloc/length.s new file mode 100644 index 0000000..b70d89c --- /dev/null +++ b/source/salloc/length.s @@ -0,0 +1,27 @@ +.globl length +.globl position +.globl w, r, a, l +/ +/ +/ routine to return the length of a string +/ +/ mov ...,r1 +/ jsr pc,length +/ mov r0,... +/ +length: + mov w(r1),r0 + sub a(r1),r0 + rts pc +/ +/ +/ routine to return the read pointer position +/ +/ mov ...,r1 +/ jsr pc,position +/ mov r0,... +/ +position: + mov r(r1),r0 + sub a(r1),r0 + rts pc diff --git a/source/salloc/rewind.s b/source/salloc/rewind.s new file mode 100644 index 0000000..07467d1 --- /dev/null +++ b/source/salloc/rewind.s @@ -0,0 +1,36 @@ +.globl rewind +.globl create +.globl fsfile +.globl w, r, a, l +/ +/ +/ routine to rewind read pointer of string +/ pointed to by r1 +/ +/ mov ...,r1 +/ jsr pc,rewind +/ +rewind: + mov a(r1),r(r1) + rts pc +/ +/ routine to rewind write pointer of string +/ pointed to by r1 +/ +/ mov ...,r1 +/ jsr pc,create +/ +create: + mov a(r1),w(r1) + mov a(r1),r(r1) + rts pc +/ +/ +/ routine to copy read pointer of string to end of string +/ +/ mov ...,r1 +/ jsr pc,fsfile +/ +fsfile: + mov w(r1),r(r1) + rts pc diff --git a/source/salloc/run b/source/salloc/run new file mode 100644 index 0000000..751b9ed --- /dev/null +++ b/source/salloc/run @@ -0,0 +1,11 @@ +as alloc?.s; mv a.out alloc.o +as altch.s; mv a.out altch.o +as bsp.s; mv a.out bsp.o +as bword.s; mv a.out bword.o +as getch.s; mv a.out getch.o +as getwd.s; mv a.out getwd.o +as length.s; mv a.out length.o +as rewind.s; mv a.out rewind.o +as zero.s; mv a.out zero.o +ar r /lib/libs.a *.o +rm *.o diff --git a/source/salloc/zero.s b/source/salloc/zero.s new file mode 100644 index 0000000..d4824df --- /dev/null +++ b/source/salloc/zero.s @@ -0,0 +1,21 @@ +.globl zero +.globl putchar +.globl w, r, a, l +/ +/ +/ routine to zero a string +/ +/ mov ...,r1 +/ jsr pc,zero +/ +zero: + mov r0,-(sp) + mov a(r1),w(r1) + clrb r0 +1: cmp w(r1),l(r1) + bhis 1f + jsr pc,putchar + br 1b +1: mov a(r1),w(r1) + mov (sp)+,r0 + rts pc diff --git a/source/sno/run b/source/sno/run new file mode 100644 index 0000000..bd0a9d0 --- /dev/null +++ b/source/sno/run @@ -0,0 +1,4 @@ +cc -s -O sno?.c +cmp a.out /usr/bin/sno +cp a.out /usr/bin/sno +rm *.o a.out diff --git a/source/sno/sno.h b/source/sno/sno.h new file mode 100644 index 0000000..b3ec624 --- /dev/null +++ b/source/sno/sno.h @@ -0,0 +1,21 @@ +struct node { + struct node *p1; + struct node *p2; + char typ; + char ch; +}; + +int freesize; +struct node *lookf; +struct node *looks; +struct node *lookend; +struct node *lookstart; +struct node *lookdef; +struct node *lookret; +struct node *lookfret; +int cfail; +int rfail; +struct node *freelist; +struct node *namelist; +int lc; +struct node *schar; diff --git a/source/sno/sno1.c b/source/sno/sno1.c new file mode 100644 index 0000000..8de0093 --- /dev/null +++ b/source/sno/sno1.c @@ -0,0 +1,468 @@ +#include "sno.h" + +/* + * Snobol III + */ + + +int freesize; +struct node *freespace &end; +struct node *freelist 0; +int *fault -1; + +mes(s) { + sysput(strstr(s)); +} + +init(s, t) { + register struct node *a, *b; + + a = strstr(s); + b = look(a); + delete(a); + b->typ = t; + return(b); +} + +main(argc, argv) +char *argv[]; +{ + extern fin, fout; + register struct node *a, *b, *c; + + if(argc > 1) { + fin = open(argv[1], 0); + if(fin < 0) { + mes("cannot open input"); + exit(); + } + } + fout = dup(1); + lookf = init("f", 0); + looks = init("s", 0); + lookend = init("end", 0); + lookstart = init("start", 0); + lookdef = init("define", 0); + lookret = init("return", 0); + lookfret = init("freturn", 0); + init("syspit", 3); + init("syspot", 4); + a = c = compile(); + while (lookend->typ != 2) { + a->p1 = b = compile(); + a = b; + } + cfail = 1; + a->p1 = 0; + if (lookstart->typ == 2) + c = lookstart->p2; + while (c=execute(c)); + flush(); +} + +syspit() { + extern fin; + register struct node *b, *c, *d; + int a; + + if ((a=getchar())=='\n') + return(0); + b = c = alloc(); + while(a != '\n') { + c->p1 = d = alloc(); + c = d; + l: + c->ch = a; + if(a == '\0') { + if(fin) { + close(fin); + fin = 0; + a = getchar(); + goto l; + } + rfail = 1; + break; + } + a = getchar(); + } + b->p2 = c; + if(rfail) { + delete(b); + b = 0; + } + return(b); +} + +syspot(string) +struct node *string; +{ + register struct node *a, *b, *s; + + s = string; + if (s!=0) { + a = s; + b = s->p2; + while(a != b) { + a = a->p1; + putchar(a->ch); + } + } + putchar('\n'); +} + +strstr(s) +char s[]; +{ + int c; + register struct node *e, *f, *d; + + d = f = alloc(); + while ((c = *s++)!='\0') { + (e=alloc())->ch = c; + f->p1 = e; + f = e; + } + d->p2 = e; + return(d); +} + +class(c) { + switch (c) { + case ')': return(1); + case '(': return(2); + case '\t': + case ' ': return(3); + case '+': return(4); + case '-': return(5); + case '*': return(6); + case '/': return(7); + case '$': return(8); + case '"': + case '\'': return(9); + case '=': return(10); + case ',': return(11); + } + return(0); +} + +alloc() { + register struct node *f; + register int i; + extern fout; + + if (freelist==0) { + if (--freesize < 20) { + if ((i=sbrk(1200)) == -1) { + flush(); + write (fout, "Out of free space\n", 18); + exit(); + } + freesize =+ 200; + } + return(freespace++); + } + f = freelist; + freelist = freelist->p1; + return(f); +} + +free(pointer) +struct node *pointer; +{ + pointer->p1 = freelist; + freelist = pointer; +} + +nfree() +{ + register int i; + register struct node *a; + + i = freesize; + a = freelist; + while(a) { + a = a->p1; + i++; + } + return(i); +} + +look(string) +struct node *string; +{ + register struct node *i, *j, *k; + + k = 0; + i = namelist; + while (i) { + j = i->p1; + if (equal(j->p1, string) == 0) + return(j); + i = (k=i)->p2; + } + i = alloc(); + i->p2 = 0; + if (k) + k->p2 = i; + else + namelist = i; + j = alloc(); + i->p1 = j; + j->p1 = copy(string); + j->p2 = 0; + j->typ = 0; + return(j); +} + +copy(string) +struct node *string; +{ + register struct node *j, *l, *m; + struct node *i, *k; + + if (string == 0) + return(0); + i = l = alloc(); + j = string; + k = string->p2; + while(j != k) { + m = alloc(); + m->ch = (j=j->p1)->ch; + l->p1 = m; + l = m; + } + i->p2 = l; + return(i); +} + +equal(string1, string2) +struct node *string1, *string2; +{ + register struct node *i, *j, *k; + struct node *l; + int n, m; + + if (string1==0) { + if (string2==0) + return(0); + return(-1); + } + if (string2==0) + return(1); + i = string1; + j = string1->p2; + k = string2; + l = string2->p2; + for(;;) { + m = (i=i->p1)->ch; + n = (k=k->p1)->ch; + if (m>n) + return(1); + if (mp1; + q = s->p2; + sign = 1; + if (class(p->ch)==5) { /* minus */ + sign = -1; + if (p==q) + return(0); + p = p->p1; + } +loop: + m = p->ch - '0'; + if (m>9 | m<0) + writes("bad integer string"); + n = n * 10 + m; + if (p==q) + return(n*sign); + p = p->p1; + goto loop; +} + +binstr(binary) { + int n, sign; + register struct node *m, *p, *q; + + n = binary; + p = alloc(); + q = alloc(); + sign = 1; + if (binary<0) { + sign = -1; + n = -binary; + } + p->p2 = q; +loop: + q->ch = n%10+'0'; + n = n / 10; + if (n==0) { + if (sign<0) { + m = alloc(); + m->p1 = q; + q = m; + q->ch = '-'; + } + p->p1 = q; + return(p); + } + m = alloc(); + m->p1 = q; + q = m; + goto loop; +} + +add(string1, string2) { + return(binstr(strbin(string1) + strbin(string2))); +} + +sub(string1, string2) { + return(binstr(strbin(string1) - strbin(string2))); +} + +mult(string1, string2) { + return(binstr(strbin(string1) * strbin(string2))); +} + +div(string1, string2) { + return(binstr(strbin(string1) / strbin(string2))); +} + +cat(string1, string2) +struct node *string1, *string2; +{ + register struct node *a, *b; + + if (string1==0) + return(copy(string2)); + if (string2==0) + return(copy(string1)); + a = copy(string1); + b = copy(string2); + a->p2->p1 = b->p1; + a->p2 = b->p2; + free(b); + return(a); +} + +dcat(a,b) +struct node *a, *b; +{ + register struct node *c; + + c = cat(a,b); + delete(a); + delete(b); + return(c); +} + +delete(string) +struct node *string; +{ + register struct node *a, *b, *c; + + if (string==0) + return; + a = string; + b = string->p2; + while(a != b) { + c = a->p1; + free(a); + a = c; + } + free(a); +} + +sysput(string) { + syspot(string); + delete(string); +} + +dump() +{ + dump1(namelist); +} + +dump1(base) +struct node *base; +{ + register struct node *b, *c, *e; + struct node *d; + + while (base) { + b = base->p1; + c = binstr(b->typ); + d = strstr(" "); + e = dcat(c, d); + sysput(cat(e, b->p1)); + delete(e); + if (b->typ==1) { + c = strstr(" "); + sysput(cat(c, b->p2)); + delete(c); + } + base = base->p2; + } +} + +writes(s) { + + sysput(dcat(binstr(lc),dcat(strstr("\t"),strstr(s)))); + flush(); + if (cfail) { + dump(); + flush(); + exit(); + } + while(getc()); + while (compile()); + flush(); + exit(); +} + +getc() { + register struct node *a; + static struct node *line; + static linflg; + + while (line==0) { + line = syspit(); + if(rfail) { + cfail++; + writes("eof on input"); + } + lc++; + } + if (linflg) { + line = 0; + linflg = 0; + return(0); + } + a = line->p1; + if (a==line->p2) { + free(line); + linflg++; + } else + line->p1 = a->p1; + return(a); +} diff --git a/source/sno/sno2.c b/source/sno/sno2.c new file mode 100644 index 0000000..8b5368f --- /dev/null +++ b/source/sno/sno2.c @@ -0,0 +1,559 @@ +#include "sno.h" + + +compon() { + register struct node *a, *b; + register int c; + static next; + + if (next == 0) + schar = getc(); else + next = 0; + if (schar == 0) { + (a=alloc())->typ = 0; + return(a); + } + switch (class(schar->ch)) { + + case 1: + schar->typ = 5; + return(schar); + + case 2: + schar->typ = 16; + return(schar); + + case 3: + a = schar; + for(;;) { + schar = getc(); + if (schar == 0) { + a->typ = 0; + return(a); + } + if (class(schar->ch) != 3) + break; + free(schar); + } + next = 1; + a->typ = 7; + return(a); + + case 4: + schar->typ = 8; + return(schar); + + case 5: + schar->typ = 9; + return(schar); + + case 6: + a = schar; + schar = getc(); + if (class(schar->ch) == 3) + a->typ = 10; else + a->typ = 1; + next = 1; + return(a); + + case 7: + a = schar; + schar = getc(); + if (class(schar->ch) == 3) + a->typ = 11; else + a->typ = 2; + next = 1; + return(a); + + case 8: + schar->typ = 12; + return(schar); + + case 9: + c = schar->ch; + a = getc(); + if(a == 0) + goto lerr; + b = schar; + if(a->ch == c) { + free(schar); + a->typ = 15; + a->p1 = 0; + return(a); + } + b->p1 = a; + for(;;) { + schar = getc(); + if (schar == 0) + lerr: + writes("illegal literal string"); + if(schar->ch == c) + break; + a->p1 = schar; + a = schar; + } + b->p2 = a; + schar->typ = 15; + schar->p1 = b; + return(schar); + + case 10: + schar->typ = 3; + return(schar); + + case 11: + schar->typ = 4; + return(schar); + + } + b = alloc(); + b->p1 = a = schar; + schar = getc(); + while(schar!=0 & !class(schar->ch)) { + a->p1 = schar; + a = schar; + schar = getc(); + } + b->p2 = a; + next = 1; + a = look(b); + delete(b); + b = alloc(); + b->typ = 14; + b->p1 = a; + return(b); +} + +nscomp() +{ + register struct node *c; + + while((c=compon())->typ == 7) + free(c); + return(c); +} + +push(stack) { + register struct node *a; + + (a=alloc())->p2 = stack; + return(a); +} + +pop(stack) +struct node *stack; +{ + register struct node *a, *s; + + s = stack; + if (s == 0) + writes("pop"); + a = s->p2; + free(s); + return(a); +} + +expr(start, eof, e) +struct node *e; +{ + register struct node *stack, *list, *comp; + int operand, op, space, op1; + struct node *a, *b, *c; + int d; + + list = alloc(); + e->p2 = list; + stack = push(0); + stack->typ = eof; + operand = 0; + space = start; +l1: + if (space) { + comp = space; + space = 0; + } else + comp = compon(); + +l3: + op = comp->typ; + switch (op) { + + case 7: + space = 1; + free(comp); + comp = compon(); + goto l3; + + case 10: + if (space == 0) { + comp->typ = 1; + goto l3; + } + + case 11: + if (space == 0) { + comp->typ = 2; + goto l3; + } + + case 8: + case 9: + if (operand == 0) + writes("no operand preceding operator"); + operand = 0; + goto l5; + + case 14: + case 15: + if (operand == 0) { + operand = 1; + goto l5; + } + if (space == 0) + goto l7; + goto l4; + + case 12: + if (operand == 0) + goto l5; + if (space) + goto l4; + l7: + writes("illegal juxtaposition of operands"); + + case 16: + if (operand == 0) + goto l5; + if (space) + goto l4; + b = compon(); + op = comp->typ = 13; + if (b->typ == 5) { + comp->p1 = 0; + goto l10; + } + comp->p1 = a = alloc(); + b = expr(b, 6, a); + while((d=b->typ) == 4) { + a->p1 = b; + a = b; + b = expr(0, 6, a); + } + if (d != 5) + writes("error in function"); + a->p1 = 0; + l10: + free(b); + goto l6; + + l4: + space = comp; + op = 7; + operand = 0; + goto l6; + } + if (operand==0) + writes("no operand at end of expression"); +l5: + space = 0; +l6: + op1 = stack->typ; + if (op > op1) { + stack = push(stack); + if (op == 16) + op = 6; + stack->typ = op; + stack->p1 = comp; + goto l1; + } + c = stack->p1; + stack = pop(stack); + if (stack == 0) { + list->typ = 0; + return(comp); + } + if (op1 == 6) { + if (op != 5) + writes("too many ('s"); + goto l1; + } + if (op1 == 7) + c = alloc(); + list->typ = op1; + list->p2 = c->p1; + list->p1 = c; + list = c; + goto l6; +} + +match(start, m) +struct node *m; +{ + register struct node *list, *comp, *term; + struct node *a; + int b, bal; + + term = bal = 0; + list = alloc(); + m->p2 = list; + comp = start; + if (!comp) + comp = compon(); + goto l2; + +l3: + list->p1 = a = alloc(); + list = a; +l2: + switch (comp->typ) { + case 7: + free(comp); + comp = compon(); + goto l2; + + case 12: + case 14: + case 15: + case 16: + term = 0; + comp = expr(comp, 6, list); + list->typ = 1; + goto l3; + + case 1: + free(comp); + comp = compon(); + bal = 0; + if (comp->typ == 16) { + bal = 1; + free(comp); + comp = compon(); + } + a = alloc(); + b = comp->typ; + if (b == 2 | b == 5 | b == 10 | b == 1) + a->p1 = 0; else { + comp = expr(comp, 11, a); + a->p1 = a->p2; + } + if (comp->typ != 2) { + a->p2 = 0; + } else { + free(comp); + comp = expr(0, 6, a); + } + if (bal) { + if (comp->typ != 5) + goto merr; + free(comp); + comp = compon(); + } + b = comp->typ; + if (b != 1 & b != 10) + goto merr; + list->p2 = a; + list->typ = 2; + a->typ = bal; + free(comp); + comp = compon(); + if(bal) + term = 0; else + term = list; + goto l3; + } + if(term) + term->typ = 3; + list->typ = 0; + return(comp); + +merr: + writes("unrecognized component in match"); +} + +compile() { + register struct node *b, *comp; + struct node *r, *l, *xs, *xf, *g; + register int a; + int m, t, as; + + m = l = as = xs = xf = t = 0; + comp = compon(); + a = comp->typ; + if (a == 14) { + l = comp->p1; + free(comp); + comp = compon(); + a = comp->typ; + } + if (a != 7) + writes("no space beginning statement"); + free(comp); + if (l == lookdef) + goto def; + comp = expr(0, 11, r=alloc()); + a = comp->typ; + if (a == 0) + goto asmble; + if (a == 2) + goto xfer; + if (a == 3) + goto assig; + m = alloc(); + comp = match(comp, m); + a = comp->typ; + if (a == 0) + goto asmble; + if (a == 2) + goto xfer; + if (a == 3) + goto assig; + writes("unrecognized component in match"); + +assig: + free(comp); + comp = expr(0, 6, as=alloc()); + a = comp->typ; + if (a == 0) + goto asmble; + if (a == 2) + goto xfer; + writes("unrecognized component in assignment"); + +xfer: + free(comp); + comp = compon(); + a = comp->typ; + if (a == 16) + goto xboth; + if (a == 0) { + if (xs!=0 | xf!=0) + goto asmble; + goto xerr; + } + if (a != 14) + goto xerr; + b = comp->p1; + free(comp); + if (b == looks) + goto xsuc; + if (b == lookf) + goto xfail; + +xerr: + writes("unrecognized component in goto"); + +xboth: + free(comp); + xs = alloc(); + xf = alloc(); + comp = expr(0, 6, xs); + if (comp->typ != 5) + goto xerr; + xf->p2 = xs->p2; + comp = compon(); + if (comp->typ != 0) + goto xerr; + goto asmble; + +xsuc: + if(xs) + goto xerr; + comp = compon(); + if (comp->typ != 16) + goto xerr; + comp = expr(0, 6, xs=alloc()); + if (comp->typ != 5) + goto xerr; + goto xfer; + +xfail: + if (xf) + goto xerr; + comp = compon(); + if (comp->typ != 16) + goto xerr; + comp = expr(0, 6, xf=alloc()); + if (comp->typ != 5) + goto xerr; + goto xfer; + +asmble: + if(l) { + if (l->typ) + writes("name doubly defined"); + l->p2 = comp; + l->typ = 2; /* type label;*/ + } + comp->p2 = r; + if (m) { + t++; + r->p1 = m; + r = m; + } + if (as) { + t =+ 2; + r->p1 = as; + r = as; + } + (g=alloc())->p1 = 0; + if (xs) { + g->p1 = xs->p2; + free(xs); + } + g->p2 = 0; + if (xf) { + g->p2 = xf->p2; + free(xf); + } + r->p1 = g; + comp->typ = t; + comp->ch = lc; + return(comp); + +def: + r = nscomp(); + if (r->typ != 14) + goto derr; + l = r->p1; + if (l->typ) + writes("name doubly defined"); + l->typ = 5; /*type function;*/ + a = r; + l->p2 = a; + r = nscomp(); + l = r; + a->p1 = l; + if (r->typ == 0) + goto d4; + if (r->typ != 16) + goto derr; + +d2: + r = nscomp(); + if (r->typ != 14) + goto derr; + a->p2 = r; + r->typ = 0; + a = r; + r = nscomp(); + if (r->typ == 4) { + free(r); + goto d2; + } + if (r->typ != 5) + goto derr; + free(r); + if ((r=compon())->typ != 0) + goto derr; + free(r); + +d4: + r = compile(); + a->p2 = 0; + l->p1 = r; + l->p2 = 0; + return(r); + +derr: + writes("illegal component in define"); +} diff --git a/source/sno/sno3.c b/source/sno/sno3.c new file mode 100644 index 0000000..b5b73fa --- /dev/null +++ b/source/sno/sno3.c @@ -0,0 +1,272 @@ +#include "sno.h" + +/* + * sno3 + */ + + +bextend(str, last) +struct node *str, *last; +{ + register struct node *a, *s; + register int b; + int c, d; + + s = str; + if ((c = s->p1) == 0) + goto bad; + b = d = 0; + a = s->p2; + if(a == 0) { + a = c; + goto eb2; + } +eb1: + if (a == last) + goto bad; + a = a->p1; +eb2: + d++; + c = class(a->ch); + if (c == 1) { /* rp */ + if (b == 0) + goto bad; + b--; + goto eb3; + } + if (c == 2) { /* lp */ + b++; + goto eb1; + } +eb3: + if (b == 0) { + s->p2= a; + return(d); + } + goto eb1; +bad: + return(0); +} + +ubextend(str, last) +struct node *str, *last; +{ + register struct node *a, *b, *s; + + s = str; + a = s->p1; + if(a == 0) + goto bad; + b = s->p2; + if(b == 0) + goto good; + if (b == last) + goto bad; + a = b->p1; +good: + s->p2 = a; + return(1); +bad: + return(0); +} + +search(arg, r) +struct node *arg, *r; +{ + struct node *list, *back, *str, + *etc, *next, *last, *base, *e; + register struct node *a, *b, *var; + int c, d; + + a = arg->p2; + list = base = alloc(); + last = next = 0; + goto badv1; +badvanc: + a = a->p1; + if (a->typ == 0) { + list->p1 = 0; + if (rfail == 1) { + a = 0; + goto fail; + } + list = base; + if (r == 0) + next = last = 0; else { + next = r->p1; + last = r->p2; + } + goto adv1; + } + b = alloc(); + list->p1 = b; + list = b; +badv1: + list->p2 = back = alloc(); + back->p1 = last; + b = a->p2; + c = a->typ; + list->typ = c; + if (c < 2) { + back->p2 = eval(b, 1); + goto badvanc; + } + last = list; + str = alloc(); + etc = alloc(); + back->p2 = var = alloc(); + var->typ = b->typ; + var->p1 = str; + var->p2 = etc; + e = b->p1; + if (e == 0) + etc->p1 = 0; else + etc->p1 = eval(e, 0); + e = b->p2; + if (e == 0) + etc->p2 = 0; else { + e = eval(e, 1); + etc->p2 = strbin(e); + delete(e); + } + goto badvanc; + +retard: + a = back->p1; + if (a == 0) { + rfail = 1; + goto fail; + } + list = a; + back = list->p2; + var = back->p2; + str = var->p1; + etc = var->p2; + if (etc->p2) + goto retard; + if (var->typ == 1) { + if (bextend(str, last) == 0) + goto retard; + goto adv0; + } + if (ubextend(str, last) == 0) + goto retard; +adv0: + a = str->p2; +adv01: + if (a == last) + next = 0; else + next = a->p1; +advanc: + a = list->p1; + if (a == 0) { + a = alloc(); + if (r == 0) { + a->p1 = a->p2 = 0; + goto fail; + } + b = r->p1; + a->p1 = b; + if (next == 0) { + a->p2 = r->p2; + goto fail; + } + while(1) { + e = b->p1; + if (e == next) { + a->p2 = b; + goto fail; + } + b = e; + } + } + list = a; +adv1: + back = list->p2; + var = back->p2; + d = list->typ; + if(d < 2) { + if (var == 0) + goto advanc; + if (next == 0) + goto retard; + a = next; + b = var->p1; + e = var->p2; + while(1) { + if (a->ch != b->ch) + goto retard; + if (b == e) + goto adv01; + if (a == last) + goto retard; + a = a->p1; + b = b->p1; + } + } + str = var->p1; + etc = var->p2; + str->p1 = next; + str->p2 = 0; + c = etc->p2; + if (var->typ == 1) { + d = bextend(str, last); + if (d == 0) + goto retard; + if (c == 0) + goto adv0; + while(1) { + c =- d; + if (c == 0) + goto adv0; + if (c < 0) + goto retard; + d = bextend(str, last); + if (d == 0) + goto retard; + } + } + if (c == 0) { + if(d==3 & next!=0) { + str->p2 = last; + goto adv0; + } + goto advanc; + } + while(c--) + if (ubextend(str, last) == 0) + goto retard; + goto adv0; + +fail: + list = base; + goto f1; +fadv: + free(back); + b = list->p1; + free(list); + if (b == 0) + return(a); + list = b; +f1: + back = list->p2; + var = back->p2; + if (list->typ < 2) { + delete(var); + goto fadv; + } + str = var->p1; + etc = var->p2; + if (a != 0 & etc->p1 != 0) { + if (str->p2 == 0) { + free(str); + str = 0; + } + assign(etc->p1, copy(str)); + } + if (str) + free(str); + free(etc); + free(var); + goto fadv; +} diff --git a/source/sno/sno4.c b/source/sno/sno4.c new file mode 100644 index 0000000..b79da54 --- /dev/null +++ b/source/sno/sno4.c @@ -0,0 +1,282 @@ +#include "sno.h" +/* + * sno4 + */ + + +and(ptr) +struct node *ptr; +{ + register struct node *a, *p; + + p = ptr; + a = p->p1; + if (p->typ == 0) { + switch (a->typ) { + case0: + case 0: + a->typ = 1; + case 1: + goto l1; + case 3: + flush(); + return(syspit()); + case 5: + a = a->p2->p1; + goto l1; + case 6: + return(binstr(nfree())); + } + writes("attempt to take an illegal value"); + goto case0; + l1: + a = copy(a->p2); + } + return(a); +} + +eval(e, t) +struct node *e; +{ + struct node *list, *a2, *a3, *a4, *a3base; + register struct node *a1, *stack, *op; + + if (rfail == 1) + return(0); + stack = 0; + list = e; + goto l1; +advanc: + list = list->p1; +l1: + op = list->typ; + switch (op) { + default: + case 0: + if (t == 1) { + a1 = and(stack); + goto e1; + } + if (stack->typ == 1) + writes("attempt to store in a value"); + a1 = stack->p1; + e1: + stack = pop(stack); + if (stack) + writes("phase error"); + return(a1); + case 12: + a1 = and(stack); + stack->p1 = look(a1); + delete(a1); + stack->typ = 0; + goto advanc; + case 13: + if (stack->typ) + writes("illegal function"); + a1 = stack->p1; + if (a1->typ!=5) + writes("illegal function"); + a1 = a1->p2; + op = a1->p1; + a3base = a3 = alloc(); + a3->p2 = op->p2; + op->p2 = 0; + a1 = a1->p2; + a2 = list->p2; + f1: + if (a1!=0 & a2!=0) + goto f2; + if (a1!=a2) + writes("parameters do not match"); + op = op->p1; + goto f3; + f2: + a3->p1 = a4 = alloc(); + a3 = a4; + a3->p2 = and(a1); + assign(a1->p1, eval(a2->p2, 1));/* recursive */ + a1 = a1->p2; + a2 = a2->p1; + goto f1; + f3: + op = execute(op); /* recursive */ + if (op) + goto f3; + a1 = stack->p1->p2; + op = a1->p1; + a3 = a3base; + stack->p1 = op->p2; + stack->typ = 1; + op->p2 = a3->p2; + f4: + a4 = a3->p1; + free(a3); + a3 = a4; + a1 = a1->p2; + if (a1 == 0) + goto advanc; + assign(a1->p1, a3->p2); + goto f4; + case 11: + case 10: + case 9: + case 8: + case 7: + a1 = and(stack); + stack = pop(stack); + a2 = and(stack); + a3 = doop(op, a2, a1); + delete(a1); + delete(a2); + stack->p1 = a3; + stack->typ = 1; + goto advanc; + case 15: + a1 = copy(list->p2); + a2 = 1; + goto l3; + case 14: + a1 = list->p2; + a2 = 0; + l3: + stack = push(stack); + stack->p1 = a1; + stack->typ = a2; + goto advanc; + } +} + +doop(op, arg1, arg2) +{ + register int a1, a2; + + a1 = arg1; + a2 = arg2; + switch (op) { + + case 11: + return(div(a1, a2)); + case 10: + return(mult(a1, a2)); + case 8: + return(add(a1, a2)); + case 9: + return(sub(a1, a2)); + case 7: + return(cat(a1, a2)); + } + return(0); +} + +execute(e) +struct node *e; +{ + register struct node *r, *b, *c; + struct node *m, *ca, *d, *a; + + r = e->p2; + lc = e->ch; + switch (e->typ) { + case 0: /* r g */ + a = r->p1; + delete(eval(r->p2, 1)); + goto xsuc; + case 1: /* r m g */ + m = r->p1; + a = m->p1; + b = eval(r->p2, 1); + c = search(m, b); + delete(b); + if (c == 0) + goto xfail; + free(c); + goto xsuc; + case 2: /* r a g */ + ca = r->p1; + a = ca->p1; + b = eval(r->p2, 0); + assign(b, eval(ca->p2, 1)); + goto xsuc; + case 3: /* r m a g */ + m = r->p1; + ca = m->p1; + a = ca->p1; + b = eval(r->p2, 0); + d = search(m, b->p2); + if (d == 0) + goto xfail; + c = eval(ca->p2, 1); + if (d->p1 == 0) { + free(d); + assign(b, cat(c, b->p2)); + delete(c); + goto xsuc; + } + if (d->p2 == b->p2->p2) { + assign(b, c); + free(d); + goto xsuc; + } + (r=alloc())->p1 = d->p2->p1; + r->p2 = b->p2->p2; + assign(b, cat(c, r)); + free(d); + free(r); + delete(c); + goto xsuc; + } +xsuc: + if (rfail) + goto xfail; + b = a->p1; + goto xboth; +xfail: + rfail = 0; + b = a->p2; +xboth: + if (b == 0) { + return(e->p1); + } + b = eval(b, 0); + if (b == lookret) + return(0); + if (b == lookfret) { + rfail = 1; + return(0); + } + if (b->typ!=2) + writes("attempt to transfer to non-label"); + return(b->p2); +} + +assign(adr, val) +struct node *adr, *val; +{ + register struct node *a, *addr, *value; + + addr = adr; + value = val; + if (rfail == 1) { + delete(value); + return; + } + switch (addr->typ) { + default: + writes("attempt to make an illegal assignment"); + case 0: + addr->typ = 1; + case 1: + delete(addr->p2); + addr->p2 = value; + return; + case 4: + sysput(value); + return; + case 5: + a = addr->p2->p1; + delete(a->p2); + a->p2 = value; + return; + } +} diff --git a/source/tmg/run b/source/tmg/run new file mode 100644 index 0000000..a6a0744 --- /dev/null +++ b/source/tmg/run @@ -0,0 +1,60 @@ +as tmga.s +cmp a.out /usr/lib/tmga +cp a.out /usr/lib/tmga + +as tmgc.s +cmp a.out /usr/lib/tmgc +cp a.out /usr/lib/tmgc + +chdir tmgb +as any.s; mv a.out any.o +as append.s; mv a.out append.o +as arith.s; mv a.out arith.o +as bundle.s; mv a.out bundle.o +as char.s; mv a.out char.o +as copy.s; mv a.out copy.o +as cstr.s; mv a.out cstr.o +as ctest.s; mv a.out ctest.o +as decmal.s; mv a.out decmal.o +as discd.s; mv a.out discd.o +as emit.s; mv a.out emit.o +as end.s; mv a.out end.o +as f.s; mv a.out f.o +as find.s; mv a.out find.o +as getnam.s; mv a.out getnam.o +as ignore.s; mv a.out ignore.o +as inc.s; mv a.out inc.o +as infix.s; mv a.out infix.o +as jget.s; mv a.out jget.o +as lvrv.s; mv a.out lvrv.o +as mult.s; mv a.out mult.o +as octal.s; mv a.out octal.o +as params.s; mv a.out params.o +as push.s; mv a.out push.o +as putcal.s; mv a.out putcal.o +as putdec.s; mv a.out putdec.o +as putoct.s; mv a.out putoct.o +as px.s; mv a.out px.o +as reln.s; mv a.out reln.o +as shift.s; mv a.out shift.o +as stack.s; mv a.out stack.o +as string.s; mv a.out string.o +as table.s; mv a.out table.o +as tq.s; mv a.out tq.o +as trace.s; mv a.out trace.o +as trans.s; mv a.out trans.o +as tx.s; mv a.out tx.o +as unary.s; mv a.out unary.o +ar r /lib/tmgb *.o +rm *.o + +chdir .. +as - tmgl.s +ld -s /usr/lib/tmga a.out /usr/lib/tmgb /usr/lib/tmgc -ls +cmp a.out /usr/lib/tmg +cp a.out /usr/lib/tmg +/usr/lib/tmg tmgl.t x +cmp x tmgl.s +cp x tmgl.s + +rm a.out x diff --git a/source/tmg/tmga.s b/source/tmg/tmga.s new file mode 100644 index 0000000..f563b3a --- /dev/null +++ b/source/tmg/tmga.s @@ -0,0 +1,486 @@ +/ tmg +/ main program and parsing rule interpreter +/ +tracing = 1 +f = r5 +g = r4 +i = r3 + +sef=sec^sec; clf=clc^clc; bfs=bcs^bcs; bfc=bcc^bcc /fail indicator + +.globl flush,obuild,putch,iget,kput +.globl generate +.globl cfile,dfile,ofile,input +.globl main,succ,fail,errcom,pbundle,parse,diag +.globl alt,salt,stop,goto +.globl tables,start,end +.globl stkb,stke +.globl ktab +.globl trswitch,trace +.globl x,si,j,k,n,g1,env + +/ begin here +/ get arguments from shell +/ arg1 is input file +/ arg2 is output file (standard output if missing) + +main: + dec (sp) + beq 3f + mov 4(sp),0f + sys open;0:0;0 + bes 1f + mov r0,input + dec (sp) + beq 3f + mov 6(sp),0f + sys creat;0:0;666 + bes 1f + mov r0,ofile + +/ set up tables +/ initialize stack, for definitions see tmgc.s +/ go interpret beginning at "start" +/ finish up +3: + mov $stkb,f + clr j(f) + clr k(f) + clr n(f) + mov f,g + add $g1,g + mov $start,r0 + jsr pc,adv + jsr pc,flush +1: + sys unlink;1f + sys exit +1: + ;.even +/ fatal processor error +/write a two letter message on diagnostic file +/ get a dump + +errcom: + mov dfile,cfile + jsr pc,obuild + mov $1f,r0 + jsr pc,obuild + jsr pc,flush +stop: + 4 +1: <--fatal\n\0>;.even + +/ all functions that succeed come here +/ test the exit indicator, and leave the rule if on + +succ: + inc succc + bit $1,x(f) + bne sret +contin: + inc continc + .if tracing + tst trswitch + beq 1f + mov $'r,r0 + jsr pc,trace +1: + .endif +/ get interpreted instruction +/ save its exit bit (bit 0) on stack +/ distinguish type of instruction by ranges of value + + jsr pc,iget + mov r0,x(f) + bic $1,r0 +.if .. + cmp r0,$.. + blo 1f +.endif + cmp r0,$start + blo 2f + cmp r0,$end + blo 3f + cmp r0,$tables + blo 2f + +/ bad address +1: + jsr r0,errcom + ;.even + +/ machine coded function +2: + jmp (r0) + +/ tmg-coded rule, execute and test its success +/ bfc = branch on fail clear +3: + jsr pc,adv + bfc succ + +/ all functions and rules that fail come here +/ if exit bit is on do a fail return +/ if following instruction is an alternate (recognized literally) +/ do a goto, if a success alternate, do a nop +/ otherwise do a fail return + +fail: + inc failc + bit $1,x(f) + bne fret + jsr pc,iget + mov r0,x(f) + bic $1,r0 + cmp r0,$alt + beq salt + cmp r0,$salt + bne fret + +alt: + tst (i)+ + br succ + +salt: + jsr pc,iget + mov r0,i + br contin + +goto: + br salt + +/ do a success return +/ bundle translations delivered to this rule, +/ pop stack frame +/ restore interpreted instruction counter (i) +/ update input cursor (j) for invoking rule +/ update high water mark (k) in ktable +/ if there was a translation delivered, add to stack frame +/ clear the fail flag + +sret: + mov f,r0 + add $g1,r0 + jsr pc,pbundle + mov f,g + mov (f),f + mov si(f),i + mov j(g),j(f) + mov k(g),k(f) + tst r0 + beq 1f + mov r0,(g)+ +1: + clf + rts pc + +/ do a fail return +/ pop stack +/ do not update j or k +/ restore interpreted instruction counter + +fret: + mov f,g + mov (f),f + mov si(f),i + sef + rts pc + +/ diag and parse builtins +/ set current file to diagnostic or output +/ save and restore ktable water mark around parse-translate +/ also current file and next frame pointer (g) +/ execute parsing rule + +diag: + mov dfile,r1 + br 1f +parse: + mov ofile,r1 +1: + mov cfile,-(sp) + mov r1,cfile + mov k(f),-(sp) + mov g,-(sp) + jsr pc,iget + jsr pc,adv + bfs 1f +/ rule succeeded +/ if it delivered translation, put it in ktable and set +/ instruction counter for +/ translation generator to point there +/ go generate + cmp g,(sp)+ + ble 2f + mov -(g),r0 + jsr pc,kput + mov k(f),i + neg i + add $ktab,i + mov f,-(sp) + mov g,f + clr x(f) + jsr pc,generate + mov (sp)+,f + mov si(f),i +2: + mov (sp)+,k(f) + mov (sp)+,cfile + jmp succ +1: + mov (sp)+,g + mov (sp)+,k(f) + mov (sp)+,cfile + br fail + +/ advance stack frame to invoke a parsing rule +/ copy corsor, watr mark, ignored class to new frame +/ set intial frame length to default (g1) +/ check end of stack +/ r0,r1 are new i,environment + +adv: + inc advc + mov f,(g) + mov i,si(f) + mov j(f),j(g) + mov k(f),k(g) + mov n(f),n(g) + mov g,f + add $g1,g + cmp g,$stke + bhis 1f + mov r0,i + mov r1,env(f) + jmp contin +1: + jsr r0,errcom + ;.even + +/pbundle entered with pointer to earliest element of bunlde +/to reduce from the top of stack in r0 +/exit with pointer to bundle in r0, or zero if bundle is empty + +pbundle: + cmp r0,g + blo 1f + clr r0 /empty bundle + rts pc +1: + mov r0,-(sp) + mov r0,r1 + mov (r1)+,r0 + cmp r1,g + beq 2f /trivial bundle +1: + mov r1,-(sp) + jsr pc,kput + mov (sp)+,r1 + mov (r1)+,r0 + cmp r1,g + blos 1b + mov k(f),r0 +2: + mov (sp)+,g + rts pc + +/ tmg translation rule interpreter (generator) +/ see tmgc.s for definitions + +tracing = 1 +f = r5 +.globl x,si,ek,ep,ek.fs,ep.fs,fs +.globl trswitch,trace +.globl start,end,tables,ktab,ktat +.globl errcom +.globl generate,.tp +i = r3 + +/ if exit bit is on pop stack frame restore inst counter and return + +generate: +bit $1,x(f) + beq gcontin + sub $fs,f + mov si(f),i + rts pc +gcontin: + .if tracing + tst trswitch + beq 1f + mov $'g,r0 + jsr pc,trace +1: + .endif +/ get interpreted instruction, decode by range of values + + mov (i)+,r0 + mov r0,x(f) + bic $1,r0 +.if .. + cmp r0,$.. + blo badadr +.endif + cmp r0,$start + blo gf + cmp r0,$end + blo gc + cmp r0,$tables + blo gf + neg r0 + cmp r0,$ktat + blo gk +badadr: + jsr r0,errcom + ;.even + +/ builtin translation function +gf: + jmp (r0) + +/ tmg-coded translation subroutine +/ execute it in current environment +gc: + mov i,si(f) + mov r0,i + mov ek(f),ek.fs(f) + mov ep(f),ep.fs(f) + add $fs,f + jsr pc,gcontin + br generate + +/ delivered compound translation +/ instruction counter is in ktable +/ set the k environment for understanding 1, 2 ... +/ to designate this frame +gk: + mov f,ek(f) + add $ktab,r0 + mov r0,i + br gcontin + +/ execute rule called for by 1 2 ... +/ found relative to instruction counter in the k environment +/ this frame becomes th p environment for +/ any parameters passed with this invocation +/ e.g. for 1(x) see also .tq +.tp: + movb (i)+,r0 + movb (i)+,r2 + inc r0 + asl r0 + mov i,si(f) + mov f,ep.fs(f) + mov ek(f),r1 + mov si(r1),i + sub r0,i + add $fs,f + mov f,ek(f) + asl r2 + beq 2f +/element is 1.1, 1.2, .. 2.1,... + mov (i),i + neg i + bge 1f + jsr r0,errcom + ;.even +1: + cmp i,$ktat + bhis badadr + add $ktab,i + sub r2,i +2: + jsr pc,gcontin + br generate + +/ tmg output routines/ and iget +f = r5 +i = r3 +.globl env,si +.globl errcom +.globl cfile,lfile +.globl putch,obuild,iget,flush +.globl outb,outt,outw +.globl start + +/ adds 1 or 2 characters in r0 to output + +putch: + clr -(sp) + mov r0,-(sp) + mov sp,r0 + jsr pc,obuild + add $4,sp + rts pc + +/ r0 points to string to put out on current output file (cfile) +/ string terminated by 0 +/ if last file differed from current file, flush output buffer first +/ in any case flush output buffer when its write pointer (outw) +/ reaches its top (outt) + +obuild: + cmp cfile,lfile + beq 1f + mov r0,-(sp) + jsr pc,flush + mov (sp)+,r0 + mov cfile,lfile +1: + mov outw,r1 +1: + tstb (r0) + beq 1f + movb (r0)+,outb(r1) + inc r1 + mov r1,outw + cmp r1,$outt + blt 1b + mov r0,-(sp) + jsr pc,flush + mov (sp)+,r0 + br obuild +1: + rts pc + +/ copy output buffer onto last output file and clear buffer + +flush: + mov outw,0f + mov lfile,r0 + sys write;outb;0:0 + clr outw + rts pc + + +/ get interpreted instruction for a parsing rule +/ negative instruction is a pointer to a parameter in this +/ stack fromae, fetch that instead +/ put environment pointer in r1 + +iget: + mov f,r1 + mov (i)+,r0 + bge 2f + mov r0,-(sp) /save the exit bit + bic $-2,(sp) + bic (sp),r0 +1: /chase parameter + mov env(r1),r1 + add si(r1),r0 + mov (r0),r0 + blt 1b + mov env(r1),r1 + bis (sp)+,r0 +2: + rts pc +/there followeth the driving tables +start: + +.data +succc: 0 +continc: 0 +failc: 0 +advc: 0 +.text diff --git a/source/tmg/tmgb/any.s b/source/tmg/tmgb/any.s new file mode 100644 index 0000000..2d48fb1 --- /dev/null +++ b/source/tmg/tmgb/any.s @@ -0,0 +1,17 @@ +i = r3 +f = r5 +.globl x,j +.globl succ,fail +.globl ctest,iget +.globl any + +any: + mov j(f),-(sp) + jsr pc,iget + jsr pc,ctest + bcs 1f + mov (sp)+,j(f) + jmp fail +1: + tst (sp)+ + jmp succ diff --git a/source/tmg/tmgb/append.s b/source/tmg/tmgb/append.s new file mode 100644 index 0000000..33e2956 --- /dev/null +++ b/source/tmg/tmgb/append.s @@ -0,0 +1,16 @@ +.globl succ +.globl putcstr,iget +.globl append + +append: + jsr pc,iget + mov r0,-(sp) +1: + movb *(sp),r0 + beq 1f + jsr pc,putcstr + inc (sp) + br 1b +1: + tst (sp)+ + jmp succ diff --git a/source/tmg/tmgb/arith.s b/source/tmg/tmgb/arith.s new file mode 100644 index 0000000..b60cadf --- /dev/null +++ b/source/tmg/tmgb/arith.s @@ -0,0 +1,56 @@ +.globl succ,fail,iget +.globl seekchar,getword,alterword +.globl sprv,update +.globl .l,.u,.p,.t,.st, + +/ infix = +.st: + jsr pc,sprv + mov (sp)+,(sp) + mov (sp)+,(sp) +/ update +.u: + jsr pc,update + br 9f +/ pop stack +.p: + jsr pc,sprv + cmp (sp)+,(sp)+ + br 9f +/ test stack +.t: + jsr pc,sprv + mov (sp)+,(sp)+ + bne 9f + jmp fail +/ load named value +/ rvalue into (sp), lvalue into 2(sp) +.l: + jsr pc,iget + mov r0,-(sp) + mov (r0),-(sp) + br 9f +/ update a stored value, used by all assignments +update: + cmp 2+2(sp),$-1 + beq 1f + mov 0+2(sp),*2+2(sp) + rts pc +1: + mov 4+2(sp),r1 + mov 6+2(sp),r0 + jsr pc,seekchar + mov 0+2(sp),r0 + jsr pc,alterword +/ make sp hold a simple rv (forget it might be a table value) +sprv: + mov (sp)+,r0 + cmp $-1,2(sp) + bne 1f + mov (sp)+,(sp) + mov (sp)+,(sp) +1: + mov r0,pc +9: + jmp succ + diff --git a/source/tmg/tmgb/bundle.s b/source/tmg/tmgb/bundle.s new file mode 100644 index 0000000..25cf68f --- /dev/null +++ b/source/tmg/tmgb/bundle.s @@ -0,0 +1,25 @@ +f = r5 +g = r4 +.globl g1 +.globl pbundle,iget +.globl succ +.globl bundle,reduce + +reduce: + jsr pc,iget + mov (r0),r1 + mov g,r0 + asl r1 + sub r1,r0 + br 1f + br 1f +bundle: + mov f,r0 + add $g1,r0 +1: + jsr pc,pbundle + tst r0 + beq 1f + mov r0,(g)+ +1: + jmp succ diff --git a/source/tmg/tmgb/char.s b/source/tmg/tmgb/char.s new file mode 100644 index 0000000..a76a74d --- /dev/null +++ b/source/tmg/tmgb/char.s @@ -0,0 +1,18 @@ +f = r5 +i = r3 +.globl j +.globl jget,iget +.globl char +.globl succ,fail + +char: + jsr pc,jget + bne 1f + tst (i)+ + jmp fail +1: + mov r0,-(sp) + jsr pc,iget + mov (sp)+,(r0) + inc j(f) + jmp succ diff --git a/source/tmg/tmgb/copy.s b/source/tmg/tmgb/copy.s new file mode 100644 index 0000000..f5446e5 --- /dev/null +++ b/source/tmg/tmgb/copy.s @@ -0,0 +1,36 @@ +f = r5 +i = r3 +.globl x,k +.globl ktab,ktat +.globl putcall,obuild +.globl errcom,succ,generate +.globl rewcstr,getcstr +.globl scopy + +scopy: + mov $2f+1,r0 + jsr pc,putcall + jsr pc,rewcstr + mov k(f),r2 + neg r2 + add $2,r2 +1: + jsr pc,getcstr + tst r0 + beq 1f + movb r0,ktab(r2) + inc r2 + cmp r2,$ktat + blt 1b + jsr r0,errcom + ;.even +1: + clrb ktab(r2) + bic $1,r2 + neg r2 + mov r2,k(f) + jmp succ +2: + mov i,r0 + jsr pc,obuild + jmp generate diff --git a/source/tmg/tmgb/cstr.s b/source/tmg/tmgb/cstr.s new file mode 100644 index 0000000..bffedaf --- /dev/null +++ b/source/tmg/tmgb/cstr.s @@ -0,0 +1,75 @@ +.globl jget,iget +.globl succ +.globl create,rewind,putchar,getchar,allocate +.globl smark +.globl rewcstr,putcstr,getcstr,size + +/ currnet string manipulations +/ keep a initial fragment handy for quick access +/go to allocator for the rest + +smark: + jsr pc,jget + clr cstrw + jmp succ + +rewcstr: + clr cstrr + rts pc + +putcstr: + mov cstrw,r1 + inc cstrw + cmp r1,$cstrt /is it quick access? + bge 1f + movb r0,cstrb(r1) /yes, stash the char + rts pc +1: + bne 1f + mov r0,-(sp) /first char to allocator + mov symp,r1 + bne 2f + mov $64,r0 + jsr pc,allocate + mov r1,symp +2: + jsr pc,create + mov (sp)+,r0 +1: + mov symp,r1 + jsr pc,putchar + rts pc + +getcstr: + mov cstrr,r1 + cmp r1,cstrw + blt 1f + clr r0 /end of string + rts pc +1: + inc cstrr + cmp r1,$cstrt + bge 1f + movb cstrb(r1),r0 + rts pc +1: + bne 1f + mov symp,r1 + jsr pc,rewind +1: + mov symp,r1 + jsr pc,getchar + rts pc + +size: + jsr pc,iget + mov cstrw,(r0) + jmp succ + +cstrt = 16 /top of quick access current string +.data +symp: 0 /pointer to dynamicallly allocated current string +cstrw: 0 /current string write pointer +.bss +cstrr: .=.+2 /read pointer +cstrb: .=.+cstrt /base of quick access fragment diff --git a/source/tmg/tmgb/ctest.s b/source/tmg/tmgb/ctest.s new file mode 100644 index 0000000..f5b5955 --- /dev/null +++ b/source/tmg/tmgb/ctest.s @@ -0,0 +1,24 @@ +f = r5 +.globl j +.globl classtab,jget +.globl ctest +.globl putcstr +.globl succ + +ctest: + inc ctestc + mov r0,-(sp) + jsr pc,jget + asl r0 + bit *(sp)+,classtab(r0) + clc + beq 1f + asr r0 + jsr pc,putcstr + inc j(f) + sec +1: + rts pc + +.data +ctestc: 0 diff --git a/source/tmg/tmgb/decmal.s b/source/tmg/tmgb/decmal.s new file mode 100644 index 0000000..77e769c --- /dev/null +++ b/source/tmg/tmgb/decmal.s @@ -0,0 +1,16 @@ +i = r3 +.globl putcall,iget,kput,putdec +.globl generate,succ +.globl decimal + +decimal: + mov $1f+1,r0 + jsr pc,putcall + jsr pc,iget + mov (r0),r0 + jsr pc,kput + jmp succ +1: + mov (i),r0 + jsr pc,putdec + jmp generate diff --git a/source/tmg/tmgb/discd.s b/source/tmg/tmgb/discd.s new file mode 100644 index 0000000..02d8970 --- /dev/null +++ b/source/tmg/tmgb/discd.s @@ -0,0 +1,9 @@ +.globl release +.globl discard +.globl iget,succ + +discard: + jsr pc,iget + mov (r0),r1 + jsr pc,release + jmp succ diff --git a/source/tmg/tmgb/emit.s b/source/tmg/tmgb/emit.s new file mode 100644 index 0000000..93f9dd8 --- /dev/null +++ b/source/tmg/tmgb/emit.s @@ -0,0 +1,42 @@ +f=r5 +g=r4 +.globl ofile +.globl dogen +.globl succ +.globl g1,k +.globl emit + +emit: + mov f,-(sp) + add $g1,(sp) + mov g,r1 +1: /look for a translation + cmp (sp),r1 + bge 3f /none at all + bit -(r1),$100001 + beq 1b + /move it to end of stak + mov (r1)+,r0 +1: + cmp g,r1 + ble 1f + mov (r1),-2(r1) + mov r0,(r1)+ + br 1b +1: + mov ofile,r0 + jsr pc,dogen + mov g,r1 +1: + cmp (sp),r1 /try to find prev value of k + bge 1f /nothing more in this stack frame + tst -(r1) + bge 1b /this isnt a k pointer (negative) + mov (r1),k(f) + br 3f +1: + mov f,r0 /go back to prev stack frame + mov k(r0),k(f) +3: + tst (sp)+ + jmp succ diff --git a/source/tmg/tmgb/end.s b/source/tmg/tmgb/end.s new file mode 100644 index 0000000..6dfc863 --- /dev/null +++ b/source/tmg/tmgb/end.s @@ -0,0 +1,3 @@ +.globl end +/ the driving tables ended just before here +end: diff --git a/source/tmg/tmgb/f.s b/source/tmg/tmgb/f.s new file mode 100644 index 0000000..bfa8a18 --- /dev/null +++ b/source/tmg/tmgb/f.s @@ -0,0 +1,13 @@ +.globl .f +.globl succ +.globl seekchar,getword + +.f: + mov (sp),r0 + mov r0,6(sp) + mov 4(sp),r1 + jsr pc,seekchar + jsr pc,getword + mov r0,(sp) + mov $-1,2(sp) + jmp succ diff --git a/source/tmg/tmgb/find.s b/source/tmg/tmgb/find.s new file mode 100644 index 0000000..596ea3e --- /dev/null +++ b/source/tmg/tmgb/find.s @@ -0,0 +1,93 @@ +i=r3 +.globl lptr,rptr,sptr +.globl succ,fail +.globl iget +.globl find,enter +.globl seekchar,getword,getchar +.globl putword,putchar,alterword +.globl getcstr,rewcstr +.globl length,rewind + +index=0 +tablep=2 +temp=4 +which=6 +framel=10 + +find: + mov pc,-(sp) /which(sp) + br 1f +enter: + clr -(sp) +1: + jsr pc,rewcstr + jsr pc,getcstr + bne 1f + tst (sp)+ + jmp fail +1: + clr -(sp) /temp(sp) + jsr pc,iget + mov (r0),-(sp) /tablep(sp) + clr -(sp) /index(sp) + +right: + add $rptr,index(sp) + br 1f +left: + add $lptr,index(sp) +1: /get index of next entry + mov tablep(sp),r1 + mov index(sp),r0 + jsr pc,seekchar + jsr pc,getword + tst r0 + beq nomore + mov r0,index(sp) + add $sptr,r0 + jsr pc,seekchar + jsr pc,rewcstr +1: /comparison loop + mov tablep(sp),r1 + jsr pc,getchar + mov r0,-(sp) + jsr pc,getcstr + cmp r0,(sp)+ + bgt right + blt left + tst r0 + beq found + br 1b + +nomore: /not in table + tst which(sp) + beq 1f + tst (i)+ /exit from find + add $framel,sp + jmp fail +1: + mov tablep(sp),r1 + jsr pc,length + mov r0,temp(sp) + clr r0 + jsr pc,putword /scratch word + jsr pc,putword /left pointer + jsr pc,putword /right + mov index(sp),r0 + jsr pc,seekchar + mov temp(sp),r0 + mov r0,index(sp) + jsr pc,alterword + jsr pc,rewcstr +1: /copy loop + jsr pc,getcstr + mov tablep(sp),r1 + jsr pc,putchar + tst r0 + bne 1b + +found: + jsr pc,iget + mov index(sp),(r0) + add $framel,sp + jmp succ diff --git a/source/tmg/tmgb/getnam.s b/source/tmg/tmgb/getnam.s new file mode 100644 index 0000000..33ef5af --- /dev/null +++ b/source/tmg/tmgb/getnam.s @@ -0,0 +1,50 @@ +i = r3 +.globl putcall,kput,obuild +.globl seekchar +.globl getchar +.globl outb, outw, outt +.globl cfile, lfile, flush +.globl iget +.globl sptr +.globl generate,succ +.globl getnam + +getnam: + mov $1f+1,r0 + jsr pc,putcall + jsr pc,iget + mov (r0),r0 + jsr pc,kput + jsr pc,iget + mov (r0),r0 + jsr pc,kput + jmp succ +1: + cmp cfile,lfile + beq 1f + jsr pc,flush + mov cfile,lfile +1: + mov (i)+,r1 + mov r1,-(sp) + mov (i)+,r0 + add $sptr,r0 + jsr pc,seekchar +2: + mov (sp),r1 + mov outw,r2 +1: + jsr pc,getchar + tst r0 + beq 1f + movb r0,outb(r2) + inc r2 + mov r2,outw + cmp r2,$outt + blt 1b +/ + jsr pc,flush + br 2b +1: + tst (sp)+ + jmp generate diff --git a/source/tmg/tmgb/ignore.s b/source/tmg/tmgb/ignore.s new file mode 100644 index 0000000..f7cb1a1 --- /dev/null +++ b/source/tmg/tmgb/ignore.s @@ -0,0 +1,9 @@ +f = r5 +.globl n +.globl succ,iget +.globl ignore + +ignore: + jsr pc,iget + mov (r0),n(f) + jmp succ diff --git a/source/tmg/tmgb/inc.s b/source/tmg/tmgb/inc.s new file mode 100644 index 0000000..73801ca --- /dev/null +++ b/source/tmg/tmgb/inc.s @@ -0,0 +1,24 @@ +.globl succ,.u,update +.globl .ia,.ib,.da,.db + +/prefix ++ +.ib: + inc (sp) + jmp .u +/prefix -- +.db: + dec (sp) + jmp .u +/postfix++ +.ia: + inc (sp) + jsr pc,update + dec (sp) + jmp succ +/potsfix -- +.da: + dec (sp) + jsr pc,update + inc (sp) + jmp succ + diff --git a/source/tmg/tmgb/infix.s b/source/tmg/tmgb/infix.s new file mode 100644 index 0000000..c1d5e81 --- /dev/null +++ b/source/tmg/tmgb/infix.s @@ -0,0 +1,35 @@ +.globl .p,sprv +.globl .a,.s,.o,.n,.x + +/ + +.a: + jsr pc,sprv + add (sp),4(sp) + br 9f + +/ - +.s: + jsr pc,sprv + sub (sp),4(sp) + br 9f + +/ | +.o: + jsr pc,sprv + bis (sp),4(sp) + br 9f + +/ & +.n: + jsr pc,sprv + com (sp) + bic (sp),4(sp) + br 9f + +/ ^ exclusive or +.x: + jsr pc,sprv + mov (sp),r0 + xor r0,4(sp) +9: + jmp .p diff --git a/source/tmg/tmgb/jget.s b/source/tmg/tmgb/jget.s new file mode 100644 index 0000000..a3fcc43 --- /dev/null +++ b/source/tmg/tmgb/jget.s @@ -0,0 +1,46 @@ +f = r5 +.globl j,n +.globl input +.globl classtab +.globl jget + +jget: + inc jgetc +3: + mov j(f),r1 + mov r1,r0 + bic $inpt-1,r0 + bic r0,r1 + cmp r0,inpr + beq 1f + inc readc + mov r0,inpr + mov input,r0 + sys seek +inpr: 1;0 + sys read;inpb;inpt +2: + cmp r0,$inpt + bge 1f + clrb inpb(r0) + inc r0 + br 2b +1: + movb inpb(r1),r0 + asl r0 + bit n(f),classtab(r0) + beq 1f + inc j(f) + inc r1 + cmp r1,$inpt + blt 1b + br 3b +1: + asr r0 + rts pc +inpt = 128. +.bss +inpb: . = .+inpt +.data +jgetc: 0 +readc: 0 diff --git a/source/tmg/tmgb/lvrv.s b/source/tmg/tmgb/lvrv.s new file mode 100644 index 0000000..afa385c --- /dev/null +++ b/source/tmg/tmgb/lvrv.s @@ -0,0 +1,15 @@ +.globl .lv,.rv +.globl succ + +/ unary & + +.lv: + mov 2(sp),(sp) + jmp succ + +/ * + +.rv: + mov (sp),2(sp) + mov *2(sp),(sp) + jmp succ diff --git a/source/tmg/tmgb/mult.s b/source/tmg/tmgb/mult.s new file mode 100644 index 0000000..7e9452e --- /dev/null +++ b/source/tmg/tmgb/mult.s @@ -0,0 +1,26 @@ +.globl .m,.q,.r +.globl .p,sprv + +.m: + jsr pc,sprv + mov (sp),r0 + mpy 4(sp),r0 + mov r1,4(sp) + br 1f + +.q: + jsr pc,sprv + mov 4(sp),r1 + sxt r0 + dvd (sp),r0 + mov r0,4(sp) + br 1f + +.r: + jsr pc,sprv + mov 4(sp),r1 + sxt r0 + dvd (sp),r0 + mov r1,4(sp) +1: + jmp .p diff --git a/source/tmg/tmgb/octal.s b/source/tmg/tmgb/octal.s new file mode 100644 index 0000000..47ade75 --- /dev/null +++ b/source/tmg/tmgb/octal.s @@ -0,0 +1,16 @@ +i = r3 +.globl putcall,iget,kput,putoct +.globl generate,succ +.globl octal + +octal: + mov $1f+1,r0 + jsr pc,putcall + jsr pc,iget + mov (r0),r0 + jsr pc,kput + jmp succ +1: + mov (i),r0 + jsr pc,putoct + jmp generate diff --git a/source/tmg/tmgb/params.s b/source/tmg/tmgb/params.s new file mode 100644 index 0000000..97ae7b3 --- /dev/null +++ b/source/tmg/tmgb/params.s @@ -0,0 +1,13 @@ +f = r5 +.globl iget +.globl env,si +.globl succ +.globl params + +params: + jsr pc,iget + mov (r0),r0 + asl r0 + mov env(f),r1 + add r0,si(r1) + jmp succ diff --git a/source/tmg/tmgb/push.s b/source/tmg/tmgb/push.s new file mode 100644 index 0000000..64048ca --- /dev/null +++ b/source/tmg/tmgb/push.s @@ -0,0 +1,25 @@ +.globl succ +.globl iget +.globl push + +push: + jsr pc,iget + mov (r0),r2 + mov r2,r1 +1: + mov r1,-(sp) + jsr pc,iget + mov (sp)+,r1 + mov r0,-(sp) + mov (r0),-(sp) + dec r2 + bgt 1b + mov r1,-(sp) + jsr pc,succ +/ preserve c bit from here on + mov (sp)+,r2 +1: + mov (sp)+,*(sp)+ + dec r2 + bgt 1b + rts pc /pass sret or fret back to invoking rule diff --git a/source/tmg/tmgb/putcal.s b/source/tmg/tmgb/putcal.s new file mode 100644 index 0000000..bfedd93 --- /dev/null +++ b/source/tmg/tmgb/putcal.s @@ -0,0 +1,23 @@ +f = r5 +g = r4 +.globl k +.globl errcom +.globl ktab,ktat +.globl putcall,kput + +putcall: + jsr pc,kput + mov k(f),(g)+ + rts pc + +kput: + sub $2,k(f) + mov k(f),r1 + neg r1 + mov r0,ktab(r1) + cmp r1,$ktat + bhis 1f + rts pc +1: + jsr r0,errcom + ;.even diff --git a/source/tmg/tmgb/putdec.s b/source/tmg/tmgb/putdec.s new file mode 100644 index 0000000..efb6f9d --- /dev/null +++ b/source/tmg/tmgb/putdec.s @@ -0,0 +1,29 @@ +.globl putch,obuild +.globl putdec + +putdec: + tst r0 + bge 1f + cmp r0,$100000 + beq 2f + mov r0,-(sp) + mov $'-,r0 + jsr pc,putch + mov (sp)+,r0 + neg r0 +1: + alsc $-16.,r0 + dvd $10.,r0 + beq 1f + mov r1,-(sp) + jsr pc,1b + mov (sp)+,r1 +1: + mov r1,r0 + add $'0,r0 + jmp putch +2: + mov $1f,r0 + jmp obuild +1: + <-32768\0>;.even diff --git a/source/tmg/tmgb/putoct.s b/source/tmg/tmgb/putoct.s new file mode 100644 index 0000000..c77641d --- /dev/null +++ b/source/tmg/tmgb/putoct.s @@ -0,0 +1,18 @@ +.globl putch,obuild +.globl putoct + + +putoct: mov r0,-(sp) + bic $7,r0 + bic r0,(sp) + clc + ror r0 + ror r0 + ror r0 + beq 1f + jsr pc,putoct +1: + mov (sp)+,r0 + add $'0,r0 + jsr pc,putch + rts pc diff --git a/source/tmg/tmgb/px.s b/source/tmg/tmgb/px.s new file mode 100644 index 0000000..aa88da2 --- /dev/null +++ b/source/tmg/tmgb/px.s @@ -0,0 +1,38 @@ +f = r5 +i = r3 +.globl j,n +.globl iget,jget +.globl succ,fail +.globl .px,.pxs + +.pxs: + mov i,r0 + tst (i)+ + br 1f +.px: + jsr pc,iget +1: + inc litc + mov n(f),-(sp) + mov j(f),-(sp) + mov r0,-(sp) +2: + tstb *(sp) + beq 2f + jsr pc,jget + cmpb r0,*(sp) + beq 1f + tst (sp)+ + mov (sp)+,j(f) + mov (sp)+,n(f) + jmp fail +1: + clr n(f) + inc (sp) + inc j(f) + br 2b +2: + cmp (sp)+,(sp)+ + mov (sp)+,n(f) + jmp succ +litc: 0 diff --git a/source/tmg/tmgb/reln.s b/source/tmg/tmgb/reln.s new file mode 100644 index 0000000..68c1ad5 --- /dev/null +++ b/source/tmg/tmgb/reln.s @@ -0,0 +1,45 @@ +.globl .p,sprv +.globl .eq,.ne,.lt,.le,.gt,.ge + +.eq: + jsr pc,sprv + cmp 4(sp),(sp) + beq true + br false + +.ne: + jsr pc,sprv + cmp 4(sp),(sp) + bne true + br false +.lt: + jsr pc,sprv + cmp 4(sp),(sp) + blt true + br false + +.le: + jsr pc,sprv + cmp 4(sp),(sp) + ble true + br false + +.gt: + jsr pc,sprv + cmp 4(sp),(sp) + bgt true + br false + +.ge: + jsr pc,sprv + cmp 4(sp),(sp) + bge true + br false + +true: + mov $1,4(sp) + jmp .p + +false: + clr 4(sp) + jmp .p diff --git a/source/tmg/tmgb/shift.s b/source/tmg/tmgb/shift.s new file mode 100644 index 0000000..ef213b1 --- /dev/null +++ b/source/tmg/tmgb/shift.s @@ -0,0 +1,14 @@ +.globl .p,sprv +.globl .sr,.sl + +/ >> +.sr: + neg (sp) + +/ << +.sl: + mov 4(sp),r1 + clr r0 + alsc (sp),r0 + mov r1,4(sp) + jmp .p diff --git a/source/tmg/tmgb/stack.s b/source/tmg/tmgb/stack.s new file mode 100644 index 0000000..a14be79 --- /dev/null +++ b/source/tmg/tmgb/stack.s @@ -0,0 +1,76 @@ +/ builtins for shift-reduce parsking +f = r5 +i = r3 +g = r4 +.globl succ,pbundle,goto,iget +.globl g1 +.globl stack,unstack,gotab,accept + +/stack label of present rule (state) +/should come first in a rule + +stack: + mov i,(g) + sub $2,(g)+ + jmp succ + +/unstack(n) deletes last n stacked states +/states are distinguishable from translations in not having +/an exit bit ($1) nor being bundles ($100000) +unstack: + jsr pc,iget + mov (r0),r0 + mov g,r1 +1: + bit -(r1),$100001 + bne 1b + dec r0 + bge 1b + tst (r1)+ + br 1f + +accept: /clean out all states from stack + mov f,r1 + add $g1,r1 +1: + mov r1,r0 + mov r1,-(sp) +1: + cmp r1,g + bge 2f + bit (r1)+,$100001 + beq 1b + mov -2(r1),(r0)+ + br 1b +2: + mov r0,g + mov (sp)+,r0 + jsr pc,pbundle + tst r0 + beq 1f + mov r0,(g)+ +1: + jmp succ + +/gotab(s1,t1,s2,t2,...sn,tn,0,t) +/checks top of stack for states +/s1,s2,... and goes to t1, t2 accordingly +/if top of stack is not in table, goes to t + +gotab: + mov g,r0 +1: + bit -(r0),$100001 /find top state + bne 1b + mov (r0),-(sp) +1: + jsr pc,iget + tst (r0) + beq 1f + cmp (sp),r0 + beq 1f + jsr pc,iget + br 1b +1: + tst (sp)+ + jmp goto diff --git a/source/tmg/tmgb/string.s b/source/tmg/tmgb/string.s new file mode 100644 index 0000000..b2a3fc5 --- /dev/null +++ b/source/tmg/tmgb/string.s @@ -0,0 +1,18 @@ +f = r5 +i = r3 +.globl j +.globl succ +.globl ctest,iget +.globl string + +string: + tst -(sp) + jsr pc,iget +1: + mov j(f),(sp) + mov r0,-(sp) + jsr pc,ctest + mov (sp)+,r0 + bcs 1b + mov (sp)+,j(f) + jmp succ diff --git a/source/tmg/tmgb/table.s b/source/tmg/tmgb/table.s new file mode 100644 index 0000000..465f8a3 --- /dev/null +++ b/source/tmg/tmgb/table.s @@ -0,0 +1,17 @@ +.globl allocate,putword,putchar +.globl iget +.globl succ +.globl table + +table: + mov $10,r0 + jsr pc,allocate + mov r1,-(sp) + clr r0 + jsr pc,putword + jsr pc,putword + jsr pc,putword + jsr pc,putchar + jsr pc,iget + mov (sp)+,(r0) + jmp succ diff --git a/source/tmg/tmgb/tq.s b/source/tmg/tmgb/tq.s new file mode 100644 index 0000000..31908f2 --- /dev/null +++ b/source/tmg/tmgb/tq.s @@ -0,0 +1,28 @@ +f = r5 +i = r3 +.globl ek,ep,ek.fs,ep.fs,si,x,fs +.globl generate +.globl .tq,gpar + +.tq: + mov (i)+,r0 + mov i,si(f) + mov ep(f),r1 + mov ep(r1),ep.fs(f) + mov ek(r1),ek.fs(f) + mov si(r1),r1 + asl r0 + sub r0,r1 + mov (r1),i + add $fs,f + clr x(f) + jsr pc,generate + jmp generate + +gpar: + mov (i)+,r0 + mov ep(f),r1 + asl r0 + add r0,si(r1) + jmp generate +.globl gq;gq=.tq diff --git a/source/tmg/tmgb/trace.s b/source/tmg/tmgb/trace.s new file mode 100644 index 0000000..8d33791 --- /dev/null +++ b/source/tmg/tmgb/trace.s @@ -0,0 +1,14 @@ +i = r3 +.globl putch,putoct +.globl trswitch +.globl trace + +trace: + jsr pc,putch + mov i,r0 + jsr pc,putoct + mov $'\n,r0 + jsr pc,putch + rts pc +.data +trswitch: 0 diff --git a/source/tmg/tmgb/trans.s b/source/tmg/tmgb/trans.s new file mode 100644 index 0000000..4ad0f6c --- /dev/null +++ b/source/tmg/tmgb/trans.s @@ -0,0 +1,8 @@ +g = r4 +.globl succ,iget +.globl trans + +trans: + jsr pc,iget + mov r0,(g)+ + jmp succ diff --git a/source/tmg/tmgb/tx.s b/source/tmg/tmgb/tx.s new file mode 100644 index 0000000..16fe4f5 --- /dev/null +++ b/source/tmg/tmgb/tx.s @@ -0,0 +1,14 @@ +i = r3 +.globl generate +.globl obuild +.globl .tx,.txs + +.txs: + mov i,r0 + tst (i)+ + br 1f +.tx: + mov (i)+,r0 +1: + jsr pc,obuild + jmp generate diff --git a/source/tmg/tmgb/unary.s b/source/tmg/tmgb/unary.s new file mode 100644 index 0000000..07278b6 --- /dev/null +++ b/source/tmg/tmgb/unary.s @@ -0,0 +1,27 @@ +.globl succ +.globl .ng,.nt,.cm + +/ ! + +.nt: + tst (sp) + beq 1f + clr (sp) + br 9f +1: + mov $1,(sp) + br 9f + +/unary - + +.ng: + neg (sp) + br 9f + +/ ~ + +.cm: + com (sp) + +9: + jmp succ diff --git a/source/tmg/tmgc.s b/source/tmg/tmgc.s new file mode 100644 index 0000000..2cf927f --- /dev/null +++ b/source/tmg/tmgc.s @@ -0,0 +1,71 @@ +/ tmg tables and global definitions + +/ in addition to these definitions each routine +/ follows the convention +/ f = stack frame pointer during parse and translation +/ g = stack frame end during parse +/ i = interprested instruction counter during parse and translation + +.globl tables +.globl x,si,j,k,n,g1,env +.globl ek,ek.fs,ep,ep.fs,fs +.globl lptr,sptr,rptr +.globl outb,outt,outw +.globl stkt,stkb,stke +.globl ktat,ktab +.globl input,cfile,lfile,dfile,ofile + +/ parse stack frame layout +/ 0 is previous frame pointer +/ return address in (sp) +x = 2. /exit bit, nonzero at end of rule +si = 4. / save location for instruction counter +j = 6. / input cursor counts characters +k = 8. / ktable water mark, last use location relative to base +n = 10. /address of ignored character class +env = 12. / frame pointer for static environment +g1 = 14. / frame length during parse + +/symbol table entry layout +/word 0 is for customer +lptr=2. /index of next entry on tree to left +rptr=4. /index of next entry to right +sptr=6. /first character of string in this entry + /next char is in 7, etc + +/ translation frame layout +/ used as ek(f), ep(f), etc +/ x and si have same meaning as in parse stack frame +/ return address in (sp) +ek = 0 / k environment, frame where bunlde address is in si +ep = 6 / p environment, frame where si points to parameter list +fs = 10 / frame size +ek.fs = ek+fs / k environment in next frame +ep.fs = ep+fs / p env in next frame + +.data + +tables = . /marks break between routines and tables + +outt = 64. / output buffer top +stkt = 800. /stack top for (f), not for (sp) +ktat = 1200. / k table top + + +input: -1 / stream number of input +cfile: 1 / stream number of current output +lfile: 1 / last current output +dfile: 2 / diagnostic file +ofile: 1 /output file + + +outw: 0 / output write pointer, number of chars in buffer +.bss +outb: .=.+outt /output buffer + + + +ktab: . = .+ktat / contains translation rules that have been bundled + +stkb: . = .+stkt / stack, (f) ponts into this +stke = . /stack end diff --git a/source/tmg/tmgl.s b/source/tmg/tmgl.s new file mode 100644 index 0000000..1d6c200 --- /dev/null +++ b/source/tmg/tmgl.s @@ -0,0 +1,2098 @@ +1 ..1 +..1:begin: + +ignore +blanks +pr1: +comment +salt;pr1 +parse +first +salt;pr2 +diag +error +pr2: +comment +salt;pr2 +parse +line +salt;pr2 +diag +error +salt;pr2 +putcharcl +1 parse +last +.3=. +<1 \0>;.even +.2=. +.tx;.3 +.tp;.byte 1,0; +1 .tn +.1=. +fref +1 trans;1 .2 +.4=. +.tp;.byte 2,0; +.txs;': +1 .tp;.byte 1,0; +first: + +parse +.1 +getfref +line +1 trans;1 .4 +.1=. +1 +.2=. +2 +.3=. +1 .txs;'; +.5=. +;.even +.4=. +.tn +.tx;.5 +.tp;.byte 2,0; +.tp;.byte 1,0; +1 .tn +error: + +smark +ignore +none +any +.1 +string +.2 +scopy +.pxs;'; +alt;..3 +trans;1 .3 +goto;..2 +..3:null +..2: +1 trans;1 .4 +.1=. +.tp;.byte 2,0; +.tn +.tp;.byte 1,0; +1 .tn +line: + +labels +charcl +alt;..7 +.pxs;'; +goto;..4 +..7:statement +salt;..5 +numbers +salt;..6 +trule +.pxs;'; +..6: +..5: +..4: +1 trans;1 .1 +.1=. +.tp;.byte 2,0; +.tn +1 .tp;.byte 1,0; +numbers: + +number +.pxs;'; +numbers +alt;done +1 trans;1 .1 +.1=. +.tp;.byte 2,0; +.tn +1 .tp;.byte 1,0; +labels: + +label +labels +alt;done +1 trans;1 .1 +.1=. +.tp;.byte 1,0; +1 .txs;': +label: + +name +.pxs;': +1 trans;1 .1 +.2=. +<.pn:1 .pxs;12\0>;.even +.3=. +<.tn:1 .txs;12\0>;.even +.1=. +.tx;.2 +.tn +.tx;.3 +1 .tn +last: + +1 trans;1 .1 +.1=. +;.even +.2=. +4 +comment: + +.px;.1 +co1: +ignore +.2 +.pxs;'* +ignore +none +.pxs;'/ +1 alt;co1 +.1=. +0 +.2=. +gpar;1 +.tp;.byte 2,0; +1 .tp;.byte 1,0; +.3=. +gpar;1 +1 generate +.4=. +gpar;1 +.tp;.byte 2,0;nil +.tn +1 .tp;.byte 1,0;q1 +.5=. +1 .tp;.byte 1,0;xbit +.7=. +<1 succ\0>;.even +.6=. +.tp;.byte 1,0;nil +.tn +1 .tx;.7 +statement: + +.l;csym +.l;.1 +.st +.p +oldtab +dtt +oldtab +pat +proc +alt;..11 +plst +tlst +.pxs;') +trans;1 .2 +goto;..10 +..11:trans;1 .3 +noelem +..10: +stt1: +bundle +frag +alt;..15 +trans;1 .4 +salt;stt1 +goto;..12 +..15:.pxs;'; +ifelem +alt;..14 +trans;1 .5 +goto;..13 +..14:trans;1 .6 +..13: +..12: +1 succ +.1=. +;.even +proc: + +smark +ignore +none +1 .px;.1 +.1=. +1 octal +npa +.3=. +;.even +.2=. +.tx;.3 +.tp;.byte 1,0; +1 .tn +plst: + +list +pident +alt;null +remote +.1 +1 trans;1 .2 +pident: + +ident +1 newtab +pat +npa +.1=. +0 +.2=. +name +.l;i +.ia +1 .p +.3=. +1 octal +i +.5=. +;.even +.4=. +.tx;.5 +.tp;.byte 1,0; +.tn +.tp;.byte 2,0; +1 .tn +tlst: + +.pxs;'; +alt;null +.l;i +.l;.1 +.st +.p +list +.2 +remote +.3 +1 trans;1 .4 +.1=. +gpar;1 +1 .tp;.byte 1,0;nil +q1 +.2=. +gpar;1 +1 .tp;.byte 1,0; +frag: + +prule +alt;..17 +trans;1 .1 +goto;..16 +..17:labels +noelem +trans;1 .2 +..16: +1 succ +.2=. +;.even +.1=. +gpar;2 +.tp;.byte 3,0;nil +nil +.tn +.tx;.2 +.tp;.byte 2,0; +.tn +.tp;.byte 1,0;q2 +q1 +.tn +.tp;.byte 2,0; +1 .txs;': +.5=. +;.even +.4=. +.tn +.tx;.5 +1 .tp;.byte 1,0; +.6=. +;.even +.3=. +gpar;2 +.tp;.byte 4,0;.4 +q1 +.tn +.tx;.6 +.tp;.byte 3,0; +.tn +.tp;.byte 1,0; +.txs;': +.tp;.byte 2,0;q2 +q1 +.tn +.tp;.byte 3,0; +1 .txs;': +prule: + +.l;sndt +.l;ndt +.st +.p +disj +.pxs;'| +alt;..23 +.l;ndt +.l;sndt +.st +.p +fref +ifeasy +alt;..21 +prule +trans;1 .1 +goto;..20 +..21:prule +fref +trans;1 .3 +..20: +noelem +goto;..22 +..23: +..22: +1 succ +.1=. +gpar;2 +.tp;.byte 2,0;q2 +nil +.tn +1 .tp;.byte 1,0;nil +q1 +disj: + +pelem +pdot +disj +alt;..25 +trans;1 .1 +ifelem +alt;done +ishard +goto;..24 +..25: +..24: +1 succ +.1=. +gpar;2 +.tp;.byte 1,0;q1 +1 .tq;2 +.2=. +1 +.3=. +gpar;2 +1 generate +pelem: + +pprim +alt;..31 +trans;1 .1 +iseasy +goto;..26 +..31:.pxs;'( +push +.2 +sndt +prule +alt;..30 +.pxs;') +goto;..27 +..30:.pxs;') +trans;1 .3 +noelem +..27: +..26: +1 succ +.1=. +gpar;1 +.tq;1 +.tp;.byte 2,0; +.tn +1 .tp;.byte 1,0; +.2=. +gpar;1 +.tq;1 +1 .tp;.byte 1,0; +.4=. +;.even +.3=. +1 .tx;.4 +.5=. +<\\\0>;.even +.7=. +;.even +.6=. +1 .tx;.7 +.10=. +gpar;1 +.tp;.byte 3,0;nil +.tn +.tq;1 +.tp;.byte 2,0; +1 .tp;.byte 1,0; +pprim: + +special +salt;..32 +rname +.pxs;': +alt;..37 +fail +goto;..33 +..37:spdot +salt;..34 + +..34: +ignore +none +.pxs;'( +alt;..36 +ignore +blanks +list +parg +.pxs;') +trans;1 .1 +goto;..35 +..36:trans;1 .2 +..35: +..33: +..32: +.pxs;'/ +alt;..41 +trans;1 .3 +goto;..40 +..41:.px;.5 +alt;..43 +trans;1 .6 +..40: +rname +trans;1 .10 +goto;..42 +..43: +..42: +1 succ +.2=. +0 +pdot: + +.pxs;'. +alt;done +ignore +none +ident +salt;alias +.l;dtt +.t +salt;..44 +table +dtt +.l;ndt +.l;.2 +.st +.p +..44: +.l;ndt +.ia +1 .p +.1=. +1 any +letter +spdot: + +.pxs;'. +ignore +none +not +.1 +alias: +1 newtab +dtt +ndt +parg: + +rname +salt;..45 +remote +specparg +..45: +1 succ +.2=. +<\\n\\0\0>;.even +.1=. +1 .tx;.2 +.4=. +<1 succ\0>;.even +.3=. +1 .tx;.4 +.5=. +3 +.6=. +0 +.7=. +1 .tp;.byte 1,0;nil +xbit +.11=. +<1 succ\0>;.even +.10=. +.tp;.byte 1,0;nil +nil +.tn +1 .tx;.11 +specparg: + +number +salt;..46 +charcl +salt;..47 +.pxs;'< +alt;..57 +longlit +goto;..50 +..57:.pxs;'* +alt;..56 +trans;1 .1 +goto;..51 +..56:.pxs;'( +.pxs;') +alt;..55 +trans;1 .3 +goto;..52 +..55:push +.5 +dtt +ndt +sndt +.l;dtt +.l;.6 +.st +.p +prule +.pxs;') +oldtab +dtt +ifelem +alt;..54 +trans;1 .7 +goto;..53 +..54:trans;1 .10 +..53: +..52: +..51: +..50: +..47: +..46: +1 succ +.1=. +1 +iseasy: + +.l;easy +.l;.1 +.st +1 .p +.1=. +0 +ishard: + +.l;easy +.l;.1 +.st +1 .p +.1=. +2 +noelem: + +.l;easy +.l;.1 +.st +1 .p +.1=. +2 +ifelem: + +.l;easy +.l;.1 +.ne +1 .t +.2=. +1 +ifeasy: + +.l;easy +.l;.2 +.eq +1 .t +.2=. +;.even +.1=. +gpar;1 +.tq;1 +.tx;.2 +1 .tp;.byte 1,0; +.4=. +<.px\0>;.even +.3=. +gpar;1 +.tq;1 +.tx;.4 +1 .tp;.byte 1,0; +.6=. +<.pn\0>;.even +.5=. +gpar;1 +.tq;1 +1 .tx;.6 +.10=. +<.t\0>;.even +.7=. +1 .tx;.10 +.12=. +<.p\0>;.even +.11=. +1 .tx;.12 +.13=. +gpar;1 +.tp;.byte 2,0; +.tn +.tq;1 +1 .tp;.byte 1,0; +special: + +.pxs;'= +alt;..70 +rname +salt;..60 +remote +trule +..60: +trans;1 .1 +goto;..61 +..70:.pxs;'< +alt;..67 +literal +trans;1 .3 +goto;..62 +..67:.pxs;'* +alt;..66 +trans;1 .5 +goto;..63 +..66:.pxs;'[ +expr +.pxs;'? +alt;..65 +trans;1 .7 +goto;..64 +..65:trans;1 .11 +..64: +.pxs;'] +trans;1 .13 +..63: +..62: +..61: +1 succ +.2=. +<[-\0>;.even +.3=. +<\\<1]\0>;.even +.1=. +.tx;.2 +.tp;.byte 1,0; +1 .tx;.3 +rname: + +name +alt;..72 +tabval +pat +npa +alt;done +goto;..71 +..72:.pxs;'$ +number +..71: +1 trans;1 .1 +.2=. +;.even +.1=. +.tx;.2 +.tp;.byte 2,0; +.tn +1 .tp;.byte 1,0; +trule: + +oldtab +ptt +tbody +salt;..73 +.pxs;'( +number +salt;..74 +tra +..74: +.pxs;') +tbody +trans;1 .1 +..73: +1 succ +tra: + +list +tident +1 octal +npt +tident: + +ident +1 newtab +ptt +npt +.2=. +<1 generate\0>;.even +.1=. +1 .tx;.2 +tbody: + +.pxs;'{ +.pxs;'} +alt;..76 +trans;1 .1 +goto;..75 +..76:trb +..75: +1 succ +.1=. +xbit +1 .tp;.byte 1,0; +.2=. +.tp;.byte 2,0; +.tn +1 .tp;.byte 1,0; +trb: + +telem +.pxs;'} +alt;..100 +trans;1 .1 +goto;..77 +..100:trb +trans;1 .2 +..77: +1 succ +.2=. +<.tx\0>;.even +.1=. +.tx;.2 +1 .tp;.byte 1,0; +.4=. +<.tn\0>;.even +.3=. +1 .tx;.4 +.6=. +<.tq;\0>;.even +.5=. +.tx;.6 +1 .tp;.byte 1,0; +telem: + +.pxs;'< +alt;..110 +literal +trans;1 .1 +goto;..101 +..110:.pxs;'* +alt;..107 +trans;1 .3 +goto;..102 +..107:.pxs;'$ +alt;..106 +number +trans;1 .5 +goto;..103 +..106:number +alt;..105 +tdot +trans;1 tpt +goto;..104 +..105:name +te1 +salt;done +te2 +salt;done +..104: +..103: +..102: +..101: +1 succ +te1: + +tabval +dtt +ndt +tdot +1 trans;1 tpt +.2=. +<.tq;\0>;.even +.1=. +.tx;.2 +1 .tp;.byte 1,0; +te2: + +tabval +ptt +npt +1 trans;1 .1 +.1=. +1 .txs;'0 +.2=. +.tp;.byte 2,0; +.txs;'; +1 .tp;.byte 1,0; +tdot: + +.pxs;'. +alt;..112 +number +goto;..111 +..112:trans;1 .1 +..111: +.pxs;'( +alt;..114 +list +targ +.pxs;') +goto;..113 +..114:null +..113: +1 trans;1 .2 +targ: + +name +salt;..115 +remote +tbody +..115: +1 succ +.1=. +<.tp;.byte \0>;.even +tpt: +.tx;.1 +.tp;.byte 2,0; +.txs;', +1 .tp;.byte 1,0; +.1=. +.txs;'; +1 .tp;.byte 1,0; +literal: + +shortlit +salt;..116 +remote +longlit +trans;1 .1 +..116: +1 succ +.1=. +<\>\0>;.even +.3=. +;.even +.2=. +.tx;.3 +1 .tp;.byte 1,0; +shortlit: + +ignore +none +smark +any +litch +.px;.1 +scopy +1 trans;1 .2 +.1=. +<\>\0>;.even +.3=. +<\\\0>;.even +.4=. +<\>\0>;.even +.2=. +.tx;.3 +1 .tx;.4 +.5=. +<\>\0>;.even +.7=. +<\\0\0>;.even +.10=. +<\>;.even\0>;.even +.6=. +.txs;'< +.tp;.byte 2,0; +.tp;.byte 1,0; +.tx;.7 +1 .tx;.10 +longlit: + +ignore +none +.px;.1 +alt;..120 +trans;1 .2 +goto;..117 +..120:null +..117: +litb +.px;.5 +1 trans;1 .6 +.1=. +<\\\0>;.even +.3=. +<\\\\\0>;.even +.2=. +.tp;.byte 2,0; +.tx;.3 +1 .tp;.byte 1,0; +litb: + +smark +string +litch +scopy +.px;.1 +alt;done +litb +1 trans;1 .2 +expr: + +assignment +salt;..121 +rv +..121: +1 succ +.1=. +.tp;.byte 3,0; +.tn +.tp;.byte 1,0; +.tn +1 .tp;.byte 2,0; +assignment: + +lv +assign +expr +1 trans;1 .1 +.1=. +.tp;.byte 3,0; +.tn +.tp;.byte 1,0; +.tn +1 .tp;.byte 2,0; +.2=. +.tp;.byte 2,0; +.tn +1 .tp;.byte 1,0; +rv: + +prime +rv1: +bundle +infix +alt;..125 +prime +trans;1 .1 +salt;rv1 +goto;..122 +..125:rva +alt;..124 +trans;1 .2 +goto;..123 +..124: +..123: +..122: +1 succ +.2=. +<.t;alt;\0>;.even +.3=. +;.even +.1=. +.tx;.2 +.tp;.byte 2,0; +.tn +.tp;.byte 4,0; +.tn +.tx;.3 +.tp;.byte 1,0; +.tn +.tp;.byte 2,0; +.txs;': +.tp;.byte 3,0; +.tn +.tp;.byte 1,0; +1 .txs;': +rva: + +.pxs;'? +rv +.pxs;': +rv +fref +fref +1 trans;1 .1 +.1=. +.tp;.byte 2,0; +.tn +1 .tp;.byte 1,0; +.2=. +.tp;.byte 1,0; +.tn +1 .tp;.byte 2,0; +.3=. +.tp;.byte 1,0; +.tn +1 .tp;.byte 2,0; +.5=. +<.l;\0>;.even +.4=. +.tx;.5 +1 .tp;.byte 1,0; +prime: + +lv +alt;..135 +suffix +alt;done +trans;1 .1 +goto;..126 +..135:prefix +alt;..134 +lv +trans;1 .2 +goto;..127 +..134:.pxs;'( +alt;..133 +expr +.pxs;') +goto;..130 +..133:unary +alt;..132 +prime +trans;1 .3 +goto;..131 +..132:remote +number +trans;1 .4 +..131: +..130: +..127: +..126: +1 succ +.2=. +<.l;\0>;.even +.1=. +.tx;.2 +1 .tp;.byte 1,0; +.4=. +<.rv\0>;.even +.3=. +.tp;.byte 1,0; +.tn +1 .tx;.4 +.6=. +<.f\0>;.even +.5=. +.tp;.byte 2,0; +.tn +.tp;.byte 1,0; +.tn +1 .tx;.6 +lv: + +rname +alt;..141 +trans;1 .1 +goto;..136 +..141:.pxs;'( +alt;..140 +lv +.pxs;') +goto;..137 +..140:.pxs;'* +prime +trans;1 .3 +..137: +..136: +lv1: +.pxs;'[ +alt;done +bundle +expr +.pxs;'] +trans;1 .5 +1 salt;lv1 +.2=. +<.u\0>;.even +.1=. +.tp;.byte 1,0; +.tn +1 .tx;.2 +.4=. +<.st\0>;.even +.3=. +1 .tx;.4 +assign: + +.pxs;'= +ignore +none +infix +alt;..143 +trans;1 .1 +goto;..142 +..143:trans;1 .3 +..142: +1 succ +.2=. +1 .pxs;'+ +.1=. +.pxs;'+ +1 not +.2 +.4=. +<.a\0>;.even +.3=. +1 .tx;.4 +.6=. +<.s\0>;.even +.5=. +1 .tx;.6 +.10=. +<.m\0>;.even +.7=. +1 .tx;.10 +.12=. +<.q\0>;.even +.11=. +1 .tx;.12 +.14=. +<.r\0>;.even +.13=. +1 .tx;.14 +.16=. +<.o\0>;.even +.15=. +1 .tx;.16 +.20=. +<.x\0>;.even +.17=. +1 .tx;.20 +.22=. +<.n\0>;.even +.21=. +1 .tx;.22 +.23=. +<==\0>;.even +.25=. +<.eq\0>;.even +.24=. +1 .tx;.25 +.26=. +;.even +.30=. +<.ne\0>;.even +.27=. +1 .tx;.30 +.31=. +<<=\0>;.even +.33=. +<.le\0>;.even +.32=. +1 .tx;.33 +.34=. +<\>=\0>;.even +.36=. +<.ge\0>;.even +.35=. +1 .tx;.36 +.37=. +<<<\0>;.even +.41=. +<.sl\0>;.even +.40=. +1 .tx;.41 +.43=. +<.lt\0>;.even +.42=. +1 .tx;.43 +.44=. +<\>\0>;.even +.45=. +<\>\0>;.even +.47=. +<.sr\0>;.even +.46=. +1 .tx;.47 +.51=. +<.gt\0>;.even +.50=. +1 .tx;.51 +infix: + +smark +ignore +none +.pxs;'+ +alt;..201 +not +.1 +trans;1 .3 +goto;..144 +..201:.pxs;'- +alt;..200 +trans;1 .5 +goto;..145 +..200:.pxs;'* +alt;..177 +trans;1 .7 +goto;..146 +..177:.pxs;'/ +alt;..176 +trans;1 .11 +goto;..147 +..176:.pxs;'% +alt;..175 +trans;1 .13 +goto;..150 +..175:.pxs;'| +alt;..174 +trans;1 .15 +goto;..151 +..174:.pxs;'^ +alt;..173 +trans;1 .17 +goto;..152 +..173:.pxs;'& +alt;..172 +trans;1 .21 +goto;..153 +..172:.px;.23 +alt;..171 +trans;1 .24 +goto;..154 +..171:.px;.26 +alt;..170 +trans;1 .27 +goto;..155 +..170:.px;.31 +alt;..167 +trans;1 .32 +goto;..156 +..167:.px;.34 +alt;..166 +trans;1 .35 +goto;..157 +..166:.px;.37 +alt;..165 +trans;1 .40 +goto;..160 +..165:.pxs;'< +alt;..164 +trans;1 .42 +goto;..161 +..164:.px;.44 +.px;.45 +alt;..163 +trans;1 .46 +goto;..162 +..163:trans;1 .50 +..162: +..161: +..160: +..157: +..156: +..155: +..154: +..153: +..152: +..151: +..150: +..147: +..146: +..145: +..144: +1 succ +.2=. +<.lv\0>;.even +.1=. +1 .tx;.2 +.3=. +<++\0>;.even +.5=. +<.ib\0>;.even +.4=. +1 .tx;.5 +.6=. +<--\0>;.even +.10=. +<.db\0>;.even +.7=. +1 .tx;.10 +prefix: + +smark +ignore +none +.pxs;'& +alt;..205 +trans;1 .1 +goto;..202 +..205:.px;.3 +alt;..204 +trans;1 .4 +goto;..203 +..204:.px;.6 +trans;1 .7 +..203: +..202: +1 succ +.1=. +<++\0>;.even +.3=. +<.ia\0>;.even +.2=. +1 .tx;.3 +.4=. +<--\0>;.even +.6=. +<.da\0>;.even +.5=. +1 .tx;.6 +suffix: + +smark +ignore +none +.px;.1 +alt;..207 +trans;1 .2 +goto;..206 +..207:.px;.4 +trans;1 .5 +..206: +1 succ +.2=. +<.nt\0>;.even +.1=. +1 .tx;.2 +.4=. +<.ng\0>;.even +.3=. +1 .tx;.4 +.6=. +<.cm\0>;.even +.5=. +1 .tx;.6 +unary: + +.pxs;'! +alt;..213 +trans;1 .1 +goto;..210 +..213:.pxs;'- +alt;..212 +trans;1 .3 +goto;..211 +..212:.pxs;'~ +trans;1 .5 +..211: +..210: +1 succ +charcl: + +.pxs;'! +alt;..215 +ccla +cclb +goto;..214 +..215:ccla +..214: +1 octal +classmask +.1=. +<<<\0>;.even +.2=. +1 +.4=. +<<<\0>;.even +ccla: + +.px;.1 +.l;classmask +.l;.2 +.l;nclass +.ia +.sl +.st +.p +.l;classmask +.t +alt;cherr +ccl1: +cclc +.px;.4 +1 salt;ccl1 +.1=. +<\>\0>;.even +cclc: + +ignore +none +ccl3: +.px;.1 +salt;ccl4 +ccle +1 salt;ccl3 +.1=. +<\>\0>;.even +.3=. +<\>\0>;.even +.2=. +1 .px;.3 +ccl4: + +.px;.1 +salt;..216 +cclx +fail +..216: +not +.2 +salt;..217 +ccle +..217: +1 succ +.1=. +2 +ccle: + +char +n +.l;.1 +.l;n +.m +.l;classes +.lv +.a +.rv +.l;classmask +.o +.u +1 .p +cclb: + +zeron +ccl5: +.l;classes +.lv +.l;n +.a +.rv +.l;classmask +.x +.u +.p +testn +1 salt;ccl5 +cclx: + +.l;nclass +.da +.p +zeron +ccl6: +.l;classes +.lv +.l;n +.a +.rv +.l;classmask +.cm +.n +.u +.p +testn +1 salt;ccl6 +.3=. +;.even +.2=. +1 .tx;.3 +.1=. +1 trans;1 .2 +cherr: + +1 diag +.1 +.1=. +0 +zeron: + +.l;n +.l;.1 +.st +1 .p +.1=. +2 +.2=. +400 +testn: + +.l;n +.l;.1 +.a +.u +.l;.2 +.lt +1 .t +.1=. +0 +.4=. +<.globl classtab\0>;.even +.5=. +;.even +.3=. +.tn +.tx;.4 +.tn +.tx;.5 +1 .tn +.2=. +1 trans;1 .3 +.7=. +.tp;.byte 1,0; +1 .tn +.6=. +octal +w +1 trans;1 .7 +putcharcl: + +zeron +.l;classes +.l;.1 +.st +.p +parse +.2 +ptc1: +.l;w +.l;classes +.lv +.l;n +.a +.rv +.st +.p +parse +.6 +bundle +testn +1 salt;ptc1 +classmask: +0 +nclass: +0 +classes: +cl1: +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +cl2: +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +cl3: +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +cl4: +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +cl5: +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +cl6: +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +cl7: +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +cl8: +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +done: + +1 succ +.1=. +.txs;'. +1 .tp;.byte 1,0; +create: + +.l;csym +.ia +.p +getcsym: +octal +csym +1 trans;1 .1 +.2=. +<..\0>;.even +.1=. +.tx;.2 +1 .tp;.byte 1,0; +fref: + +.l;fsym +.ia +.p +getfref: +octal +fsym +1 trans;1 .1 +.1=. +1 +not: + +params +.1 +[-1\<1] +alt;done +1 fail +.1=. +1 +.2=. +.tp;.byte 2,0; +.tn +1 .tp;.byte 1,0; +list: + +params +.1 +[-1\<1] +list1: +bundle +.pxs;', +alt;done +[-1\<1] +trans;1 .2 +1 salt;list1 +.1=. +1 +remote: + +params +.1 +create +1 parse +rem1 +[-1\<1] +.1=. +1 +.3=. +<=.\0>;.even +.2=. +.tp;.byte 2,0; +.tx;.3 +.tn +.tp;.byte 1,0; +1 .tn +rem1: + +params +.1 +getcsym +[-1\<1] +1 trans;1 .2 +number: + +smark +ignore +none +any +digit +string +digit +1 scopy +name: + +ident +1 scopy +ident: + +smark +ignore +none +any +letter +1 string +alpha +.1=. +1 +.3=. +0 +oldtab: + +params +.1 +.l;[-1\<1] +.t +alt;done +discard +[-1\<1] +.l;[-1\<1] +.l;.3 +.st +1 .p +.1=. +2 +.3=. +0 +newtab: + +params +.1 +.l;[-2\<1] +.t +salt;..220 +table +[-2\<1] +.l;[-1\<1] +.l;.3 +.st +.p +..220: +enter +[-2\<1] +i +.l;[-2\<1] +.l;i +.f +.l;[-1\<1] +.ia +.st +1 .p +.1=. +2 +tabval: + +params +.1 +.l;[-2\<1] +.t +find +[-2\<1] +i +.l;i +.l;[-1\<1] +.l;[-2\<1] +.l;i +.f +.s +.st +.p +1 octal +i +null: + +1 trans;1 nil +.1=. +<1 \0>;.even +xbit: +1 .tx;.1 +q1: +1 .tq;1 +q2: +1 .tq;2 +nil: +1 generate +blanks: +10 +digit: +20 +letter: +40 +alpha: +100 +litch: +200 +none: +400 +csym: +0 +fsym: +0 +easy: +0 +w: +0 +n: +0 +dtt: +0 +ndt: +0 +sndt: +0 +pat: +0 +npa: +0 +ptt: +0 +npt: +0 +i: +0 + +.globl classtab +classtab: +0 +207 +207 +207 +207 +207 +207 +207 +207 +217 +217 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +207 +217 +207 +207 +207 +207 +207 +207 +207 +207 +207 +203 +207 +207 +207 +207 +207 +327 +327 +327 +327 +327 +327 +327 +327 +327 +327 +207 +205 +207 +207 +7 +207 +207 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +207 +7 +207 +207 +207 +207 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +347 +207 +207 +207 +207 +207 +.pn:1 .pxs;12 +.tn:1 .txs;12 diff --git a/source/tmg/tmgl.t b/source/tmg/tmgl.t new file mode 100644 index 0000000..dd4d033 --- /dev/null +++ b/source/tmg/tmgl.t @@ -0,0 +1,324 @@ +begin: ignore(blanks) +pr1: comment\pr1 + parse(first)\pr2 + diag(error) +pr2: comment\pr2 + parse(line)\pr2 + diag(error)\pr2 + putcharcl + parse(last); + +first: parse(( fref = {<1 > 1 *})) + getfref line = { 2<:> 1 }; + +error: smark ignore(none) any(!<<>>) string(!<<;>>) scopy + ( <;> = {<;>} | null ) + = { * 2 1 * }; + +line: + labels + ( charcl <;> + | statement + | numbers + | trule <;> ) + = { 2 * 1 * }; + +numbers: number <;> numbers/done = { 2 * 1 }; + +labels: label labels/done = { 2 * 1 }; + +label: name <:> = { 1 <:> }; + +last: = { <.pn:1 .pxs;12> * + <.tn:1 .txs;12> * }; + +comment: +co1: ignore(!<<*>>) <*> ignore(none) /co1; + +statement: [csym=0] oldtab(dtt) oldtab(pat) + ( proc plst tlst <)> = (1){2 1 } + | = (1){} noelem ) +stt1: bundle ( frag = (1){ 2(nil) * 1(q1) }\stt1 + | <;> ( ifelem = { 1(xbit) } + | ={ 1(nil) * <1 succ> } + ) ); + +proc: smark ignore(none) ; + +plst: list(pident)/null remote((octal(npa))) + = { 1 * }; + +pident: ident newtab(pat,npa); + +tlst: <;>/null [i=0] list((name [i++])) remote((octal(i))) + = { 1 * 2 * }; + +frag: prule = (1){ 1(nil,q1) } + | labels noelem = (1){ 1 }; + +/*in sequel q2 is where to go on fail,q1 is exit bit*/ + +prule: [sndt=ndt] disj + ( <|> [ndt=sndt] fref + ( ifeasy prule = (2){3(nil,nil)*2* + 1(q2,q1)*2<:>} + | prule fref = (2){4({*1},q1)*3* + 1<:>2(q2,q1)*3<:>} ) + noelem + | () ); + +disj: pelem pdot + ( disj = (2){2(q2,nil) * 1(nil,q1)} ifelem/done ishard + | () ); + +pelem: pprim = (2){1(q1)$2} iseasy + | <(> push(1,sndt) + ( prule <)> + | <)> = (2){} noelem ); + +pprim: ( special + | rname ( <:> fail + | (spdot|()) ignore(none) + ( <(> ignore(blanks) list(parg) <)> + = (1){$1 2 * 1} + | = (1){$1 1} ))) + ( ( = {} | <\>={}) + rname = (1){3(nil)*$1 2 1} + | () ); + +pdot: <.>/done ignore(none) ident\alias + ([dtt?] | table(dtt) [ndt=0]) [ndt++]; +spdot: <.> ignore(none) not(( any(letter) )) +alias: newtab(dtt,ndt); + +parg: rname | remote(specparg); + +specparg: number + | charcl + | <<> longlit + | <*> = { <\n\0> } + | <(> ( <)> = {<1 succ>} + | push(3,dtt,ndt,sndt) [dtt=0] + prule <)> oldtab(dtt) + ( ifelem = {1(nil,xbit) } + | = {1(nil,nil)*<1 succ>} + ) ); + +iseasy: [easy = 1]; +ishard: [easy = 0]; +noelem: [easy = 2]; +ifelem: [easy!=2?]; +ifeasy: [easy==1?]; + +special: <=> (rname | remote(trule)) + = (1){ $1 1 } + | <<> literal = (1){ $1 <.px> 1 } + | <*> = (1){ $1 <.pn> } + | <[> expr + ( = {<.t>} + | = {<.p>} ) + <]> = (1){ 2 * $1 1 }; + +rname: ( name tabval(pat,npa)/done + | <$> number ) + = { <[-> 1 <\<1]> }; + +trule: oldtab(ptt) + ( tbody + | <(> (number|tra) <)> tbody = { 2 * 1 } ); +tra: list(tident) octal(npt); + +tident: ident newtab(ptt,npt); + +tbody: <{> ( <}> = { <1 generate> } + | trb); +trb: telem ( <}> = { xbit 1 } + | trb = { 2 * 1 } ); + +telem: <<> literal = { <.tx> 1 } + | <*> = {<.tn>} + | <$> number = { <.tq;> 1 } + | number tdot = tpt + | name te1\done te2\done; + +te1: tabval(dtt,ndt) tdot = tpt; +te2: tabval(ptt,npt) = {<.tq;>1}; + +tdot: (<.> number | ={<0>}) + ( <(> list(targ) <)> | null) + = { 2 <;> 1 }; + +targ: name|remote(tbody); + +tpt: { <.tp;.byte > 2 <,> 1 }; + +literal: ( shortlit + | remote(longlit) = { <;> 1} ); + +shortlit: ignore(none) smark any(litch) <>> scopy = { 1 }; + +longlit: ignore(none) (<>> = { <\> <>> } | null) litb <>> + = { <<> 2 1 <\0> <>;.even> }; + +litb: smark string(litch) scopy <\>/done + litb = { 2 <\\> 1 }; + +expr: assignment | rv ; + +assignment: lv assign expr = { 3 * 1 * 2 }; + +rv: prime +rv1: bundle ( infix prime = { 3 * 1 * 2 }\rv1 + | rva = { 2 * 1 } + | () ); +rva: rv <:> rv fref fref + = { <.t;alt;> 2 * 4 * 1 * 2 <:> 3 * 1 <:> }; + +prime: + lv suffix/done = { 2 * 1 } + | prefix lv = { 1 * 2 } + | <(> expr <)> + | unary prime = { 1 * 2 } + | remote(number) = { <.l;> 1 }; + +lv: ( rname = { <.l;> 1 } + | <(> lv <)> + | <*> prime = { 1 * <.rv> } ) +lv1: <[>/done bundle expr <]> = { 2 * 1 * <.f> }\lv1; + +assign: <=> ignore(none) ( infix = { 1 * <.u> } + | = { <.st> } ); + +infix: smark ignore(none) + ( <+> not((<+> not((<+>)) )) = {<.a>} + | <-> = {<.s>} + | <*> = {<.m>} + | = {<.q>} + | <%> = {<.r>} + | <|> = {<.o>} + | <^> = {<.x>} + | <&> = {<.n>} + | <==> = {<.eq>} + | = {<.ne>} + | <<=> = {<.le>} + | <>=> = {<.ge>} + | <<<> = {<.sl>} + | <<> = {<.lt>} + | <>> ( <>> = {<.sr>} + | = {<.gt>} ) + ); + +prefix: smark ignore(none) + ( <&> = {<.lv>} + | <++> = {<.ib>} + | <--> = {<.db>} + ); + +suffix: smark ignore(none) + ( <++> = {<.ia>} + | <--> = {<.da>} + ); + +unary: ( = {<.nt>} + | <-> = {<.ng>} + | <~> = {<.cm>} + ); + +charcl: + ( ccla cclb | ccla ) + octal(classmask); +ccla: (<<<>) [classmask = 1<\ccl1; +cclc: ignore(none) + +ccl3: <>>\ccl4 ccle\ccl3; +ccl4: (<>> | cclx fail) (not((<>>)) | ccle); +ccle: char(n) [*(2*n+&classes) =| classmask]; +cclb: zeron +ccl5: [*(&classes+n) =^ classmask] testn\ccl5; +cclx: [nclass--] zeron +ccl6: [*(&classes+n) =& ~classmask] testn\ccl6; +cherr: diag(( ={} )); + +zeron: [n=0]; +testn: [(n=+2)<400?]; + +putcharcl: zeron [classes=0] + parse(( = { * <.globl classtab> * * } )) +ptc1: [w = *(&classes+n)] parse((octal(w) = {1*})) + bundle testn\ptc1; + +classmask: 0; +nclass: 0; +classes: +cl1: 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; +cl2: 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; +cl3: 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; +cl4: 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; +cl5: 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; +cl6: 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; +cl7: 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; +cl8: 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; + +done: ; + +create: [csym++] +getcsym: octal(csym) = {<.> 1}; + +fref: [fsym++] +getfref: octal(fsym) = { <..> 1 }; + +not: params(1) $1/done fail; + +list: params(1) $1 +list1: bundle <,>/done $1 = { 2 * 1 }\list1; + +remote: params(1) create parse(rem1,$1); +rem1: params(1) getcsym $1 = { 2 <=.> * 1 * }; + +number: smark ignore(none) any(digit) string(digit) scopy; + +name: ident scopy; + +ident: smark ignore(none) any(letter) string(alpha); + +oldtab: params(1) [$1?]/done discard($1) [$1=0]; + +newtab: params(2) ([$2?] | table($2) [$1=0]) + enter($2,i) [$2[i] = $1++]; + +tabval: params(2) [$2?] find($2,i) [i=$1-$2[i]] octal(i); + +null: = nil; + +xbit: {<1 >}; + +q1: { $1 }; +q2: { $2 }; + +nil: {}; + +blanks: << + >>; +digit: <<0123456789>>; +letter: <> + <>; +alpha: <<0123456789>> + <> + <>; +litch: !<<\>>>; +none: <<>>; + +csym: 0; +fsym: 0; +easy: 0; +w: 0; +n: 0; +dtt: 0; /*delivered translation table*/ +ndt: 0; /*numb of delivered translations*/ +sndt: 0; /*saved ndt at beginning of disjunctive term*/ +pat: 0; /*parsing rule parameter table*/ +npa: 0; /*number of parsing rule params*/ +ptt: 0; /*table of params of translation*/ +npt: 0; /*number of params of translation*/ +i: 0; diff --git a/source/yacc/lib/main.c b/source/yacc/lib/main.c new file mode 100644 index 0000000..8941a1e --- /dev/null +++ b/source/yacc/lib/main.c @@ -0,0 +1,5 @@ +main( argc, argv ) int argc; char *argv[]; { + yyinit( argc, argv ); + if( yyparse() ) return; + yyaccpt(); + } diff --git a/source/yacc/lib/parser.c b/source/yacc/lib/parser.c new file mode 100644 index 0000000..bf06e8c --- /dev/null +++ b/source/yacc/lib/parser.c @@ -0,0 +1,125 @@ +# define _maxdepth 150 + +/* parser for yacc output */ +extern int yyval; /* defined in the table file */ +extern int yylval; /* defined in the table file */ +extern int *yypv; /* defined in the table file */ + + +int yydebug 0; /* 1 for debugging */ +int yyv[_maxdepth]; /* where the values are stored */ +int yystate 0; /* current parser state */ +int yychar -1; /* current input token number */ +int yynerrs 0; /* number of errors */ +int yyerrflag 0; /* error recovery flag */ + + +yyparse() { + + extern int yygo[], yypgo[], yyr1[], yyr2[], yyact[], yypact[]; + auto int *ps, s[_maxdepth]; + auto int ac, n, *p; + + yystate = 0; + yychar = -1; + yynerrs = 0; + yyerrflag = 0; + ps= &s[0]-1; + yypv= &yyv[0]-1; + + stack: /* put a state and value onto the stack */ + + if( yydebug ) printf( "state %d, value %d, char %d\n",yystate,yyval,yychar ); + *++ps = yystate; + *++yypv = yyval; + + newstate: /* set ap to point to the parsing actions for the new state */ + + p = &yyact[ yypact[yystate+1] ]; + + actn: /* get the next action, and perform it */ + + n = ( ac = *p++ ) & 07777; /* n is the "address" of the action */ + + switch( ac>>12 ) { /* switch on operation */ + + case 1: /* skip on test */ + if( yydebug && (yychar<0) ){ + yychar = yylex(); + printf( "character %d read\n", yychar ); + } + if( n != ( (yychar<0) ? ( yychar=yylex() ) : yychar ) ) ++p; + goto actn; /* get next action */ + + case 2: /* shift */ + + yystate=n; + yyval=yylval; + yychar= -1; + if( yyerrflag ) --yyerrflag; + goto stack; /* stack new state */ + + case 3: /* reduce */ + + if( yydebug ) printf("reduce %d\n",n); + ps =- yyr2[n]; + yypv =- yyr2[n]; + yyval=yypv[1]; + yyactr(n); + /* consult goto table to find next state */ + for( p= &yygo[yypgo[yyr1[n]]]; *p != *ps && *p >= 0 ; p =+ 2 ) ; + yystate = p[1]; + goto stack; /* stack new state and value */ + + case 4: /* accept */ + return(0); + + case 0: /* error ... attempt to resume parsing */ + + switch( yyerrflag ){ + + case 0: /* brand new error */ + + ++yynerrs; + yyerror( "syntax error" ); + + case 1: + case 2: /* incompletely recovered error ... try again */ + + yyerrflag = 3; + + /* find a state where "error" is a legal shift action */ + + while ( ps >= s ) { + for( p= &yyact[ yypact[*ps+1] ] ; (*p>>12) == 1 ; p =+ 2 ) /* search ps actions */ + if( *p == 4352 ) goto found; + + /* the current ps has no shift onn "error", pop stack */ + + if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *ps, ps[-1] ); + --ps; + --yypv; + } + + /* there is no state on the stack with an error shift ... abort */ + + abort: + return(1); + + found: /* we have a state with a shift on "error", resume parsing */ + + yystate = p[1] & 07777; + goto stack; + + case 3: /* no shift yet; clobber input char */ + + if( yydebug ) printf( "error recovery discards char %d\n", yychar ); + + if( yychar == 0 ) goto abort; /* don't discard EOF, quit */ + yychar = -1; + goto newstate; /* try again in the same state */ + + } + + } + } diff --git a/source/yacc/lib/zacc.c b/source/yacc/lib/zacc.c new file mode 100644 index 0000000..47297e7 --- /dev/null +++ b/source/yacc/lib/zacc.c @@ -0,0 +1 @@ +yyaccpt(){} diff --git a/source/yacc/lib/zerr.c b/source/yacc/lib/zerr.c new file mode 100644 index 0000000..ab6ae04 --- /dev/null +++ b/source/yacc/lib/zerr.c @@ -0,0 +1,16 @@ +extern int yyline; /* input line number */ + +yyerror(s) char *s; { + extern int yychar; + extern char *yysterm[]; + printf("\n%s", s ); + if( yyline ) printf(", line %d,", yyline ); + printf(" on input: "); + if( yychar >= 0400 ) printf("%s\n", yysterm[yychar-0400] ); + else switch ( yychar ) { + case '\t': printf( "\\t\n" ); return; + case '\n': printf( "\\n\n" ); return; + case '\0': printf( "$end\n" ); return; + default: printf( "%c\n" , yychar ); return; + } + } diff --git a/source/yacc/lib/zinit.c b/source/yacc/lib/zinit.c new file mode 100644 index 0000000..b6c46a5 --- /dev/null +++ b/source/yacc/lib/zinit.c @@ -0,0 +1 @@ +yyinit(){} diff --git a/source/yacc/run b/source/yacc/run new file mode 100644 index 0000000..9abeb04 --- /dev/null +++ b/source/yacc/run @@ -0,0 +1,9 @@ +chdir lib +cc -c -O *.c +ar r /lib/liby.a *.o +rm *.o +chdir ../source +cc -s -O y?.c +cmp a.out /usr/bin/yacc +cp a.out /usr/bin/yacc +rm a.out *.o diff --git a/source/yacc/source/dextern b/source/yacc/source/dextern new file mode 100644 index 0000000..e93ba65 --- /dev/null +++ b/source/yacc/source/dextern @@ -0,0 +1,123 @@ +# +/* MANIFEST CONSTANT DEFINITIONS */ + +# define NTBASE 010000 + + /* internal codes for error and accept actions */ + +# define ERRCODE 8190 +# define ACCEPTCODE 8191 + +# define errfileno 1 /* file number for erros and reduction message */ +# define _tbitset 6 /* 16*_tbitset - 1 >= _nterms */ + +extern int tbitset; /* number of wds of lookahead vector */ +extern int nolook; /* flag to turn off lookahed computations */ +struct looksets { int lset[ _tbitset ]; } ; +struct item { int *pitem; struct looksets *look; } ; + + /* output actions */ + +# define ERRACT 0 +# define TESTACT 4096 +# define SHIFTACT 8192 +# define REDUCACT 12288 +# define ACCEPTACT 16384 + +# define _REGISTER register + +extern int nstate ; /* number of states */ +extern struct item *pstate[]; /* pointers to the descriptions of the states */ +extern int apstate[]; /* index to actions in amem by state */ +extern int actsiz; /* size of the action table array */ +extern int tystate[]; /* contains type information about the states */ + /* 0 = simple state, completely generated + 1 = state awaiting generation + 2 = state with an empty production in closure + */ +extern int stsize ; /* maximum number of states, at present */ +extern int memsiz ; /* maximum size for productions and states */ +extern int mem0[] ; /* added production */ +extern int *mem ; +extern int amem[]; /* action table storage */ +extern int actsiz; /* action table size */ +extern int memact ; /* next free action table position */ +extern int nprod ; /* number of productions */ +extern int *prdptr[]; /* pointers to descriptions of productions */ +extern int prdlim; /* the number of productions allowed */ +extern int levprd[] ; /* contains production levels to break conflicts */ + /* last two bits code associativity: + 0 = no definition + 1 = left associative + 2 = binary + 3 = right associative + bit 04 is 1 if the production has an action + the high 13 bits have the production level + */ +extern int nterms ; /* number of terminals */ +extern int nerrors; /* number of errors */ +extern int fatfl; /* if on, error is fatal */ + /* the ascii representations of the terminals */ +extern int extval; /* start of output values */ +extern struct sxxx1 {char *name; int value;} trmset[]; +extern char cnames[]; +extern int cnamsz; +extern char *cnamp; +extern int maxtmp ; /* the size of the temp arrays */ + /* temporary vectors, indexable by states, terms, or nterms */ +extern int temp1[]; +extern int temp2[]; +extern int trmlev[]; /* vector with the precedence of the terminals */ + /* The levels are the same as for levprd, but bit 04 is always 0 */ + /* the ascii representations of the nonterminals */ +extern struct sxxx2 { char *name; } nontrst[]; +extern int indgo[]; /* index to the stored goto table */ +extern int ***pres; /* vector of pointers to the productions yielding each nonterminal */ +extern struct looksets **pfirst; /* vector of pointers to first sets for each nonterminal */ +extern int *pempty ; /* table of nonterminals nontrivially deriving e */ +extern int nnonter ; /* the number of nonterminals */ +extern int lastred ; /* the number of the last reduction of a state */ +extern int ftable; /* y.tab.c file */ +extern int foutput; /* y.output file */ +extern int cin; /* current input file */ +extern int cout; /* current output file */ +extern int arrndx; +extern int zzcwset; +extern int zzpairs ; +extern int zzgoent ; +extern int zzgobest ; +extern int zzacent ; +extern int zzacsave ; +extern int zznsave ; +extern int zzclose ; +extern int zzrrconf ; +extern int zzsrconf ; +extern char *ctokn; +struct {int **ppi;} ; +extern int ntlim ; /* maximum number of nonterminals */ +extern int tlim ; /* maximum number of terminals */ +extern int lineno; /* current line number */ +extern int peekc; /* look-ahead character */ +extern int tstates[]; +extern int ntstates[]; +extern int mstates[]; + +extern struct looksets clset; +extern struct looksets lkst[]; +extern int nlset; /* next lookahead set index */ +extern int lsetsz; /* number of lookahead sets */ + +extern struct wset { int *pitem, flag, ws[ _tbitset ]; } wsets[]; +extern int cwset; +extern int wssize; + +extern int numbval; /* the value of an input number */ +extern int rflag; /* ratfor flag */ +extern int oflag; /* optimization flag */ +extern int ndefout; /* number of defined symbols output */ + +extern int machine; + +# define UNIX 1 +# define GCOS 2 +# define IBM 3 diff --git a/source/yacc/source/y0.c b/source/yacc/source/y0.c new file mode 100644 index 0000000..c7a329e --- /dev/null +++ b/source/yacc/source/y0.c @@ -0,0 +1,103 @@ +# define _actsize 1500 +# define _memsize 3500 +# define _nstates 400 +# define _nterms 95 +# define _nprod 250 +# define _nnonterm 100 +# define _tempsize 400 +# define _cnamsz 2000 +# define _lsetsize 200 +# define _wsetsize 150 + +# define _tbitset 6 + +int tbitset; /* size of lookahed sets */ +int nolook 0; /* flag to suppress lookahead computations */ +struct looksets { int lset[ _tbitset ]; } ; +struct item { int *pitem; } ; + +/* this file contains the definitions for most externally known data */ + +int nstate 0; /* number of states */ +struct item *pstate[_nstates]; /* pointers to the descriptions of the states */ +int apstate[_nstates]; /* index to the actions for the states */ +int tystate[_nstates]; /* contains type information about the states */ +int stsize _nstates; /* maximum number of states, at present */ +int memsiz _memsize; /* maximum size for productions and states */ +int mem0[_memsize] ; /* production storage */ +int *mem mem0; +int amem[_actsize]; /* action table storage */ +int actsiz _actsize; /* action table size */ +int memact 0; /* next free action table position */ +int nprod 1; /* number of productions */ +int *prdptr[_nprod]; /* pointers to descriptions of productions */ +int prdlim _nprod ; /* the maximum number of productions */ + /* levprd - productions levels to break conflicts */ +int levprd[_nprod] {0,0}; + /* last two bits code associativity: + 0 = no definition + 1 = left associative + 2 = binary + 3 = right associative + bit 04 is 1 if the production has an action + the high 13 bits have the production level + */ +int nterms 0; /* number of terminals */ +int tlim _nterms ; /* the maximum number of terminals */ +/* the ascii representations of the terminals */ +int extval 0; /* start of output values */ +struct sxxx1 {char *name; int value;} trmset[_nterms]; +char cnames[_cnamsz]; +int cnamsz _cnamsz; +char *cnamp; +int maxtmp _tempsize; /* the size of the temp1 array */ +int temp1[_tempsize]; /* temporary storage, indexed by terms + nterms or states */ +int temp2[_nnonterm]; /* temporary storage indexed by nonterminals */ +int trmlev[_nterms]; /* vector with the precedence of the terminals */ + /* The levels are the same as for levprd, but bit 04 is always 0 */ +/* the ascii representations of the nonterminals */ +struct sxxx2 { char *name; } nontrst[_nnonterm]; +int ntlim _nnonterm ; /* limit to the number of nonterminals */ +int indgo[_nstates]; /* index to the stored goto table */ +int ***pres; /* vector of pointers to the productions yielding each nonterminal */ +struct looksets **pfirst; /* vector of pointers to first sets for each nonterminal */ +int *pempty 0 ; /* table of nonterminals nontrivially deriving e */ +int nnonter -1; /* the number of nonterminals */ +int lastred 0; /* the number of the last reduction of a state */ +int ftable; /* y.tab.c file */ +int foutput; /* y.output file */ +int arrndx; /* used in the output of arrays on y.tab.c */ +int zzcwset 0; +int zzpairs 0; +int zzgoent 0; +int zzgobest 0; +int zzacent 0; +int zzacsave 0; +int zznsave 0; +int zzclose 0; +int zzsrconf 0; +int zzrrconf 0; +char *ctokn; +int lineno 1; /* current input line number */ +int peekc -1; /* look-ahead character */ +int tstates[ _nterms ]; /* states generated by terminal gotos */ +int ntstates[ _nnonterm ]; /* states generated by nonterminal gotos */ +int mstates[ _nstates ]; /* chain of overflows of term/nonterm generation lists */ + +struct looksets clset; +struct looksets lkst [ _lsetsize ]; +int nlset 0; /* next lookahead set index */ +int lsetsz _lsetsize; /* number of lookahead sets */ + +struct wset { int *pitem, flag, ws[_tbitset]; } wsets[ _wsetsize ]; +int cwset; +int wssize _wsetsize; + +int numbval; /* the value of an input number */ +int rflag 0; /* ratfor flag */ +int oflag 0; /* optimization flag */ + +int ndefout 3; /* number of defined symbols output */ +int nerrors 0; /* number of errors */ +int fatfl 1; /* if on, error is fatal */ +int machine; /* has a number describing the machine */ diff --git a/source/yacc/source/y1.c b/source/yacc/source/y1.c new file mode 100644 index 0000000..a637739 --- /dev/null +++ b/source/yacc/source/y1.c @@ -0,0 +1,281 @@ +# include "dextern" + /* * * * * y a c c * * * * */ + + /* features to be fixed up ... + + *** Print estimate of total space needed for parser + *** Either list inputs on y.output, or list empty prdn's in states + *** Mention nonterms not used (or, rules. not reduced) as nonfatal error + *** Output states where conflicts were found by default on y.output + *** Engage in newspeak: production=>grammar rules, term=>token, etc. + *** handle # define, #ifdef, etc., in yacc actions, %{ %} + */ + + /* new features to be added + + *** reductions by single productions ( by request ) + *** follow sets for start symbol + *** option to only do slr(1) + *** easily changed array names on output + *** allocate core, rather than predefined + *** input controlled by a grammar + *** support multiple choices for conflicts + *** better conflict diagnostics + */ + + + +main(argc,argv) int argc; char *argv[]; { + auto int n; + + whereami(); + setup(argc,argv); /* initialize and read productions */ + tbitset = (nterms+16)/16; + cpres(); /* make table of which productions yield a given nonterminal */ + cempty(); /* make a table of which nonterminals can match the empty string */ + cpfir(); /* make a table of e free first lists */ + stagen(); /* generate the states */ + output(); /* write the states and the tables */ + go2out(); + summary(); + windup(); + } + +whereami(){ /* sets the variable machine to UNIX, GCOS, or IBM */ + + int i; + + i = 1; + i = i << 30; + if( i == 0 ) { + machine = UNIX; + return; + } + i = i << 4; + if( i == 0 ){ + machine = IBM; + return; + } + machine = GCOS; + } + +windup(){ + /* no errors, do the optimization if appropriate */ + char *cp; + int i; + + cflush(1); + if( !oflag ) cexit(0); + + for( i=3; i<10; ++i ) cclose(i); + switch( machine ){ + + case GCOS: + if( rflag ){ + if( foutput<0 ) system( "./yopt -r" ); + else system( "./yopt -rv" ); + } + else { + if( foutput<0 ) system( "./yopt" ); + else system( "./yopt -v" ); + } + cexit(0); /* terminate */ + + case UNIX: + cp = "/usr/yacc/yopti"; + if( rflag ) execl( cp, cp, (foutput<0)?"-r":"-rv", 0 ); + else if( foutput<0 ) execl( cp, cp, 0 ); + else execl( cp, cp, "-v", 0 ); + error( "optimization execl call fails" ); + + case IBM: + if( rflag ){ + if( foutput<0 ) system( "MH2019.yaccopt -r" ); + else system( "MH2019.yaccopt -rv" ); + } + else { + if( foutput<0 ) system( "MH2019.yaccopt" ); + else system( "MH2019.yaccopt -v" ); + } + cexit(0); + + } + + } + +settty() +/* sets the output file to y.output */ +{ + cflush( foutput ); /* a bit of a cheat */ + cout = foutput; + } + +settab(){ /* sets the output file to y.tab.c */ + + cflush( ftable ); + cout = ftable; + } + +char *chcopy( p, q ) char *p, *q; { + /* copies string q into p, returning next free char ptr */ + while( *p = *q++ ) ++p; + return( p ); + } + +char *writem(pp) struct item *pp; { /* creates output string for item pointed to by pp */ + int i,*p; + static char sarr[100]; + char *q; + + for( p=pp->pitem; *p>0 ; ++p ) ; + p = prdptr[-*p]; + q = chcopy( sarr, nontrst[*p-NTBASE].name ); + q = chcopy( q, " : " ); + + for(;;){ + *q++ = ++p==(pp->pitem) ? '_' : ' '; + if((i = *p) <= 0) break; + q = chcopy( q, symnam(i) ); + } + + *q = '\0' ; + return( sarr ); + } + +char *symnam(i){ /* return a pointer to the name of symbol i */ + char *cp; + + cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : trmset[i].name ; + if( *cp == ' ' ) ++cp; + return( cp ); + } + +summary(){ /* output the summary on the tty */ + + int i, s, *pn; + + + if( !rflag ){ + settab(); + printf("\nint nterms %d;",nterms); + printf("\nint nnonter %d;", nnonter); + printf("\nint nstate %d;", nstate); + printf("\nchar *yysterm[] {"); + for (i=1;i<=nterms;i++) if( trmset[i].value >= 0400 ) printf("\n\"%s\",",symnam(i)); + printf( "\n0 };\n" ); + printf("\nchar *yysnter[] {"); + for (i=0;i= memsiz) error("memory overflow"); + return(omem); + } + +aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */ + int i; + for( i=0; ilset; + if( pp == 0 ) printf("\tNULL"); + else { + printf(" { " ); + for( j=1; j<=nterms; ++j ){ + if( (pp[j>>4]>>(j&017) )&01 != 0 ) printf( "%s ", symnam(j) ); + } + printf( "}" ); + } + } diff --git a/source/yacc/source/y2.c b/source/yacc/source/y2.c new file mode 100644 index 0000000..235fda2 --- /dev/null +++ b/source/yacc/source/y2.c @@ -0,0 +1,533 @@ +# include "dextern" +# define IDENTIFIER 257 +# define MARK 258 +# define TERM 259 +# define LEFT 260 +# define BINARY 261 +# define RIGHT 262 +# define PREC 263 +# define LCURLY 264 +# define C_IDENTIFIER 265 /* name followed by colon */ +# define NUMBER 266 + +setup(argc,argv) int argc; char *argv[]; +{ int i,j,lev,t; + int c; + + foutput = -2; + i = 1; + while( argc >= 2 && argv[1][0] == '-' ) { + while( *++(argv[1]) ){ + switch( *argv[1] ){ + case 'v': + case 'V': + foutput = copen("y.output", 'w' ); + if( foutput < 0 ) error( "cannot open y.output"); + continue; + case 'o': + case 'O': + oflag = 1; + continue; + case 'r': + case 'R': + oflag = 1; + rflag = 1; + continue; + default: error( "illegal option: %c", *argv[1]); + } + } + argv++; + argc--; + } + + ftable = copen( oflag ? "yacc.tmp" : "y.tab.c" , 'w' ); + if( ftable<0 ) error( "cannot open table file" ); + if( argc > 1 ) cin = copen( argv[1], 'r' ); + if( cin < 0 ) error( "cannot open input" ); + settab(); + printf("#\n"); + ctokn = "$end"; + defin(0); /* eof */ + extval = 0400; /* beginning of assigned values */ + ctokn = "error"; + defin(0); + ctokn = "$accept"; + defin(1); + mem=mem0; + cnamp = cnames; + lev=0; + i=0; + + while( t = gettok() ){ + switch( t ){ + case IDENTIFIER: j = chfind(0); + trmlev[j] = lev; + continue; + case ',': + case ';': continue; + case TERM: lev=0; continue; + case LEFT: lev=(++i<<3)|01; continue; + case BINARY: lev=(++i<<3)|02; continue; + case RIGHT: lev=(++i<<3)|03; continue; + case MARK: + defout(); + if( rflag ){ /* RATFOR */ + printf( "define yyerrok yyerrf = 0\n" ); + printf( "define yyclearin yychar = -1\n" ); + printf( "subroutine yyactr(yyprdn)\n"); + printf( "common/yycomn/yylval,yyval,yypv,yyvalv(150)\n" ); + printf( "common/yylcom/yychar,yyerrf,yydebu\n" ); + printf( "integer yychar, yyerrf, yydebu\n" ); + printf( "integer yyprdn,yyval,yylval,yypv,yyvalv\n" ); + } + else { + printf( "#define yyclearin yychar = -1\n" ); + printf( "#define yyerrok yyerrflag = 0\n" ); + printf( "extern int yychar, yyerrflag;\n" ); + printf("\nint yyval 0;\nint *yypv;\nint yylval 0;"); + printf("\nyyactr(__np__){\n"); + } + break; + case LCURLY: defout(); + cpycode(); + continue; + case NUMBER: + trmset[j].value = numbval; + if( j < ndefout && j>2 ) + error("please define type # of %s earlier", trmset[j].name ); + continue; + default: error("bad precedence syntax, input %d", t ); + } + break; + } + prdptr[0]=mem; + /* added production */ + *mem++ = NTBASE; + *mem++ = NTBASE+1; + *mem++ = 1; + *mem++ = 0; + prdptr[1]=mem; + i=0; + + /* i is 0 when a rule can begin, 1 otherwise */ + + for(;;) switch( t=gettok() ) { + case C_IDENTIFIER: if( mem == prdptr[1] ) { /* first time */ + if( rflag ){ + printf( "goto 1000\n" ); + } + else printf("\nswitch(__np__){\n"); + } + if( i != 0 ) error( "previous rule not terminated" ); + *mem = chfind(1); + if( *mem < NTBASE )error( "token illegal on lhs of grammar rule" ); + i=1; + ++mem; + continue; + case IDENTIFIER: + *mem=chfind(1); + if(*mem < NTBASE)levprd[nprod]=trmlev[*mem]; + mem++; + if(i==0) error("missing :"); + continue; + case '=': levprd[nprod] =| 04; + if( i==0 ) error("semicolon preceeds action"); + printf( rflag?"\n%d ":"\ncase %d:", nprod ); + cpyact(); + printf( rflag ? " return" : " break;" ); + case '|': + case ';': if(i){ + *mem++ = -nprod; + prdptr[++nprod] = mem; + levprd[nprod]=0; + i=0;} + if (t=='|'){i=1;*mem++ = *prdptr[nprod-1];} + continue; + case 0: /* End Of File */ + case MARK: if( i != 0 ) error( "rule not terminated before %%%% or EOF" ); + settab(); + finact(); + /* copy the programs which follow the rules */ + if( t == MARK ){ + while (c=getchar()) putchar(c); + } + return; + case PREC: + if( i==0 ) error( "%%prec must appear inside rule" ); + if( gettok()!=IDENTIFIER)error("illegal %%prec syntax" ); + j=chfind(2); + if(j>=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name); + levprd[nprod]=trmlev[j]; + continue; + case LCURLY: + if( i!=0 ) error( "%%{ appears within a rule" ); + cpycode(); + continue; + default: error( "syntax error, input %d", t ); + } +} + +finact(){ + /* finish action routine */ + register i; + + if( rflag ){ + + printf( "\n1000 goto(" ); + for( i=1; i= ntlim ) error("too many nonterminals, limit %d",ntlim); + nontrst[nnonter].name = ctokn; + return( NTBASE + nnonter ); + } + else { + if( ++nterms >= tlim ) error("too many terminals, limit %d",tlim ); + trmset[nterms].name = ctokn; + if( ctokn[0]==' ' && ctokn[2]=='\0' ) /* single character literal */ + trmset[nterms].value = ctokn[1]; + else if ( ctokn[0]==' ' && ctokn[1]=='\\' ) { /* escape sequence */ + if( ctokn[3] == '\0' ){ /* single character escape sequence */ + switch ( ctokn[2] ){ + /* character which is escaped */ + case 'n': trmset[nterms].value = '\n'; break; + case 'r': trmset[nterms].value = '\r'; break; + case 'b': trmset[nterms].value = '\b'; break; + case 't': trmset[nterms].value = '\t'; break; + case '\'': trmset[nterms].value = '\''; break; + case '"': trmset[nterms].value = '"'; break; + case '\\': trmset[nterms].value = '\\'; break; + default: error( "invalid escape" ); + } + } + else if( ctokn[2] <= '7' && ctokn[2]>='0' ){ /* \nnn sequence */ + if( ctokn[3]<'0' || ctokn[3] > '7' || ctokn[4]<'0' || + ctokn[4]>'7' || ctokn[5] != '\0' ) error("illegal \\nnn construction" ); + trmset[nterms].value = 64*(ctokn[2]-'0')+8*(ctokn[3]-'0')+ctokn[4]-'0'; + if( trmset[nterms].value == 0 ) error( "'\\000' is illegal" ); + } + } + else { + trmset[nterms].value = extval++; + + } + trmlev[nterms] = 0; + return( nterms ); + } +} + +defout(){ /* write out the defines (at the end of the declaration section) */ + + _REGISTER int i, c; + _REGISTER char *cp; + + for( i=ndefout; i<=nterms; ++i ){ + + cp = trmset[i].name; + if( *cp == ' ' ) ++cp; /* literals */ + + for( ; (c= *cp)!='\0'; ++cp ){ + + if( c>='a' && c<='z' || + c>='A' && c<='Z' || + c>='0' && c<='9' || + c=='_' ) ; /* VOID */ + else goto nodef; + } + + /* define it */ + + printf( "%c define %s %d\n", rflag?' ':'#', trmset[i].name, trmset[i].value ); + + nodef: ; + } + + ndefout = nterms+1; + + } + +chstash( c ){ + /* put character away into cnames */ + if( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" ); + else *cnamp++ = c; + } + +int gettok() { + int j, base; + static int peekline; /* number of '\n' seen in lookahead */ + auto int c, match, reserve; + +begin: + reserve = 0; + if( peekc>=0 ) { + c = peekc; + lineno =+ peekline; + peekc = -1; + peekline = 0; + } + else c = getchar(); + while( c==' ' || c=='\n' || c=='\t' ){ + if( c == '\n' ) ++lineno; + c=getchar(); + } + if (c=='/') + {if (getchar()!='*')error("illegal /"); + c=getchar(); + while(c) { + if( c == '\n' ) ++lineno; + if (c=='*') + {if((c=getchar())=='/')break;} + else c=getchar();} + if (!c) return(0); + goto begin;} + j=0; + switch(c){ + case '"': + case '\'': match = c; + ctokn = cnamp; + chstash( ' ' ); + while(1){ + c = getchar(); + if( c == '\n' || c == '\0' ) + error("illegal or missing ' or \""); + if( c == '\\' ){ + c = getchar(); + chstash( '\\' ); + } + else if( c == match ) break; + chstash( c ); + } + break; + case '%': + case '\\': switch(c=getchar()) + {case '0': return(TERM); + case '<': return(LEFT); + case '2': return(BINARY); + case '>': return(RIGHT); + case '%': + case '\\': return(MARK); + case '=': return(PREC); + case '{': return(LCURLY); + default: reserve = 1; + } + default: if( c >= '0' && c <= '9' ){ /* number */ + numbval = c-'0' ; + base = (c=='0') ? 8 : 10 ; + for( c=getchar(); c>='0' && c<='9'; c=getchar() ){ + numbval = numbval*base + c - '0'; + } + peekc = c; + return(NUMBER); + } + else if( (c>='a'&&c<='z')||(c>='A'&&c<='Z')||c=='_'||c=='.'||c=='$'){ + ctokn = cnamp; + while( (c>='a'&&c<='z') || + (c>='A'&&c<='Z') || + (c>='0'&&c<='9') || + c=='_' || c=='.' || c=='$' ) { + chstash( c ); + if( peekc>=0 ) { c = peekc; peekc = -1; } + else c = getchar(); + } + } + else return(c); + + peekc=c; + } + chstash( '\0' ); + + if( reserve ){ /* find a reserved word */ + if( compare("term")) return( TERM ); + if( compare("TERM")) return( TERM ); + if( compare("token")) return( TERM ); + if( compare("TOKEN")) return( TERM ); + if( compare("left")) return( LEFT ); + if( compare("LEFT")) return( LEFT ); + if( compare("nonassoc")) return( BINARY ); + if( compare("NONASSOC")) return( BINARY ); + if( compare("binary")) return( BINARY ); + if( compare("BINARY")) return( BINARY ); + if( compare("right")) return( RIGHT ); + if( compare("RIGHT")) return( RIGHT ); + if( compare("prec")) return( PREC ); + if( compare("PREC")) return( PREC ); + error("invalid escape, or illegal reserved word: %s", ctokn ); + } + + /* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */ + + look: + while( peekc==' ' || peekc=='\t' || peekc == '\n' ) { + if( peekc == '\n' ) ++peekline; + peekc = getchar(); + } + + if( peekc != ':' ) return( IDENTIFIER ); + peekc = -1; + lineno =+ peekline; + peekline = 0; + return( C_IDENTIFIER ); +} +chfind(t) + +{ int i,j; + + if (ctokn[0]==' ')t=0; + for(i=1;i<=nterms;i++) + if(compare(trmset[i].name)){ + cnamp = ctokn; + return( i ); + } + for(i=1;i<=nnonter;i++) + if(compare(nontrst[i].name)) { + cnamp = ctokn; + return( i+NTBASE ); + } + /* cannot find name */ + if( t>1 && ctokn[0] != ' ' ) + error( "%s should have been defined earlier", ctokn ); + return( defin( t ) ); + } + +cpycode(){ /* copies code between \{ and \} */ + + int c; + c = getchar(); + if( c == '\n' ) { + c = getchar(); + lineno++; + } + while( c ){ + if( c=='\\' ) + if( (c=getchar()) == '}' ) return; + else putchar('\\'); + if( c=='%' ) + if( (c=getchar()) == '}' ) return; + else putchar('%'); + putchar( c ); + if( c == '\n' ) ++lineno; + c = getchar(); + } + error("eof before %%}"); + } + +cpyact(){ /* copy C action to the next ; or closing } */ + int brac, c, match, *i, j, s; + + brac = 0; + +loop: + c = getchar(); +swt: + switch( c ){ + +case ';': + if( brac == 0 ){ + putchar( c ); + return; + } + goto lcopy; + +case '{': + brac++; + goto lcopy; + +case '$': + s = 1; + c = getchar(); + if( c == '$' ){ + printf("yyval"); + goto loop; + } + if( c == '-' ){ + s = -s; + c = getchar(); + } + if( c>='0' && c <= '9' ){ + j=0; + while( c>='0' && c<= '9' ){ + j= j*10+c-'0'; + c = getchar(); + } + if( rflag ) printf( "yyvalv(yypv%c%d)", s==1?'+':'-', j ); + else printf("yypv[%d]", s*j ); + goto swt; + } + putchar( '$' ); + if( s<0 ) putchar('-'); + goto swt; + +case '}': + brac--; + if( brac == 0 ){ + putchar( c ); + return; + } + goto lcopy; + +case '/': /* look for comments */ + putchar( c ); + c = getchar(); + if( c != '*' ) goto swt; + + /* it really is a comment */ + + putchar( c ); + while( c=getchar() ){ + if( c=='*' ){ + putchar( c ); + if( (c=getchar()) == '/' ) goto lcopy; + } + putchar( c ); + } + error( "EOF inside comment" ); + +case '\'': /* character constant */ + match = '\''; + goto string; + +case '"': /* character string */ + match = '"'; + + string: + + putchar( c ); + while( c=getchar() ){ + + if( c=='\\' ){ + putchar( c ); + c=getchar(); + } + else if( c==match ) goto lcopy; + putchar( c ); + } + error( "EOF in string or character constant" ); + +case '\0': + error("action does not terminate"); +case '\n': ++lineno; + goto lcopy; + + } + +lcopy: + putchar( c ); + goto loop; + } diff --git a/source/yacc/source/y3.c b/source/yacc/source/y3.c new file mode 100644 index 0000000..22ce8b7 --- /dev/null +++ b/source/yacc/source/y3.c @@ -0,0 +1,378 @@ +# include "dextern" + +cpres(){ /* conpute an array with the beginnings of productions yielding given nonterminals + The array pres points to these lists */ + int i,j,c; + pres = yalloc(nnonter+1); + for(i=0;i<=nnonter;i++){ + c = i+NTBASE; + pres[i] = mem; + fatfl = 0; /* make undefined symbols nonfatal */ + for(j=0;j 0 ; ++p ) { + if( ch < NTBASE ) { + wsets[i].ws[ch>>4] =| (1 << (ch&017) ); + break; + } + else if( !pempty[ch-NTBASE] ) break; + } + } + } + + /* now, reflect transitivity */ + + changes = 1; + while( changes ){ + changes = 0; + for( i=0; i<=nnonter; ++i ){ + t = pres[i+1]; + for( s=pres[i]; s= 0; ++p ) { + changes =| union( wsets[i].ws, wsets[i].ws, wsets[ch].ws ); + if( !pempty[ch] ) break; + } + } + } + } + + for( i=0; i<=nnonter; i++ ) pfirst[i] = flset( wsets[i].ws ); + if( !indebug ) return; + settty(); + for( i=0; i<=nnonter; i++ ){ + printf( "\n%s: ", nontrst[i].name ); + prlook( pfirst[i] ); + printf( " %d\n", pempty[i] ); + } + } + +state(c){ /* sorts last state,and sees if it equals earlier ones. returns state number */ + int s,size1,size2; + _REGISTER i; + struct item *p1, *p2, *k, *l, *q1, *q2; + p1 = pstate[nstate]; + p2 = pstate[nstate+1]; + if(p1==p2) return(0); /* null state */ + /* sort the items */ + for(k=p2-1;k>p1;k--) { /* make k the biggest */ + for(l=k-1;l>=p1;--l)if( l->pitem > k->pitem ){ + s = k->pitem; + k->pitem = l->pitem; + l->pitem = s; + s = k->look; + k->look = l->look; + l->look = s; + } + } + size1 = p2 - p1; /* size of state */ + + for( i= (c>=NTBASE)?ntstates[c-NTBASE]:tstates[c]; i != 0; i = mstates[i] ) { + /* get ith state */ + q1 = pstate[i]; + q2 = pstate[i+1]; + size2 = q2 - q1; + if (size1 != size2) continue; + k=p1; + for(l=q1;lpitem != k->pitem ) break; + ++k; + } + if (l != q2) continue; + /* found it */ + pstate[nstate+1] = pstate[nstate]; /* delete last state */ + /* fix up lookaheads */ + k=p1; + for( l=q1; llook->lset, k->look->lset ) ) { + tystate[i] = 1; + /* register the new set */ + l->look = flset( &clset ); + } + ++k; + } + return (i); + } +/* state is new */ + pstate[nstate+2] = p2; + if(nstate+1 >= stsize) error("too many states"); + if( c >= NTBASE ){ + mstates[ nstate ] = ntstates[ c-NTBASE ]; + ntstates[ c-NTBASE ] = nstate; + } + else { + mstates[ nstate ] = tstates[ c ]; + tstates[ c ] = nstate; + } + tystate[nstate]=1; + return(nstate++); + } + +int pidebug 0; /* debugging flag for putitem */ +putitem ( ptr, lptr ) int *ptr; struct looksets *lptr;{ + int *jip, k; + struct item *i, *j; + + if( pidebug ) { + settty(); + printf("putitem(%s), state %d\n", writem(&ptr), nstate ); + } + /* see if it's there */ + j = pstate[nstate+1]; + for( i=pstate[nstate]; ipitem == ptr) { + error("yacc error--duplicate item"); + } + /* not there */ + j->pitem = ptr; + j->look = flset( lptr ); + pstate[nstate+1] = ++j; + jip = j; + if(jip-mem0 >= memsiz) error("out of state space"); + } + +cempty(){ /* mark nonterminals which derive the empty string */ + + int i, *p; + + /* set pempty to 0 */ + pempty = yalloc( nnonter ); + aryfil( pempty, nnonter+1, 0 ); + for( i=1; i=NTBASE && pempty[*p-NTBASE]!=0 ; ++p ) ; + if( *p < 0 ){ /* we have a nontrivially empty nonterminal */ + pempty[*prdptr[i]-NTBASE] = 1; + goto again; /* got one ... try for another */ + } + } + } + } + +int gsdebug 0; +stagen(){ /* generate the states */ + + int i, j, k, c; + + /* initialize */ + + nstate = 0; + pstate[0] = pstate[1] = mem; + aryfil( clset.lset, tbitset, 0 ); + putitem( prdptr[0]+1, &clset ); + tystate[0] = 1; + nstate = 1; + pstate[2] = pstate[1]; + + memact = 0; + aryfil( amem, actsiz, 0 ); + + /* now, the main state generation loop */ + + more: + for( i=0; ipitem; + wsets[cwset].flag = 1; /* this item must get closed */ + for( k=0; klook->lset[k]; + ++cwset; + } + + /* now, go through the loop, closing each item */ + + work = 1; + while( work ){ + work = 0; + for( j=0; j0 ){ + if( ch < NTBASE ){ /* terminal symbol */ + clset.lset[ch>>4] =| (1<<(ch&017)); + break; + } + /* nonterminal symbol */ + union( clset.lset, clset.lset, pfirst[ch-NTBASE] ); + if( !pempty[ch-NTBASE] ) break; + } + if( ch<=0 ) union( clset.lset, clset.lset, wsets[k].ws ); + } + } + + /* now loop over productions derived from c */ + + c =- NTBASE; /* c is now nonterminal number */ + + t = pres[c+1]; + for( s=pres[c]; s= wssize ) error( "working set overflow" ); + wsets[cwset].pitem = *s; + wsets[cwset].flag = 1; + if( nolook ){ + cwset++; + goto nexts; + } + work = 1; + for( k=0; k zzcwset ) zzcwset = cwset; + if( !cldebug ) return; + settty(); + printf("\nState %d, nolook = %d\n", i, nolook ); + for( j=0; jlset; + v = lkst[i].lset; + w = & v[tbitset]; + while( v= lsetsz )error("too many lookahead sets"); + for( j=0; jlset[j]; + } + return( & lkst[nlset++]); + } diff --git a/source/yacc/source/y4.c b/source/yacc/source/y4.c new file mode 100644 index 0000000..f131bbc --- /dev/null +++ b/source/yacc/source/y4.c @@ -0,0 +1,417 @@ +# include "dextern" + +output(){ /* print the output for the states */ + + int i, j, k, c; + + settab(); + arrset("yyact"); + + for( i=0; i0 && c>4])&(1<<(k&017))) != 0 ) { + if( temp1[k] == 0 ) temp1[k] = c; + else if( temp1[k]<0 ){ /* reduce/reduce conflict */ + settty(); + printf("\n%d: reduce/reduce conflict (red'ns %d and %d ) on %s", + i, -temp1[k], lastred, symnam(k) ); + if( -temp1[k] > lastred ) temp1[k] = -lastred; + ++zzrrconf; + settab(); + } + else { /* potential shift/reduce conflict */ + switch( precftn( lastred, k ) ) { + + case 0: /* precedence does not apply */ + + settty(); + printf("\n%d: shift/reduce conflict (shift %d, red'n %d) on %s", i, + temp1[k], lastred, symnam(k) ); + ++zzsrconf; + settab(); + break; + + case 1: /* reduce */ + + temp1[k] = -lastred; + break; + + case 2: /* error, binary operator */ + + temp1[k] = ERRCODE; + break; + + case 3: /* shift ... leave the entry alone */ + + break; + } + } + } + } + } + } + wract(i); + } + + settab(); + arrdone(); + + /* now, output the pointers to the action array */ + /* also output the info about reductions */ + prred(); + } + +prred(){ /* print the information about the actions and the reductions */ + int index, i; + + arrset("yypact"); + index = 1; /* position in the output table */ + + for( i=0; i0 ){ /* the state is real */ + temp1[i] = index; + arrval( index ); + index =+ tystate[i]; + } + else { + arrval( temp1[-tystate[i]] ); + } + } + + arrdone(); + + arrset("yyr1"); + for( i=1; i j ){ /* no actions */ + return(0); + } + j =- off; + for( k=0; k= actsiz ) error("action table overflow"); + if( k+l >= memact ) memact = k+l; + amem[k+l] = p[off+l]; + } + } + if( pkdebug ){ + for( k=0; k times ){ + best = cbest; + times = count; + } + } + + /* best is now the default entry */ + + zzgobest =+ (times-1)*2; + settab(); + for( j=0; j<=nstate; ++j ){ + if( tystate[j] != 0 && tystate[j]!=best ){ + arrval( j ); + arrval( tystate[j] ); + offset =+ 2; + zzgoent =+ 2; + } + } + + /* now, the default */ + + zzgoent =+ 2; + arrval( -1 ); + arrval( best ); + offset =+ 2; + + } + + arrdone(); + + arrset("yypgo"); + for( i=1; i<=nnonter; ++i ) arrval( temp2[i] ); + arrdone(); + + } + +int g2debug 0; +go2gen(c){ /* output the gotos for nonterminal c */ + + int i, work, cc; + struct item *p, *q; + + /* first, find nonterminals with gotos on c */ + + aryfil( temp1, nnonter+1, 0 ); + temp1[c] = 1; + + work = 1; + while( work ){ + work = 0; + for( i=0; i= 0 ){ /* cc is a nonterminal */ + if( temp1[cc] != 0 ){ /* cc has a goto on c */ + cc = *prdptr[i]-NTBASE; /* thus, the left side of production i does too */ + if( temp1[cc] == 0 ){ + work = 1; + temp1[cc] = 1; + } + } + } + } + } + + /* now, we have temp1[c] = 1 if a goto on c in closure of cc */ + + if( g2debug ){ + settty(); + printf("%s: gotos on ", nontrst[c].name ); + for( i=0; i<=nnonter; ++i ) if( temp1[i]) printf("%s ", nontrst[i].name); + printf("\n"); + } + + /* now, go through and put gotos into tystate */ + + aryfil( tystate, nstate, 0 ); + settty(); + printf("\nnonterminal %s\n", nontrst[c].name ); + for( i=0; ipitem) >= NTBASE ){ + if( temp1[cc =- NTBASE] ){ /* goto on c is possible */ + tystate[i] = amem[indgo[i]+c]; + break; + } + } + } + if( tystate[i] ) printf("\t%d\t%d\n", i, tystate[i]); + } + } + +precftn(r,t){ /* decide a shift/reduce conflict by precedence. + Returns 0 if action is 'do nothing',1 if action is reduce, + 2 if the action is 'error,binary operator' + and 3 if the action is 'reduce'. */ + + int lp,lt; + lp = levprd[r]; + lt = trmlev[t]; + if ((lt==0)||((lp&03)==0))return(0); + if((lt>>3) == (lp>>3)){ + return(lt&03); + } + if((lt>>3) > (lp>>3)) return(3); + return(1); + } + +int cdebug 0; /* debug for common states */ +wract(i){ /* output state i */ + /* temp1 has the actions, lastred the default */ + int p, p0, p1, size; + int ntimes, tred, count, j; + struct item *q0, *q1; + + /* find the best choice for lastred */ + + lastred = 0; + ntimes = 0; + for( j=1; j<=nterms; ++j ){ + if( temp1[j] >= 0 ) continue; + if( temp1[j]+lastred == 0 ) continue; + /* count the number of appearances of temp1[j] */ + count = 0; + tred = -temp1[j]; + for( p=1; p<=nterms; ++p ){ + if( temp1[p]+tred == 0 ) ++count; + } + if( count >ntimes ){ + lastred = tred; + ntimes = count; + } + } + + /* clear out entries in temp1 which equal lastred */ + for( p=1; p<= nterms; ++p ) if( temp1[p]+lastred == 0 )temp1[p]=0; + + /* write out the state */ + + /* first, check for equality with another state */ + /* see if there is a nonterminal with all dots before it. */ + + p0 = 0; + q1 = pstate[i+1]; + for( q0=pstate[i]; q0pitem) ) < NTBASE ) goto standard; + if( p0 == 0 ) p0 = p1; + else if( p0 != p1 ) goto standard; + } + + /* now, all items have dots before p0 */ + if( cdebug ){ + settty(); + printf("state %d, pre-nonterminal %s\n",i,nontrst[p0-NTBASE].name); + } + + for( j=0; jpitem) != p0 ) goto nextj; + } + + /* we have a match with state j ! */ + + tystate[i] = -j; + zzacsave =+ tystate[j]; + zznsave++; + wrstate(i); + return; + + nextj: ; + } + + + standard: + tystate[i] = 2; + wrstate(i); + + size = 0; + for( p0=1; p0<=nterms; ++p0 ) + if( (p1=temp1[p0])!=0 ) { + arrval( TESTACT+trmset[p0].value ); + if( p1 < 0 ) arrval( REDUCACT - p1 ); + else if( p1 == ACCEPTCODE ) arrval( ACCEPTACT ); + else if( p1 == ERRCODE ) arrval( ERRACT ); + else arrval( SHIFTACT + p1 ); + size =+ 2; + } + if( lastred ) arrval( REDUCACT + lastred ); + else arrval( ERRACT ); + tystate[i] = size+1; /* store entry size in tystate */ + zzacent =+ (size+1); + return; + } + +wrstate(i){ /* writes state i */ + int j0,j1,s; + struct item *pp, *qq; + settty(); + printf("\nstate %d\n",i); + qq = pstate[i+1]; + for( pp=pstate[i]; pp0 ){ /* shift, error, or accept */ + if( j1 == ACCEPTCODE ) printf( "accept" ); + else if( j1 == ERRCODE ) printf( "error" ); + else printf( "shift %d", j1 ); + } + else printf("reduce %d",-j1 ); + } + + /* output the final production */ + + if( lastred ) printf("\n\t. reduce %d\n\n", lastred ); + else printf("\n\t. error\n\n" ); + +ret: + settab(); + } diff --git a/source/yacc/source/y5.c b/source/yacc/source/y5.c new file mode 100644 index 0000000..54cf6ae --- /dev/null +++ b/source/yacc/source/y5.c @@ -0,0 +1,43 @@ +/* fake portable I/O routines, for those + sites so backward as to not have the + port. library */ + +int cin, cout; +extern int fin, fout; + +copen( s, c ) char *s; { + int f; + + if( c == 'r' ){ + fin = f = open( s, 0 ); + } + + else if( c == 'a' ){ + f = open( s, 1 ); + seek( f, 0, 2 ); + } + + else { /* c == w */ + f = creat( s, 0666 ); + } + + return( f ); + } + +cflush(x){ /* fake! sets file to x */ + flush(); + fout = x; + } + +system(){ + error( "The function \"system\" is called" ); + } + +cclose(i){ + close(i); + } + +cexit(i){ + flush(); + exit(); + } diff --git a/sys/buf.h b/sys/buf.h new file mode 100644 index 0000000..e526205 --- /dev/null +++ b/sys/buf.h @@ -0,0 +1,77 @@ +/* + * Each buffer in the pool is usually doubly linked into 2 lists: + * the device with which it is currently associated (always) + * and also on a list of blocks available for allocation + * for other use (usually). + * The latter list is kept in last-used order, and the two + * lists are doubly linked to make it easy to remove + * a buffer from one list when it was found by + * looking through the other. + * A buffer is on the available list, and is liable + * to be reassigned to another disk block, if and only + * if it is not marked BUSY. When a buffer is busy, the + * available-list pointers can be used for other purposes. + * Most drivers use the forward ptr as a link in their I/O + * active queue. + * A buffer header contains all the information required + * to perform I/O. + * Most of the routines which manipulate these things + * are in bio.c. + */ +struct buf +{ + int b_flags; /* see defines below */ + struct buf *b_forw; /* headed by devtab of b_dev */ + struct buf *b_back; /* " */ + struct buf *av_forw; /* position on free list, */ + struct buf *av_back; /* if not BUSY*/ + int b_dev; /* major+minor device name */ + int b_wcount; /* transfer count (usu. words) */ + char *b_addr; /* low order core address */ + char *b_xmem; /* high order core address */ + char *b_blkno; /* block # on device */ + char b_error; /* returned after I/O */ + char *b_resid; /* words not transferred after error */ +} buf[NBUF]; + +/* + * Each block device has a devtab, which contains private state stuff + * and 2 list heads: the b_forw/b_back list, which is doubly linked + * and has all the buffers currently associated with that major + * device; and the d_actf/d_actl list, which is private to the + * device but in fact is always used for the head and tail + * of the I/O queue for the device. + * Various routines in bio.c look at b_forw/b_back + * (notice they are the same as in the buf structure) + * but the rest is private to each device driver. + */ +struct devtab +{ + char d_active; /* busy flag */ + char d_errcnt; /* error count (for recovery) */ + struct buf *b_forw; /* first buffer for this dev */ + struct buf *b_back; /* last buffer for this dev */ + struct buf *d_actf; /* head of I/O queue */ + struct buf *d_actl; /* tail of I/O queue */ +}; + +/* + * This is the head of the queue of available + * buffers-- all unused except for the 2 list heads. + */ +struct buf bfreelist; + +/* + * These flags are kept in b_flags. + */ +#define B_WRITE 0 /* non-read pseudo-flag */ +#define B_READ 01 /* read when I/O occurs */ +#define B_DONE 02 /* transaction finished */ +#define B_ERROR 04 /* transaction aborted */ +#define B_BUSY 010 /* not on av_forw/back list */ +#define B_PHYS 020 /* Physical IO potentially using UNIBUS map */ +#define B_MAP 040 /* This block has the UNIBUS map allocated */ +#define B_WANTED 0100 /* issue wakeup when BUSY goes off */ +#define B_RELOC 0200 /* no longer used */ +#define B_ASYNC 0400 /* don't wait for I/O completion */ +#define B_DELWRI 01000 /* don't write till block leaves available list */ diff --git a/sys/conf.h b/sys/conf.h new file mode 100644 index 0000000..acb2b8d --- /dev/null +++ b/sys/conf.h @@ -0,0 +1,55 @@ +/* + * Used to dissect integer device code + * into major (driver designation) and + * minor (driver parameter) parts. + */ +struct +{ + char d_minor; + char d_major; +}; + +/* + * Declaration of block device + * switch. Each entry (row) is + * the only link between the + * main unix code and the driver. + * The initialization of the + * device switches is in the + * file conf.c. + */ +struct bdevsw +{ + int (*d_open)(); + int (*d_close)(); + int (*d_strategy)(); + int *d_tab; +} bdevsw[]; + +/* + * Nblkdev is the number of entries + * (rows) in the block switch. It is + * set in binit/bio.c by making + * a pass over the switch. + * Used in bounds checking on major + * device numbers. + */ +int nblkdev; + +/* + * Character device switch. + */ +struct cdevsw +{ + int (*d_open)(); + int (*d_close)(); + int (*d_read)(); + int (*d_write)(); + int (*d_sgtty)(); +} cdevsw[]; + +/* + * Number of character switch entries. + * Set by cinit/tty.c + */ +int nchrdev; diff --git a/sys/conf/data.s b/sys/conf/data.s new file mode 100644 index 0000000..4f7b7d1 --- /dev/null +++ b/sys/conf/data.s @@ -0,0 +1,3 @@ +/ l45.o needs to be in data space +/ to get l45.o; as data.s l.s +.data diff --git a/sys/conf/m40.s b/sys/conf/m40.s new file mode 100644 index 0000000..1651f25 --- /dev/null +++ b/sys/conf/m40.s @@ -0,0 +1,839 @@ +/ machine language assist +/ for 11/40 + +/ non-UNIX instructions +mfpi = 6500^tst +mtpi = 6600^tst +wait = 1 +rtt = 6 +reset = 5 + +.globl trap, call +.globl _trap +trap: + mov PS,-4(sp) + tst nofault + bne 1f + mov SSR0,ssr + mov SSR2,ssr+4 + mov $1,SSR0 + jsr r0,call1; _trap + / no return +1: + mov $1,SSR0 + mov nofault,(sp) + rtt + +.globl _runrun, _swtch +call1: + tst -(sp) + bic $340,PS + br 1f + +call: + mov PS,-(sp) +1: + mov r1,-(sp) + mfpi sp + mov 4(sp),-(sp) + bic $!37,(sp) + bit $30000,PS + beq 1f + jsr pc,*(r0)+ +2: + bis $340,PS + tstb _runrun + beq 2f + bic $340,PS + jsr pc,_swtch + br 2b +2: + tst (sp)+ + mtpi sp + br 2f +1: + bis $30000,PS + jsr pc,*(r0)+ + cmp (sp)+,(sp)+ +2: + mov (sp)+,r1 + tst (sp)+ + mov (sp)+,r0 + rtt + +.globl _savfp, _display +_savfp: +_display: + rts pc + +.globl _incupc +_incupc: + mov r2,-(sp) + mov 6(sp),r2 / base of prof with base,leng,off,scale + mov 4(sp),r0 / pc + sub 4(r2),r0 / offset + clc + ror r0 + mul 6(r2),r0 / scale + ashc $-14.,r0 + inc r1 + bic $1,r1 + cmp r1,2(r2) / length + bhis 1f + add (r2),r1 / base + mov nofault,-(sp) + mov $2f,nofault + mfpi (r1) + inc (sp) + mtpi (r1) + br 3f +2: + clr 6(r2) +3: + mov (sp)+,nofault +1: + mov (sp)+,r2 + rts pc + +/ Character list get/put + +.globl _getc, _putc +.globl _cfreelist + +_getc: + mov 2(sp),r1 + mov PS,-(sp) + mov r2,-(sp) + bis $340,PS + bic $100,PS / spl 5 + mov 2(r1),r2 / first ptr + beq 9f / empty + movb (r2)+,r0 / character + bic $!377,r0 + mov r2,2(r1) + dec (r1)+ / count + bne 1f + clr (r1)+ + clr (r1)+ / last block + br 2f +1: + bit $7,r2 + bne 3f + mov -10(r2),(r1) / next block + add $2,(r1) +2: + dec r2 + bic $7,r2 + mov _cfreelist,(r2) + mov r2,_cfreelist +3: + mov (sp)+,r2 + mov (sp)+,PS + rts pc +9: + clr 4(r1) + mov $-1,r0 + mov (sp)+,r2 + mov (sp)+,PS + rts pc + +_putc: + mov 2(sp),r0 + mov 4(sp),r1 + mov PS,-(sp) + mov r2,-(sp) + mov r3,-(sp) + bis $340,PS + bic $100,PS / spl 5 + mov 4(r1),r2 / last ptr + bne 1f + mov _cfreelist,r2 + beq 9f + mov (r2),_cfreelist + clr (r2)+ + mov r2,2(r1) / first ptr + br 2f +1: + bit $7,r2 + bne 2f + mov _cfreelist,r3 + beq 9f + mov (r3),_cfreelist + mov r3,-10(r2) + mov r3,r2 + clr (r2)+ +2: + movb r0,(r2)+ + mov r2,4(r1) + inc (r1) / count + clr r0 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,PS + rts pc +9: + mov pc,r0 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,PS + rts pc + +.globl _backup +.globl _regloc +_backup: + mov 2(sp),ssr+2 + mov r2,-(sp) + jsr pc,backup + mov r2,ssr+2 + mov (sp)+,r2 + movb jflg,r0 + bne 2f + mov 2(sp),r0 + movb ssr+2,r1 + jsr pc,1f + movb ssr+3,r1 + jsr pc,1f + movb _regloc+7,r1 + asl r1 + add r0,r1 + mov ssr+4,(r1) + clr r0 +2: + rts pc +1: + mov r1,-(sp) + asr (sp) + asr (sp) + asr (sp) + bic $!7,r1 + movb _regloc(r1),r1 + asl r1 + add r0,r1 + sub (sp)+,(r1) + rts pc + +/ hard part +/ simulate the ssr2 register missing on 11/40 + +backup: + clr r2 / backup register ssr1 + mov $1,bflg / clrs jflg + mov ssr+4,r0 + jsr pc,fetch + mov r0,r1 + ash $-11.,r0 + bic $!36,r0 + jmp *0f(r0) +0: t00; t01; t02; t03; t04; t05; t06; t07 + t10; t11; t12; t13; t14; t15; t16; t17 + +t00: + clrb bflg + +t10: + mov r1,r0 + swab r0 + bic $!16,r0 + jmp *0f(r0) +0: u0; u1; u2; u3; u4; u5; u6; u7 + +u6: / single op, m[tf]pi, sxt, illegal + bit $400,r1 + beq u5 / all but m[tf], sxt + bit $200,r1 + beq 1f / mfpi + bit $100,r1 + bne u5 / sxt + +/ simulate mtpi with double (sp)+,dd + bic $4000,r1 / turn instr into (sp)+ + br t01 + +/ simulate mfpi with double ss,-(sp) +1: + ash $6,r1 + bis $46,r1 / -(sp) + br t01 + +u4: / jsr + mov r1,r0 + jsr pc,setreg / assume no fault + bis $173000,r2 / -2 from sp + rts pc + +t07: / EIS + clrb bflg + +u0: / jmp, swab +u5: / single op + mov r1,r0 + br setreg + +t01: / mov +t02: / cmp +t03: / bit +t04: / bic +t05: / bis +t06: / add +t16: / sub + clrb bflg + +t11: / movb +t12: / cmpb +t13: / bitb +t14: / bicb +t15: / bisb + mov r1,r0 + ash $-6,r0 + jsr pc,setreg + swab r2 + mov r1,r0 + jsr pc,setreg + +/ if delta(dest) is zero, +/ no need to fetch source + + bit $370,r2 + beq 1f + +/ if mode(source) is R, +/ no fault is possible + + bit $7000,r1 + beq 1f + +/ if reg(source) is reg(dest), +/ too bad. + + mov r2,-(sp) + bic $174370,(sp) + cmpb 1(sp),(sp)+ + beq t17 + +/ start source cycle +/ pick up value of reg + + mov r1,r0 + ash $-6,r0 + bic $!7,r0 + movb _regloc(r0),r0 + asl r0 + add ssr+2,r0 + mov (r0),r0 + +/ if reg has been incremented, +/ must decrement it before fetch + + bit $174000,r2 + ble 2f + dec r0 + bit $10000,r2 + beq 2f + dec r0 +2: + +/ if mode is 6,7 fetch and add X(R) to R + + bit $4000,r1 + beq 2f + bit $2000,r1 + beq 2f + mov r0,-(sp) + mov ssr+4,r0 + add $2,r0 + jsr pc,fetch + add (sp)+,r0 +2: + +/ fetch operand +/ if mode is 3,5,7 fetch * + + jsr pc,fetch + bit $1000,r1 + beq 1f + bit $6000,r1 + bne fetch +1: + rts pc + +t17: / illegal +u1: / br +u2: / br +u3: / br +u7: / illegal + incb jflg + rts pc + +setreg: + mov r0,-(sp) + bic $!7,r0 + bis r0,r2 + mov (sp)+,r0 + ash $-3,r0 + bic $!7,r0 + movb 0f(r0),r0 + tstb bflg + beq 1f + bit $2,r2 + beq 2f + bit $4,r2 + beq 2f +1: + cmp r0,$20 + beq 2f + cmp r0,$-20 + beq 2f + asl r0 +2: + bisb r0,r2 + rts pc + +0: .byte 0,0,10,20,-10,-20,0,0 + +fetch: + bic $1,r0 + mov nofault,-(sp) + mov $1f,nofault + mfpi (r0) + mov (sp)+,r0 + mov (sp)+,nofault + rts pc + +1: + mov (sp)+,nofault + clrb r2 / clear out dest on fault + mov $-1,r0 + rts pc + +.bss +bflg: .=.+1 +jflg: .=.+1 +.text + +.globl _fubyte, _subyte +.globl _fuibyte, _suibyte +.globl _fuword, _suword +.globl _fuiword, _suiword +_fuibyte: +_fubyte: + mov 2(sp),r1 + bic $1,r1 + jsr pc,gword + cmp r1,2(sp) + beq 1f + swab r0 +1: + bic $!377,r0 + rts pc + +_suibyte: +_subyte: + mov 2(sp),r1 + bic $1,r1 + jsr pc,gword + mov r0,-(sp) + cmp r1,4(sp) + beq 1f + movb 6(sp),1(sp) + br 2f +1: + movb 6(sp),(sp) +2: + mov (sp)+,r0 + jsr pc,pword + clr r0 + rts pc + +_fuiword: +_fuword: + mov 2(sp),r1 +fuword: + jsr pc,gword + rts pc + +gword: + mov PS,-(sp) + bis $340,PS + mov nofault,-(sp) + mov $err,nofault + mfpi (r1) + mov (sp)+,r0 + br 1f + +_suiword: +_suword: + mov 2(sp),r1 + mov 4(sp),r0 +suword: + jsr pc,pword + rts pc + +pword: + mov PS,-(sp) + bis $340,PS + mov nofault,-(sp) + mov $err,nofault + mov r0,-(sp) + mtpi (r1) +1: + mov (sp)+,nofault + mov (sp)+,PS + rts pc + +err: + mov (sp)+,nofault + mov (sp)+,PS + tst (sp)+ + mov $-1,r0 + rts pc + +.globl _copyin, _copyout +_copyin: + jsr pc,copsu +1: + mfpi (r0)+ + mov (sp)+,(r1)+ + sob r2,1b + br 2f + +_copyout: + jsr pc,copsu +1: + mov (r0)+,-(sp) + mtpi (r1)+ + sob r2,1b +2: + mov (sp)+,nofault + mov (sp)+,r2 + clr r0 + rts pc + +copsu: + mov (sp)+,r0 + mov r2,-(sp) + mov nofault,-(sp) + mov r0,-(sp) + mov 10(sp),r0 + mov 12(sp),r1 + mov 14(sp),r2 + asr r2 + mov $1f,nofault + rts pc + +1: + mov (sp)+,nofault + mov (sp)+,r2 + mov $-1,r0 + rts pc + +.globl _idle +_idle: + mov PS,-(sp) + bic $340,PS + wait + mov (sp)+,PS + rts pc + +.globl _savu, _retu, _aretu +_savu: + bis $340,PS + mov (sp)+,r1 + mov (sp),r0 + mov sp,(r0)+ + mov r5,(r0)+ + bic $340,PS + jmp (r1) + +_aretu: + bis $340,PS + mov (sp)+,r1 + mov (sp),r0 + br 1f + +_retu: + bis $340,PS + mov (sp)+,r1 + mov (sp),KISA6 + mov $_u,r0 +1: + mov (r0)+,sp + mov (r0)+,r5 + bic $340,PS + jmp (r1) + +.globl _spl0, _spl1, _spl4, _spl5, _spl6, _spl7 +_spl0: + bic $340,PS + rts pc + +_spl1: + bis $40,PS + bic $300,PS + rts pc + +_spl4: +_spl5: + bis $340,PS + bic $100,PS + rts pc + +_spl6: + bis $340,PS + bic $40,PS + rts pc + +_spl7: + bis $340,PS + rts pc + +.globl _copyseg +_copyseg: + mov PS,-(sp) + mov UISA0,-(sp) + mov UISA1,-(sp) + mov $30340,PS + mov 10(sp),UISA0 + mov 12(sp),UISA1 + mov UISD0,-(sp) + mov UISD1,-(sp) + mov $6,UISD0 + mov $6,UISD1 + mov r2,-(sp) + clr r0 + mov $8192.,r1 + mov $32.,r2 +1: + mfpi (r0)+ + mtpi (r1)+ + sob r2,1b + mov (sp)+,r2 + mov (sp)+,UISD1 + mov (sp)+,UISD0 + mov (sp)+,UISA1 + mov (sp)+,UISA0 + mov (sp)+,PS + rts pc + +.globl _clearseg +_clearseg: + mov PS,-(sp) + mov UISA0,-(sp) + mov $30340,PS + mov 6(sp),UISA0 + mov UISD0,-(sp) + mov $6,UISD0 + clr r0 + mov $32.,r1 +1: + clr -(sp) + mtpi (r0)+ + sob r1,1b + mov (sp)+,UISD0 + mov (sp)+,UISA0 + mov (sp)+,PS + rts pc + +.globl _dpadd +_dpadd: + mov 2(sp),r0 + add 4(sp),2(r0) + adc (r0) + rts pc + +.globl _dpcmp +_dpcmp: + mov 2(sp),r0 + mov 4(sp),r1 + sub 6(sp),r0 + sub 8(sp),r1 + sbc r0 + bge 1f + cmp r0,$-1 + bne 2f + cmp r1,$-512. + bhi 3f +2: + mov $-512.,r0 + rts pc +1: + bne 2f + cmp r1,$512. + blo 3f +2: + mov $512.,r1 +3: + mov r1,r0 + rts pc + +.globl dump +dump: + bit $1,SSR0 + bne dump + +/ save regs r0,r1,r2,r3,r4,r5,r6,KIA6 +/ starting at abs location 4 + + mov r0,4 + mov $6,r0 + mov r1,(r0)+ + mov r2,(r0)+ + mov r3,(r0)+ + mov r4,(r0)+ + mov r5,(r0)+ + mov sp,(r0)+ + mov KISA6,(r0)+ + +/ dump all of core (ie to first mt error) +/ onto mag tape. (9 track or 7 track 'binary') + + mov $MTC,r0 + mov $60004,(r0)+ + clr 2(r0) +1: + mov $-512.,(r0) + inc -(r0) +2: + tstb (r0) + bge 2b + tst (r0)+ + bge 1b + reset + +/ end of file and loop + + mov $60007,-(r0) + br . + +.globl start, _end, _edata, _main +start: + bit $1,SSR0 + bne start / loop if restart + reset + +/ initialize systems segments + + mov $KISA0,r0 + mov $KISD0,r1 + mov $200,r4 + clr r2 + mov $6,r3 +1: + mov r2,(r0)+ + mov $77406,(r1)+ / 4k rw + add r4,r2 + sob r3,1b + +/ initialize user segment + + mov $_end+63.,r2 + ash $-6,r2 + bic $!1777,r2 + mov r2,(r0)+ / ksr6 = sysu + mov $usize-1\<8|6,(r1)+ + +/ initialize io segment +/ set up counts on supervisor segments + + mov $IO,(r0)+ + mov $77406,(r1)+ / rw 4k + +/ get a sp and start segmentation + + mov $_u+[usize*64.],sp + inc SSR0 + +/ clear bss + + mov $_edata,r0 +1: + clr (r0)+ + cmp r0,$_end + blo 1b + +/ clear user block + + mov $_u,r0 +1: + clr (r0)+ + cmp r0,$_u+[usize*64.] + blo 1b + +/ set up previous mode and call main +/ on return, enter user mode at 0R + + mov $30000,PS + jsr pc,_main + mov $170000,-(sp) + clr -(sp) + rtt + +.globl _ldiv +_ldiv: + clr r0 + mov 2(sp),r1 + div 4(sp),r0 + rts pc + +.globl _lrem +_lrem: + clr r0 + mov 2(sp),r1 + div 4(sp),r0 + mov r1,r0 + rts pc + +.globl _lshift +_lshift: + mov 2(sp),r1 + mov (r1)+,r0 + mov (r1),r1 + ashc 4(sp),r0 + mov r1,r0 + rts pc + +.globl csv +csv: + mov r5,r0 + mov sp,r5 + mov r4,-(sp) + mov r3,-(sp) + mov r2,-(sp) + jsr pc,(r0) + +.globl cret +cret: + mov r5,r1 + mov -(r1),r4 + mov -(r1),r3 + mov -(r1),r2 + mov r5,sp + mov (sp)+,r5 + rts pc + +.globl _u +_u = 140000 +usize = 16. + +PS = 177776 +SSR0 = 177572 +SSR2 = 177576 +KISA0 = 172340 +KISA6 = 172354 +KISD0 = 172300 +MTC = 172522 +UISA0 = 177640 +UISA1 = 177642 +UISD0 = 177600 +UISD1 = 177602 +IO = 7600 + +.data +.globl _ka6, _cputype +_ka6: KISA6 +_cputype:40. + +.bss +.globl nofault, ssr, badtrap +nofault:.=.+2 +ssr: .=.+6 +badtrap:.=.+2 diff --git a/sys/conf/m45.s b/sys/conf/m45.s new file mode 100644 index 0000000..e24ff0e --- /dev/null +++ b/sys/conf/m45.s @@ -0,0 +1,890 @@ +/ machine language assist +/ for 11/45 or 11/70 CPUs + +.fpp = 1 + +/ non-UNIX instructions +mfpi = 6500^tst +mtpi = 6600^tst +mfpd = 106500^tst +mtpd = 106600^tst +spl = 230 +ldfps = 170100^tst +stfps = 170200^tst +wait = 1 +rtt = 6 +reset = 5 + +HIPRI = 300 +HIGH = 6 + +/ Mag tape dump +/ save registers in low core and +/ write all core onto mag tape. +/ entry is thru 44 abs + +.data +.globl dump +dump: + bit $1,SSR0 + bne dump + +/ save regs r0,r1,r2,r3,r4,r5,r6,KIA6 +/ starting at abs location 4 + + mov r0,4 + mov $6,r0 + mov r1,(r0)+ + mov r2,(r0)+ + mov r3,(r0)+ + mov r4,(r0)+ + mov r5,(r0)+ + mov sp,(r0)+ + mov KDSA6,(r0)+ + +/ dump all of core (ie to first mt error) +/ onto mag tape. (9 track or 7 track 'binary') + + mov $MTC,r0 + mov $60004,(r0)+ + clr 2(r0) +1: + mov $-512.,(r0) + inc -(r0) +2: + tstb (r0) + bge 2b + tst (r0)+ + bge 1b + reset + +/ end of file and loop + + mov $60007,-(r0) + br . + +.globl start, _end, _edata, _etext, _main + +/ 11/45 and 11/70 startup. +/ entry is thru 0 abs. +/ since core is shuffled, +/ this code can be executed but once + +start: + inc $-1 + bne . + reset + clr PS + +/ set KI0 to physical 0 + + mov $77406,r3 + mov $KISA0,r0 + mov $KISD0,r1 + clr (r0)+ + mov r3,(r1)+ + +/ set KI1-6 to eventual text resting place + + mov $_end+63.,r2 + ash $-6,r2 + bic $!1777,r2 +1: + mov r2,(r0)+ + mov r3,(r1)+ + add $200,r2 + cmp r0,$KISA7 + blos 1b + +/ set KI7 to IO seg for escape + + mov $IO,-(r0) + +/ set KD0-7 to physical + + mov $KDSA0,r0 + mov $KDSD0,r1 + clr r2 +1: + mov r2,(r0)+ + mov r3,(r1)+ + add $200,r2 + cmp r0,$KDSA7 + blos 1b + +/ initialization +/ get a temp (1-word) stack +/ turn on segmentation +/ copy text to I space +/ clear bss in D space + + mov $stk+2,sp + mov $65,SSR3 / 22-bit, map, K+U sep + bit $20,SSR3 + beq 1f + mov $70.,_cputype +1: + inc SSR0 + mov $_etext,r0 + mov $_edata,r1 + add $_etext-8192.,r1 +1: + mov -(r1),-(sp) + mtpi -(r0) + cmp r1,$_edata + bhi 1b +1: + clr (r1)+ + cmp r1,$_end + blo 1b + +/ use KI escape to set KD7 to IO seg +/ set KD6 to first available core + + mov $IO,-(sp) + mtpi *$KDSA7 + mov $_etext-8192.+63.,r2 + ash $-6,r2 + bic $!1777,r2 + add KISA1,r2 + mov r2,KDSA6 + +/ set up supervisor D registers + + mov $6,SISD0 + mov $6,SISD1 + +/ set up real sp +/ clear user block + + mov $_u+[usize*64.],sp + mov $_u,r0 +1: + clr (r0)+ + cmp r0,sp + blo 1b +/ jsr pc,_isprof + +/ set up previous mode and call main +/ on return, enter user mode at 0R + + mov $30000,PS + jsr pc,_main + mov $170000,-(sp) + clr -(sp) + rtt + +.globl trap, call +.globl _trap + +/ all traps and interrupts are +/ vectored thru this routine. + +trap: + mov PS,saveps + tst nofault + bne 1f + mov SSR0,ssr + mov SSR1,ssr+2 + mov SSR2,ssr+4 + mov $1,SSR0 + jsr r0,call1; _trap + / no return +1: + mov $1,SSR0 + mov nofault,(sp) + rtt +.text + +.globl _runrun, _swtch +call1: + mov saveps,-(sp) + spl 0 + br 1f + +call: + mov PS,-(sp) +1: + mov r1,-(sp) + mfpd sp + mov 4(sp),-(sp) + bic $!37,(sp) + bit $30000,PS + beq 1f +.if .fpp + mov $20,_u+4 / FP maint mode +.endif + jsr pc,*(r0)+ +2: + spl HIGH + tstb _runrun + beq 2f + spl 0 + jsr pc,_savfp + jsr pc,_swtch + br 2b +2: +.if .fpp + mov $_u+4,r1 + bit $20,(r1) + bne 2f + mov (r1)+,r0 + ldfps r0 + movf (r1)+,fr0 + movf (r1)+,fr1 + movf fr1,fr4 + movf (r1)+,fr1 + movf fr1,fr5 + movf (r1)+,fr1 + movf (r1)+,fr2 + movf (r1)+,fr3 + ldfps r0 +2: +.endif + tst (sp)+ + mtpd sp + br 2f +1: + bis $30000,PS + jsr pc,*(r0)+ + cmp (sp)+,(sp)+ +2: + mov (sp)+,r1 + tst (sp)+ + mov (sp)+,r0 + rtt + +.globl _savfp +_savfp: +.if .fpp + mov $_u+4,r1 + bit $20,(r1) + beq 1f + stfps (r1)+ + movf fr0,(r1)+ + movf fr4,fr0 + movf fr0,(r1)+ + movf fr5,fr0 + movf fr0,(r1)+ + movf fr1,(r1)+ + movf fr2,(r1)+ + movf fr3,(r1)+ +1: +.endif + rts pc + +.globl _incupc +_incupc: + mov r2,-(sp) + mov 6(sp),r2 / base of prof with base,leng,off,scale + mov 4(sp),r0 / pc + sub 4(r2),r0 / offset + clc + ror r0 + mul 6(r2),r0 / scale + ashc $-14.,r0 + inc r1 + bic $1,r1 + cmp r1,2(r2) / length + bhis 1f + add (r2),r1 / base + mov nofault,-(sp) + mov $2f,nofault + mfpd (r1) + inc (sp) + mtpd (r1) + br 3f +2: + clr 6(r2) +3: + mov (sp)+,nofault +1: + mov (sp)+,r2 + rts pc + +.globl _display +_display: + dec dispdly + bge 2f + clr dispdly + mov PS,-(sp) + mov $HIPRI,PS + mov CSW,r1 + bit $1,r1 + beq 1f + bis $30000,PS + dec r1 +1: + jsr pc,fuword + mov r0,CSW + mov (sp)+,PS + cmp r0,$-1 + bne 2f + mov $120.,dispdly / 2 sec delay after CSW fault +2: + rts pc + +/ Character list get/put + +.globl _getc, _putc +.globl _cfreelist + +_getc: + mov 2(sp),r1 + mov PS,-(sp) + mov r2,-(sp) + spl 5 + mov 2(r1),r2 / first ptr + beq 9f / empty + movb (r2)+,r0 / character + bic $!377,r0 + mov r2,2(r1) + dec (r1)+ / count + bne 1f + clr (r1)+ + clr (r1)+ / last block + br 2f +1: + bit $7,r2 + bne 3f + mov -10(r2),(r1) / next block + add $2,(r1) +2: + dec r2 + bic $7,r2 + mov _cfreelist,(r2) + mov r2,_cfreelist +3: + mov (sp)+,r2 + mov (sp)+,PS + rts pc +9: + clr 4(r1) + mov $-1,r0 + mov (sp)+,r2 + mov (sp)+,PS + rts pc + +_putc: + mov 2(sp),r0 + mov 4(sp),r1 + mov PS,-(sp) + mov r2,-(sp) + mov r3,-(sp) + spl 5 + mov 4(r1),r2 / last ptr + bne 1f + mov _cfreelist,r2 + beq 9f + mov (r2),_cfreelist + clr (r2)+ + mov r2,2(r1) / first ptr + br 2f +1: + bit $7,r2 + bne 2f + mov _cfreelist,r3 + beq 9f + mov (r3),_cfreelist + mov r3,-10(r2) + mov r3,r2 + clr (r2)+ +2: + movb r0,(r2)+ + mov r2,4(r1) + inc (r1) / count + clr r0 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,PS + rts pc +9: + mov pc,r0 + mov (sp)+,r3 + mov (sp)+,r2 + mov (sp)+,PS + rts pc + +.globl _backup +.globl _regloc +_backup: + mov 2(sp),r0 + movb ssr+2,r1 + jsr pc,1f + movb ssr+3,r1 + jsr pc,1f + movb _regloc+7,r1 + asl r1 + add r0,r1 + mov ssr+4,(r1) + clr r0 +2: + rts pc +1: + mov r1,-(sp) + asr (sp) + asr (sp) + asr (sp) + bic $!7,r1 + movb _regloc(r1),r1 + asl r1 + add r0,r1 + sub (sp)+,(r1) + rts pc + + +.globl _fubyte, _subyte +.globl _fuword, _suword +.globl _fuibyte, _suibyte +.globl _fuiword, _suiword +_fuibyte: + mov 2(sp),r1 + bic $1,r1 + jsr pc,giword + br 2f + +_fubyte: + mov 2(sp),r1 + bic $1,r1 + jsr pc,gword + +2: + cmp r1,2(sp) + beq 1f + swab r0 +1: + bic $!377,r0 + rts pc + +_suibyte: + mov 2(sp),r1 + bic $1,r1 + jsr pc,giword + mov r0,-(sp) + cmp r1,4(sp) + beq 1f + movb 6(sp),1(sp) + br 2f +1: + movb 6(sp),(sp) +2: + mov (sp)+,r0 + jsr pc,piword + clr r0 + rts pc + +_subyte: + mov 2(sp),r1 + bic $1,r1 + jsr pc,gword + mov r0,-(sp) + cmp r1,4(sp) + beq 1f + movb 6(sp),1(sp) + br 2f +1: + movb 6(sp),(sp) +2: + mov (sp)+,r0 + jsr pc,pword + clr r0 + rts pc + +_fuiword: + mov 2(sp),r1 +fuiword: + jsr pc,giword + rts pc + +_fuword: + mov 2(sp),r1 +fuword: + jsr pc,gword + rts pc + +giword: + mov PS,-(sp) + spl HIGH + mov nofault,-(sp) + mov $err,nofault + mfpi (r1) + mov (sp)+,r0 + br 1f + +gword: + mov PS,-(sp) + spl HIGH + mov nofault,-(sp) + mov $err,nofault + mfpd (r1) + mov (sp)+,r0 + br 1f + +_suiword: + mov 2(sp),r1 + mov 4(sp),r0 +suiword: + jsr pc,piword + rts pc + +_suword: + mov 2(sp),r1 + mov 4(sp),r0 +suword: + jsr pc,pword + rts pc + +piword: + mov PS,-(sp) + spl HIGH + mov nofault,-(sp) + mov $err,nofault + mov r0,-(sp) + mtpi (r1) + br 1f + +pword: + mov PS,-(sp) + spl HIGH + mov nofault,-(sp) + mov $err,nofault + mov r0,-(sp) + mtpd (r1) +1: + mov (sp)+,nofault + mov (sp)+,PS + rts pc + +err: + mov (sp)+,nofault + mov (sp)+,PS + tst (sp)+ + mov $-1,r0 + rts pc + +.globl _copyin, _copyout +.globl _copyiin, _copyiout +_copyiin: + jsr pc,copsu +1: + mfpi (r0)+ + mov (sp)+,(r1)+ + sob r2,1b + br 2f + +_copyin: + jsr pc,copsu +1: + mfpd (r0)+ + mov (sp)+,(r1)+ + sob r2,1b + br 2f + +_copyiout: + jsr pc,copsu +1: + mov (r0)+,-(sp) + mtpi (r1)+ + sob r2,1b + br 2f + +_copyout: + jsr pc,copsu +1: + mov (r0)+,-(sp) + mtpd (r1)+ + sob r2,1b +2: + mov (sp)+,nofault + mov (sp)+,r2 + clr r0 + rts pc + +copsu: + mov (sp)+,r0 + mov r2,-(sp) + mov nofault,-(sp) + mov r0,-(sp) + mov 10(sp),r0 + mov 12(sp),r1 + mov 14(sp),r2 + asr r2 + mov $1f,nofault + rts pc + +1: + mov (sp)+,nofault + mov (sp)+,r2 + mov $-1,r0 + rts pc + +.globl _idle +_idle: + mov PS,-(sp) + spl 0 + wait + mov (sp)+,PS + rts pc + +.globl _savu, _retu, _aretu +_savu: + spl HIGH + mov (sp)+,r1 + mov (sp),r0 + mov sp,(r0)+ + mov r5,(r0)+ + spl 0 + jmp (r1) + +_aretu: + spl 7 + mov (sp)+,r1 + mov (sp),r0 + br 1f + +_retu: + spl 7 + mov (sp)+,r1 + mov (sp),KDSA6 + mov $_u,r0 +1: + mov (r0)+,sp + mov (r0)+,r5 + spl 0 + jmp (r1) + +.globl _spl0, _spl1, _spl4, _spl5, _spl6, _spl7 +_spl0: + spl 0 + rts pc + +_spl1: + spl 1 + rts pc + +_spl4: + spl 4 + rts pc + +_spl5: + spl 5 + rts pc + +_spl6: + spl 6 + rts pc + +_spl7: + spl HIGH + rts pc + +.globl _copyseg +_copyseg: + mov PS,-(sp) + mov 4(sp),SISA0 + mov 6(sp),SISA1 + mov $10000+HIPRI,PS + mov r2,-(sp) + clr r0 + mov $8192.,r1 + mov $32.,r2 +1: + mfpd (r0)+ + mtpd (r1)+ + sob r2,1b + mov (sp)+,r2 + mov (sp)+,PS + rts pc + +.globl _clearseg +_clearseg: + mov PS,-(sp) + mov 4(sp),SISA0 + mov $10000+HIPRI,PS + clr r0 + mov $32.,r1 +1: + clr -(sp) + mtpd (r0)+ + sob r1,1b + mov (sp)+,PS + rts pc + +.globl _dpadd +_dpadd: + mov 2(sp),r0 + add 4(sp),2(r0) + adc (r0) + rts pc + +.globl _dpcmp +_dpcmp: + mov 2(sp),r0 + mov 4(sp),r1 + sub 6(sp),r0 + sub 8(sp),r1 + sbc r0 + bge 1f + cmp r0,$-1 + bne 2f + cmp r1,$-512. + bhi 3f +2: + mov $-512.,r0 + rts pc +1: + bne 2f + cmp r1,$512. + blo 3f +2: + mov $512.,r1 +3: + mov r1,r0 + rts pc + +.globl _ldiv +_ldiv: + clr r0 + mov 2(sp),r1 + div 4(sp),r0 + rts pc + +.globl _lrem +_lrem: + clr r0 + mov 2(sp),r1 + div 4(sp),r0 + mov r1,r0 + rts pc + +.globl _lshift +_lshift: + mov 2(sp),r1 + mov (r1)+,r0 + mov (r1),r1 + ashc 4(sp),r0 + mov r1,r0 + rts pc + +.globl csv +csv: + mov r5,r0 + mov sp,r5 + mov r4,-(sp) + mov r3,-(sp) + mov r2,-(sp) + jsr pc,(r0) + +.globl cret +cret: + mov r5,r1 + mov -(r1),r4 + mov -(r1),r3 + mov -(r1),r2 + mov r5,sp + mov (sp)+,r5 + rts pc + +.globl _u +_u = 140000 +usize = 16. + +CSW = 177570 +PS = 177776 +SSR0 = 177572 +SSR1 = 177574 +SSR2 = 177576 +SSR3 = 172516 +KISA0 = 172340 +KISA1 = 172342 +KISA7 = 172356 +KISD0 = 172300 +KDSA0 = 172360 +KDSA6 = 172374 +KDSA7 = 172376 +KDSD0 = 172320 +MTC = 172522 +SISA0 = 172240 +SISA1 = 172242 +SISD0 = 172200 +SISD1 = 172202 +IO = 177600 + +.data +.globl _ka6 +.globl _cputype + +_ka6: KDSA6 +_cputype:45. +stk: 0 + +.bss +.globl nofault, ssr +nofault:.=.+2 +ssr: .=.+6 +dispdly:.=.+2 +saveps: .=.+2 + +.text +/ system profiler +/ +/rtt = 6 +/CCSB = 172542 +/CCSR = 172540 +/PS = 177776 +/ +/.globl _sprof, _xprobuf, _probuf, _probsiz, _mode +/_probsiz = 7500.+2048. +/ +/_isprof: +/ mov $_sprof,104 / interrupt +/ mov $340,106 / pri +/ mov $100.,CCSB / count set = 100 +/ mov $113,CCSR / count down, 10kHz, repeat +/ rts pc +/ +/_sprof: +/ mov r0,-(sp) +/ mov PS,r0 +/ ash $-11.,r0 +/ bic $!14,r0 +/ add $1,_mode+2(r0) +/ adc _mode(r0) +/ cmp r0,$14 / user +/ beq done +/ mov 2(sp),r0 / pc +/ asr r0 +/ asr r0 +/ bic $140001,r0 +/ cmp r0,$_probsiz +/ blo 1f +/ inc _outside +/ br done +/1: +/ inc _probuf(r0) +/ bne done +/ mov r1,-(sp) +/ mov $_xprobuf,r1 +/2: +/ cmp (r1)+,r0 +/ bne 3f +/ inc (r1) +/ br 4f +/3: +/ tst (r1)+ +/ bne 2b +/ sub $4,r1 +/ mov r0,(r1)+ +/ mov $1,(r1)+ +/4: +/ mov (sp)+,r1 +/done: +/ mov (sp)+,r0 +/ mov $113,CCSR +/ rtt +/ +/.bss +/_xprobuf: .=.+512. +/_probuf:.=.+_probsiz +/_mode: .=.+16. +/_outside: .=.+2 diff --git a/sys/conf/mkconf.c b/sys/conf/mkconf.c new file mode 100644 index 0000000..b198b9c --- /dev/null +++ b/sys/conf/mkconf.c @@ -0,0 +1,540 @@ +#define CHAR 01 +#define BLOCK 02 +#define INTR 04 +#define EVEN 010 +#define KL 020 +#define ROOT 040 +char *btab[] +{ + "rk", + "rp", + "rf", + "tm", + "tc", + "hs", + "hp", + "ht", + 0 +}; +char *ctab[] +{ + "console", + "pc", + "lp", + "dc", + "dh", + "dp", + "dj", + "dn", + "mem", + "rk", + "rf", + "rp", + "tm", + "hs", + "hp", + "ht", + 0 +}; +struct tab +{ + char *name; + int count; + int address; + int key; + char *codea; + char *codeb; + char *codec; + char *coded; + char *codee; +} table[] +{ + "console", + -1, 60, CHAR+INTR+KL, + "\tklin; br4\n\tklou; br4\n", + ".globl\t_klrint\nklin:\tjsr\tr0,call; _klrint\n", + ".globl\t_klxint\nklou:\tjsr\tr0,call; _klxint\n", + "", + "\t&klopen, &klclose, &klread, &klwrite, &klsgtty,", + + "mem", + -1, 300, CHAR, + "", + "", + "", + "", + "\t&nulldev, &nulldev, &mmread, &mmwrite, &nodev,", + + "pc", + 0, 70, CHAR+INTR, + "\tpcin; br4\n\tpcou; br4\n", + ".globl\t_pcrint\npcin:\tjsr\tr0,call; _pcrint\n", + ".globl\t_pcpint\npcou:\tjsr\tr0,call; _pcpint\n", + "", + "\t&pcopen, &pcclose, &pcread, &pcwrite, &nodev,", + + "clock", + -2, 100, INTR, + "\tkwlp; br6\n", + ".globl\t_clock\n", + "kwlp:\tjsr\tr0,call; _clock\n", + "", + "", + + "parity", + -1, 114, INTR, + "\ttrap; br7+7.\t\t/ 11/70 parity\n", + "", + "", + "", + "", + +/* + * 110 unused + * 114 memory parity + * 120 XY plotter + * 124 DR11-B + * 130 AD01 + * 134 AFC11 + * 140 AA11 + * 144 AA11 + * 150-174 unused + */ + + "lp", + 0, 200, CHAR+INTR, + "\tlpou; br4\n", + "", + ".globl\t_lpint\nlpou:\tjsr\tr0,call; _lpint\n", + "", + "\t&lpopen, &lpclose, &nodev, &lpwrite, &nodev,", + + "rf", + 0, 204, BLOCK+CHAR+INTR, + "\trfio; br5\n", + ".globl\t_rfintr\n", + "rfio:\tjsr\tr0,call; _rfintr\n", + "\t&nulldev,\t&nulldev,\t&rfstrategy, \t&rftab,", + "\t&nulldev, &nulldev, &rfread, &rfwrite, &nodev,", + + "hs", + 0, 204, BLOCK+CHAR+INTR, + "\thsio; br5\n", + ".globl\t_hsintr\n", + "hsio:\tjsr\tr0,call; _hsintr\n", + "\t&nulldev,\t&nulldev,\t&hsstrategy, \t&hstab,", + "\t&nulldev, &nulldev, &hsread, &hswrite, &nodev,", + +/* + * 210 RC + */ + + "tc", + 0, 214, BLOCK+INTR, + "\ttcio; br6\n", + ".globl\t_tcintr\n", + "tcio:\tjsr\tr0,call; _tcintr\n", + "\t&nulldev,\t&tcclose,\t&tcstrategy, \t&tctab,", + "", + + "rk", + 0, 220, BLOCK+CHAR+INTR, + "\trkio; br5\n", + ".globl\t_rkintr\n", + "rkio:\tjsr\tr0,call; _rkintr\n", + "\t&nulldev,\t&nulldev,\t&rkstrategy, \t&rktab,", + "\t&nulldev, &nulldev, &rkread, &rkwrite, &nodev,", + + "tm", + 0, 224, BLOCK+CHAR+INTR, + "\ttmio; br5\n", + ".globl\t_tmintr\n", + "tmio:\tjsr\tr0,call; _tmintr\n", + "\t&tmopen,\t&tmclose,\t&tmstrategy, \t&tmtab,", + "\t&tmopen, &tmclose, &tmread, &tmwrite, &nodev,", + + "ht", + 0, 224, BLOCK+CHAR+INTR, + "\thtio; br5\n", + ".globl\t_htintr\n", + "htio:\tjsr\tr0,call; _htintr\n", + "\t&htopen,\t&htclose,\t&htstrategy, \t&httab,", + "\t&htopen, &htclose, &htread, &htwrite, &nodev,", + + "cr", + 0, 230, CHAR+INTR, + "\tcrin; br6\n", + "", + ".globl\t_crint\ncrin:\tjsr\tr0,call; _crint\n", + "", + "\t&cropen, &crclose, &crread, &nodev, &nodev,", + +/* + * 234 UDC11 + */ + + "rp", + 0, 254, BLOCK+CHAR+INTR, + "\trpio; br5\n", + ".globl\t_rpintr\n", + "rpio:\tjsr\tr0,call; _rpintr\n", + "\t&nulldev,\t&nulldev,\t&rpstrategy, \t&rptab,", + "\t&nulldev, &nulldev, &rpread, &rpwrite, &nodev,", + + "hp", + 0, 254, BLOCK+CHAR+INTR, + "\thpio; br5\n", + ".globl\t_hpintr\n", + "hpio:\tjsr\tr0,call; _hpintr\n", + "\t&hpopen,\t&nulldev,\t&hpstrategy, \t&hptab,", + "\t&hpopen, &nulldev, &hpread, &hpwrite, &nodev,", + +/* + * 260 TA11 + * 264-274 unused + */ + + "dc", + 0, 308, CHAR+INTR, + "\tdcin; br5+%d.\n\tdcou; br5+%d.\n", + ".globl\t_dcrint\ndcin:\tjsr\tr0,call; _dcrint\n", + ".globl\t_dcxint\ndcou:\tjsr\tr0,call; _dcxint\n", + "", + "\t&dcopen, &dcclose, &dcread, &dcwrite, &dcsgtty,", + + "kl", + 0, 308, INTR+KL, + "\tklin; br4+%d.\n\tklou; br4+%d.\n", + "", + "", + "", + "", + + "dp", + 0, 308, CHAR+INTR, + "\tdpin; br6+%d.\n\tdpou; br6+%d.\n", + ".globl\t_dprint\ndpin:\tjsr\tr0,call; _dprint\n", + ".globl\t_dpxint\ndpou:\tjsr\tr0,call; _dpxint\n", + "", + "\t&dpopen, &dpclose, &dpread, &dpwrite, &nodev,", + +/* + * DM11-A + */ + + "dn", + 0, 304, CHAR+INTR, + "\tdnou; br5+%d.\n", + "", + ".globl\t_dnint\ndnou:\tjsr\tr0,call; _dnint\n", + "", + "\t&dnopen, &dnclose, &nodev, &dnwrite, &nodev,", + + "dhdm", + 0, 304, INTR, + "\tdmin; br4+%d.\n", + "", + ".globl\t_dmint\ndmin:\tjsr\tr0,call; _dmint\n", + "", + "", + +/* + * DR11-A+ + * DR11-C+ + * PA611+ + * PA611+ + * DT11+ + * DX11+ + */ + + "dl", + 0, 308, INTR+KL, + "\tklin; br4+%d.\n\tklou; br4+%d.\n", + "", + "", + "", + "", + +/* + * DJ11 + */ + + "dh", + 0, 308, CHAR+INTR+EVEN, + "\tdhin; br5+%d.\n\tdhou; br5+%d.\n", + ".globl\t_dhrint\ndhin:\tjsr\tr0,call; _dhrint\n", + ".globl\t_dhxint\ndhou:\tjsr\tr0,call; _dhxint\n", + "", + "\t&dhopen, &dhclose, &dhread, &dhwrite, &dhsgtty,", + +/* + * GT40 + * LPS+ + * VT20 + */ + + 0 +}; + +char *stra[] +{ + "/ low core", + "", + "br4 = 200", + "br5 = 240", + "br6 = 300", + "br7 = 340", + "", + ". = 0^.", + "\tbr\t1f", + "\t4", + "", + "/ trap vectors", + "\ttrap; br7+0.\t\t/ bus error", + "\ttrap; br7+1.\t\t/ illegal instruction", + "\ttrap; br7+2.\t\t/ bpt-trace trap", + "\ttrap; br7+3.\t\t/ iot trap", + "\ttrap; br7+4.\t\t/ power fail", + "\ttrap; br7+5.\t\t/ emulator trap", + "\ttrap; br7+6.\t\t/ system entry", + "", + ". = 40^.", + ".globl\tstart, dump", + "1:\tjmp\tstart", + "\tjmp\tdump", + "", + 0, +}; + +char *strb[] +{ + "", + ". = 240^.", + "\ttrap; br7+7.\t\t/ programmed interrupt", + "\ttrap; br7+8.\t\t/ floating point", + "\ttrap; br7+9.\t\t/ segmentation violation", + 0 +}; + +char *strc[] +{ + "", + "/ floating vectors", + ". = 300^.", + 0, +}; + +char *strd[] +{ + "", + "//////////////////////////////////////////////////////", + "/\t\tinterface code to C", + "//////////////////////////////////////////////////////", + "", + ".globl\tcall, trap", + 0 +}; + +char *stre[] +{ + "/*", + " */", + "", + "int\t(*bdevsw[])()", + "{", + 0, +}; + +char *strf[] +{ + "\t0", + "};", + "", + "int\t(*cdevsw[])()", + "{", + 0, +}; + +char *strg[] +{ + "\t0", + "};", + "", + "int\trootdev\t{(%d<<8)|0};", + "int\tswapdev\t{(%d<<8)|0};", + "int\tswplo\t4000;\t/* cannot be zero */", + "int\tnswap\t872;", + 0, +}; + +int fout; +int root -1; + +main() +{ + register struct tab *p; + register *q; + int i, n, ev, nkl; + int flagf, flagb; + + while(input()); + +/* + * pass1 -- create interrupt vectors + */ + nkl = 0; + flagf = flagb = 1; + fout = creat("l.s", 0666); + puke(stra); + for(p=table; p->name; p++) + if(p->count != 0 && p->key & INTR) { + if(p->address>240 && flagb) { + flagb = 0; + puke(strb); + } + if(p->address >= 300) { + if(flagf) { + ev = 0; + flagf = 0; + puke(strc); + } + if(p->key & EVEN && ev & 07) { + printf("\t.=.+4\n"); + ev =+ 4; + } + ev =+ p->address - 300; + } else + printf("\n. = %d^.\n", p->address); + n = p->count; + if(n < 0) + n = -n; + for(i=0; ikey & KL) { + printf(p->codea, nkl, nkl); + nkl++; + } else + printf(p->codea, i, i); + } + if(flagb) + puke(strb); + puke(strd); + for(p=table; p->name; p++) + if(p->count != 0 && p->key & INTR) + printf("\n%s%s", p->codeb, p->codec); + flush(); + close(fout); + +/* + * pass 2 -- create configuration table + */ + + fout = creat("c.c", 0666); + puke(stre); + for(i=0; q=btab[i]; i++) { + for(p=table; p->name; p++) + if(equal(q, p->name) && + (p->key&BLOCK) && p->count) { + printf("%s\t/* %s */\n", p->coded, q); + if(p->key & ROOT) + root = i; + goto newb; + } + printf("\t&nodev,\t\t&nodev,\t\t&nodev,\t\t0,\t/* %s */\n", q); + newb:; + } + puke(strf); + for(i=0; q=ctab[i]; i++) { + for(p=table; p->name; p++) + if(equal(q, p->name) && + (p->key&CHAR) && p->count) { + printf("%s\t/* %s */\n", p->codee, q); + goto newc; + } + printf("\t&nodev, &nodev, &nodev, &nodev, &nodev,\t/* %s */\n", q); + newc:; + } + puke(strg, root); + flush(); + close(fout); + if(root < 0) + write(2, "no block device given\n", 22); +} + +puke(s, a) +char **s; +{ + char *c; + + while(c = *s++) { + printf(c, a); + printf("\n"); + } +} + +input() +{ + char line[100]; + register char *p; + register struct tab *q; + register n; + + p = line; + while((n=getchar()) != '\n') { + if(n == 0) + return(0); + if(n == ' ' || n == '\t') + continue; + *p++ = n; + } + *p++ = 0; + n = 0; + p = line; + while(*p>='0' && *p<='9') { + n =* 10; + n =+ *p++ - '0'; + } + if(n == 0) + n = 1; + if(*p == 0) + return(1); + for(q=table; q->name; q++) + if(equal(q->name, p)) { + if(root < 0 && (q->key&BLOCK)) { + root = 0; + q->key =| ROOT; + } + if(q->count < 0) { + printf("%s: no more, no less\n", p); + return(1); + } + q->count =+ n; + if(q->address < 300 && q->count > 1) { + q->count = 1; + printf("%s: only one\n", p); + } + return(1); + } + if(equal(p, "done")) + return(0); + printf("%s: cannot find\n", p); + return(1); +} + +equal(a, b) +char *a, *b; +{ + + while(*a++ == *b) + if(*b++ == 0) + return(1); + return(0); +} + +getchar() +{ + int c; + + c = 0; + read(0, &c, 1); + return(c); +} diff --git a/sys/conf/sysfix b/sys/conf/sysfix new file mode 100755 index 0000000..9edb329 Binary files /dev/null and b/sys/conf/sysfix differ diff --git a/sys/conf/sysfix.c b/sys/conf/sysfix.c new file mode 100644 index 0000000..33545e1 --- /dev/null +++ b/sys/conf/sysfix.c @@ -0,0 +1,146 @@ +/* + * fix system image for I/D space + * Move data down to 0; move text to 4K. + * Also put the data at the start of the + * file and the text after it. + */ + +int tbuf[259]; +int rbuf[259]; +int obuf[259]; +int txtsiz; +int datsiz; +int bsssiz; +int symsiz; + +int txtrel 8192; +int datrel; + + +main(argc, argv) +char **argv; +{ + register word, rel, s; + + if (argc<3) { + printf("Arg count\n"); + exit(1); + } + if ((tbuf[0] = open(argv[1], 0)) < 0) { + printf("Input file\n"); + exit(1); + } + rbuf[0] = open(argv[1], 0); + if ((fcreat(argv[2], obuf)) < 0) { + printf("Output file\n"); + exit(1); + } + if (getw(tbuf) != 0407) { + printf("Bad input format\n"); + exit(1); + } + putw(0407, obuf); + txtsiz = getw(tbuf); + datsiz = getw(tbuf); + bsssiz = getw(tbuf); + symsiz = getw(tbuf); + getw(tbuf); + getw(tbuf); + if (getw(tbuf) != 0) { + printf("No relocation bits\n"); + exit(1); + } + putw(txtsiz, obuf); + putw(datsiz, obuf); + putw(bsssiz, obuf); + putw(symsiz, obuf); + putw(0, obuf); + putw(0, obuf); + putw(1, obuf); + datrel = -txtsiz; +/* + * Copy out data first + */ + tbuf[1] = 0; + seek(tbuf[0], 020+txtsiz, 0); + seek(rbuf[0], 020+txtsiz, 0); + seek(rbuf[0], txtsiz, 1); + seek(rbuf[0], datsiz, 1); + s = datsiz >> 1; + while (s--) { + word = getw(tbuf); + rel = getw(rbuf); + if (rel&01) + word =- datrel; + word =+ getrel(rel); + putw(word, obuf); + } +/* + * Now to the text. + */ + rbuf[1] = 0; + tbuf[1] = 0; + seek(rbuf[0], 020+txtsiz, 0); + seek(rbuf[0], datsiz, 1); + seek(tbuf[0], 020, 0); + s = txtsiz >> 1; + while(s--) { + rel = getw(rbuf); + word = getw(tbuf); + if (rel&01) + word =- txtrel; + word =+ getrel(rel); + putw(word, obuf); + } +/* + * The symbol table. + */ + tbuf[1] = 0; + seek(tbuf[0], 020+txtsiz, 0); + seek(tbuf[0], txtsiz, 1); + seek(tbuf[0], datsiz, 1); + seek(tbuf[0], datsiz, 1); + s = symsiz; + while ((s =- 12) >= 0) { + putw(getw(tbuf), obuf); + putw(getw(tbuf), obuf); + putw(getw(tbuf), obuf); + putw(getw(tbuf), obuf); + rel = getw(tbuf); + putw(rel, obuf); + word = getw(tbuf); + switch(rel&07) { + case 2: + word =+ txtrel; + break; + + case 3: + case 4: + word =+ datrel; + } + putw(word, obuf); + } + fflush(obuf); + close(obuf[0]); + exit(0); +} + +getrel(r) +{ + switch (r&016) { + + case 02: /* ref to text */ + return(txtrel); + + case 04: /* ref to data */ + case 06: /* ref to bss */ + return(datrel); + + case 0: + return(0); + + default: + printf("Bad relocation %o\n", r); + return(0); + } +} diff --git a/sys/dmr/bio.c b/sys/dmr/bio.c new file mode 100644 index 0000000..340159b --- /dev/null +++ b/sys/dmr/bio.c @@ -0,0 +1,636 @@ +# +/* + */ + +#include "../param.h" +#include "../user.h" +#include "../buf.h" +#include "../conf.h" +#include "../systm.h" +#include "../proc.h" +#include "../seg.h" + +/* + * This is the set of buffers proper, whose heads + * were declared in buf.h. There can exist buffer + * headers not pointing here that are used purely + * as arguments to the I/O routines to describe + * I/O to be done-- e.g. swbuf, just below, for + * swapping. + */ +char buffers[NBUF][514]; +struct buf swbuf; + +/* + * Declarations of the tables for the magtape devices; + * see bdwrite. + */ +int tmtab; +int httab; + +/* + * The following several routines allocate and free + * buffers with various side effects. In general the + * arguments to an allocate routine are a device and + * a block number, and the value is a pointer to + * to the buffer header; the buffer is marked "busy" + * so that no on else can touch it. If the block was + * already in core, no I/O need be done; if it is + * already busy, the process waits until it becomes free. + * The following routines allocate a buffer: + * getblk + * bread + * breada + * Eventually the buffer must be released, possibly with the + * side effect of writing it out, by using one of + * bwrite + * bdwrite + * bawrite + * brelse + */ + +/* + * Read in (if necessary) the block and return a buffer pointer. + */ +bread(dev, blkno) +{ + register struct buf *rbp; + + rbp = getblk(dev, blkno); + if (rbp->b_flags&B_DONE) + return(rbp); + rbp->b_flags =| B_READ; + rbp->b_wcount = -256; + (*bdevsw[dev.d_major].d_strategy)(rbp); + iowait(rbp); + return(rbp); +} + +/* + * Read in the block, like bread, but also start I/O on the + * read-ahead block (which is not allocated to the caller) + */ +breada(adev, blkno, rablkno) +{ + register struct buf *rbp, *rabp; + register int dev; + + dev = adev; + rbp = 0; + if (!incore(dev, blkno)) { + rbp = getblk(dev, blkno); + if ((rbp->b_flags&B_DONE) == 0) { + rbp->b_flags =| B_READ; + rbp->b_wcount = -256; + (*bdevsw[adev.d_major].d_strategy)(rbp); + } + } + if (rablkno && !incore(dev, rablkno)) { + rabp = getblk(dev, rablkno); + if (rabp->b_flags & B_DONE) + brelse(rabp); + else { + rabp->b_flags =| B_READ|B_ASYNC; + rabp->b_wcount = -256; + (*bdevsw[adev.d_major].d_strategy)(rabp); + } + } + if (rbp==0) + return(bread(dev, blkno)); + iowait(rbp); + return(rbp); +} + +/* + * Write the buffer, waiting for completion. + * Then release the buffer. + */ +bwrite(bp) +struct buf *bp; +{ + register struct buf *rbp; + register flag; + + rbp = bp; + flag = rbp->b_flags; + rbp->b_flags =& ~(B_READ | B_DONE | B_ERROR | B_DELWRI); + rbp->b_wcount = -256; + (*bdevsw[rbp->b_dev.d_major].d_strategy)(rbp); + if ((flag&B_ASYNC) == 0) { + iowait(rbp); + brelse(rbp); + } else if ((flag&B_DELWRI)==0) + geterror(rbp); +} + +/* + * Release the buffer, marking it so that if it is grabbed + * for another purpose it will be written out before being + * given up (e.g. when writing a partial block where it is + * assumed that another write for the same block will soon follow). + * This can't be done for magtape, since writes must be done + * in the same order as requested. + */ +bdwrite(bp) +struct buf *bp; +{ + register struct buf *rbp; + register struct devtab *dp; + + rbp = bp; + dp = bdevsw[rbp->b_dev.d_major].d_tab; + if (dp == &tmtab || dp == &httab) + bawrite(rbp); + else { + rbp->b_flags =| B_DELWRI | B_DONE; + brelse(rbp); + } +} + +/* + * Release the buffer, start I/O on it, but don't wait for completion. + */ +bawrite(bp) +struct buf *bp; +{ + register struct buf *rbp; + + rbp = bp; + rbp->b_flags =| B_ASYNC; + bwrite(rbp); +} + +/* + * release the buffer, with no I/O implied. + */ +brelse(bp) +struct buf *bp; +{ + register struct buf *rbp, **backp; + register int sps; + + rbp = bp; + if (rbp->b_flags&B_WANTED) + wakeup(rbp); + if (bfreelist.b_flags&B_WANTED) { + bfreelist.b_flags =& ~B_WANTED; + wakeup(&bfreelist); + } + if (rbp->b_flags&B_ERROR) + rbp->b_dev.d_minor = -1; /* no assoc. on error */ + backp = &bfreelist.av_back; + sps = PS->integ; + spl6(); + rbp->b_flags =& ~(B_WANTED|B_BUSY|B_ASYNC); + (*backp)->av_forw = rbp; + rbp->av_back = *backp; + *backp = rbp; + rbp->av_forw = &bfreelist; + PS->integ = sps; +} + +/* + * See if the block is associated with some buffer + * (mainly to avoid getting hung up on a wait in breada) + */ +incore(adev, blkno) +{ + register int dev; + register struct buf *bp; + register struct devtab *dp; + + dev = adev; + dp = bdevsw[adev.d_major].d_tab; + for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) + if (bp->b_blkno==blkno && bp->b_dev==dev) + return(bp); + return(0); +} + +/* + * Assign a buffer for the given block. If the appropriate + * block is already associated, return it; otherwise search + * for the oldest non-busy buffer and reassign it. + * When a 512-byte area is wanted for some random reason + * (e.g. during exec, for the user arglist) getblk can be called + * with device NODEV to avoid unwanted associativity. + */ +getblk(dev, blkno) +{ + register struct buf *bp; + register struct devtab *dp; + extern lbolt; + + if(dev.d_major >= nblkdev) + panic("blkdev"); + + loop: + if (dev < 0) + dp = &bfreelist; + else { + dp = bdevsw[dev.d_major].d_tab; + if(dp == NULL) + panic("devtab"); + for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) { + if (bp->b_blkno!=blkno || bp->b_dev!=dev) + continue; + spl6(); + if (bp->b_flags&B_BUSY) { + bp->b_flags =| B_WANTED; + sleep(bp, PRIBIO); + spl0(); + goto loop; + } + spl0(); + notavail(bp); + return(bp); + } + } + spl6(); + if (bfreelist.av_forw == &bfreelist) { + bfreelist.b_flags =| B_WANTED; + sleep(&bfreelist, PRIBIO); + spl0(); + goto loop; + } + spl0(); + notavail(bp = bfreelist.av_forw); + if (bp->b_flags & B_DELWRI) { + bp->b_flags =| B_ASYNC; + bwrite(bp); + goto loop; + } + bp->b_flags = B_BUSY | B_RELOC; + bp->b_back->b_forw = bp->b_forw; + bp->b_forw->b_back = bp->b_back; + bp->b_forw = dp->b_forw; + bp->b_back = dp; + dp->b_forw->b_back = bp; + dp->b_forw = bp; + bp->b_dev = dev; + bp->b_blkno = blkno; + return(bp); +} + +/* + * Wait for I/O completion on the buffer; return errors + * to the user. + */ +iowait(bp) +struct buf *bp; +{ + register struct buf *rbp; + + rbp = bp; + spl6(); + while ((rbp->b_flags&B_DONE)==0) + sleep(rbp, PRIBIO); + spl0(); + geterror(rbp); +} + +/* + * Unlink a buffer from the available list and mark it busy. + * (internal interface) + */ +notavail(bp) +struct buf *bp; +{ + register struct buf *rbp; + register int sps; + + rbp = bp; + sps = PS->integ; + spl6(); + rbp->av_back->av_forw = rbp->av_forw; + rbp->av_forw->av_back = rbp->av_back; + rbp->b_flags =| B_BUSY; + PS->integ = sps; +} + +/* + * Mark I/O complete on a buffer, release it if I/O is asynchronous, + * and wake up anyone waiting for it. + */ +iodone(bp) +struct buf *bp; +{ + register struct buf *rbp; + + rbp = bp; + if(rbp->b_flags&B_MAP) + mapfree(rbp); + rbp->b_flags =| B_DONE; + if (rbp->b_flags&B_ASYNC) + brelse(rbp); + else { + rbp->b_flags =& ~B_WANTED; + wakeup(rbp); + } +} + +/* + * Zero the core associated with a buffer. + */ +clrbuf(bp) +int *bp; +{ + register *p; + register c; + + p = bp->b_addr; + c = 256; + do + *p++ = 0; + while (--c); +} + +/* + * Initialize the buffer I/O system by freeing + * all buffers and setting all device buffer lists to empty. + */ +binit() +{ + register struct buf *bp; + register struct devtab *dp; + register int i; + struct bdevsw *bdp; + + bfreelist.b_forw = bfreelist.b_back = + bfreelist.av_forw = bfreelist.av_back = &bfreelist; + for (i=0; ib_dev = -1; + bp->b_addr = buffers[i]; + bp->b_back = &bfreelist; + bp->b_forw = bfreelist.b_forw; + bfreelist.b_forw->b_back = bp; + bfreelist.b_forw = bp; + bp->b_flags = B_BUSY; + brelse(bp); + } + i = 0; + for (bdp = bdevsw; bdp->d_open; bdp++) { + dp = bdp->d_tab; + if(dp) { + dp->b_forw = dp; + dp->b_back = dp; + } + i++; + } + nblkdev = i; +} + +/* + * Device start routine for disks + * and other devices that have the register + * layout of the older DEC controllers (RF, RK, RP, TM) + */ +#define IENABLE 0100 +#define WCOM 02 +#define RCOM 04 +#define GO 01 +devstart(bp, devloc, devblk, hbcom) +struct buf *bp; +int *devloc; +{ + register int *dp; + register struct buf *rbp; + register int com; + + dp = devloc; + rbp = bp; + *dp = devblk; /* block address */ + *--dp = rbp->b_addr; /* buffer address */ + *--dp = rbp->b_wcount; /* word count */ + com = (hbcom<<8) | IENABLE | GO | + ((rbp->b_xmem & 03) << 4); + if (rbp->b_flags&B_READ) /* command + x-mem */ + com =| RCOM; + else + com =| WCOM; + *--dp = com; +} + +/* + * startup routine for RH controllers. + */ +#define RHWCOM 060 +#define RHRCOM 070 + +rhstart(bp, devloc, devblk, abae) +struct buf *bp; +int *devloc, *abae; +{ + register int *dp; + register struct buf *rbp; + register int com; + + dp = devloc; + rbp = bp; + if(cputype == 70) + *abae = rbp->b_xmem; + *dp = devblk; /* block address */ + *--dp = rbp->b_addr; /* buffer address */ + *--dp = rbp->b_wcount; /* word count */ + com = IENABLE | GO | + ((rbp->b_xmem & 03) << 8); + if (rbp->b_flags&B_READ) /* command + x-mem */ + com =| RHRCOM; else + com =| RHWCOM; + *--dp = com; +} + +/* + * 11/70 routine to allocate the + * UNIBUS map and initialize for + * a unibus device. + * The code here and in + * rhstart assumes that an rh on an 11/70 + * is an rh70 and contains 22 bit addressing. + */ +int maplock; +mapalloc(abp) +struct buf *abp; +{ + register i, a; + register struct buf *bp; + + if(cputype != 70) + return; + spl6(); + while(maplock&B_BUSY) { + maplock =| B_WANTED; + sleep(&maplock, PSWP); + } + maplock =| B_BUSY; + spl0(); + bp = abp; + bp->b_flags =| B_MAP; + a = bp->b_xmem; + for(i=16; i<32; i=+2) + UBMAP->r[i+1] = a; + for(a++; i<48; i=+2) + UBMAP->r[i+1] = a; + bp->b_xmem = 1; +} + +mapfree(bp) +struct buf *bp; +{ + + bp->b_flags =& ~B_MAP; + if(maplock&B_WANTED) + wakeup(&maplock); + maplock = 0; +} + +/* + * swap I/O + */ +swap(blkno, coreaddr, count, rdflg) +{ + register int *fp; + + fp = &swbuf.b_flags; + spl6(); + while (*fp&B_BUSY) { + *fp =| B_WANTED; + sleep(fp, PSWP); + } + *fp = B_BUSY | B_PHYS | rdflg; + swbuf.b_dev = swapdev; + swbuf.b_wcount = - (count<<5); /* 32 w/block */ + swbuf.b_blkno = blkno; + swbuf.b_addr = coreaddr<<6; /* 64 b/block */ + swbuf.b_xmem = (coreaddr>>10) & 077; + (*bdevsw[swapdev>>8].d_strategy)(&swbuf); + spl6(); + while((*fp&B_DONE)==0) + sleep(fp, PSWP); + if (*fp&B_WANTED) + wakeup(fp); + spl0(); + *fp =& ~(B_BUSY|B_WANTED); + return(*fp&B_ERROR); +} + +/* + * make sure all write-behind blocks + * on dev (or NODEV for all) + * are flushed out. + * (from umount and update) + */ +bflush(dev) +{ + register struct buf *bp; + +loop: + spl6(); + for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) { + if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) { + bp->b_flags =| B_ASYNC; + notavail(bp); + bwrite(bp); + goto loop; + } + } + spl0(); +} + +/* + * Raw I/O. The arguments are + * The strategy routine for the device + * A buffer, which will always be a special buffer + * header owned exclusively by the device for this purpose + * The device number + * Read/write flag + * Essentially all the work is computing physical addresses and + * validating them. + */ +physio(strat, abp, dev, rw) +struct buf *abp; +int (*strat)(); +{ + register struct buf *bp; + register char *base; + register int nb; + int ts; + + bp = abp; + base = u.u_base; + /* + * Check odd base, odd count, and address wraparound + */ + if (base&01 || u.u_count&01 || base>=base+u.u_count) + goto bad; + ts = (u.u_tsize+127) & ~0177; + if (u.u_sep) + ts = 0; + nb = (base>>6) & 01777; + /* + * Check overlap with text. (ts and nb now + * in 64-byte clicks) + */ + if (nb < ts) + goto bad; + /* + * Check that transfer is either entirely in the + * data or in the stack: that is, either + * the end is in the data or the start is in the stack + * (remember wraparound was already checked). + */ + if ((((base+u.u_count)>>6)&01777) >= ts+u.u_dsize + && nb < 1024-u.u_ssize) + goto bad; + spl6(); + while (bp->b_flags&B_BUSY) { + bp->b_flags =| B_WANTED; + sleep(bp, PRIBIO); + } + bp->b_flags = B_BUSY | B_PHYS | rw; + bp->b_dev = dev; + /* + * Compute physical address by simulating + * the segmentation hardware. + */ + bp->b_addr = base&077; + base = (u.u_sep? UDSA: UISA)->r[nb>>7] + (nb&0177); + bp->b_addr =+ base<<6; + bp->b_xmem = (base>>10) & 077; + bp->b_blkno = lshift(u.u_offset, -9); + bp->b_wcount = -((u.u_count>>1) & 077777); + bp->b_error = 0; + u.u_procp->p_flag =| SLOCK; + (*strat)(bp); + spl6(); + while ((bp->b_flags&B_DONE) == 0) + sleep(bp, PRIBIO); + u.u_procp->p_flag =& ~SLOCK; + if (bp->b_flags&B_WANTED) + wakeup(bp); + spl0(); + bp->b_flags =& ~(B_BUSY|B_WANTED); + u.u_count = (-bp->b_resid)<<1; + geterror(bp); + return; + bad: + u.u_error = EFAULT; +} + +/* + * Pick up the device's error number and pass it to the user; + * if there is an error but the number is 0 set a generalized + * code. Actually the latter is always true because devices + * don't yet return specific errors. + */ +geterror(abp) +struct buf *abp; +{ + register struct buf *bp; + + bp = abp; + if (bp->b_flags&B_ERROR) + if ((u.u_error = bp->b_error)==0) + u.u_error = EIO; +} diff --git a/sys/dmr/cat.c b/sys/dmr/cat.c new file mode 100644 index 0000000..0866065 --- /dev/null +++ b/sys/dmr/cat.c @@ -0,0 +1,70 @@ +# +/* + */ + +/* + * GP DR11C driver used for C/A/T + */ + +#include "../param.h" +#include "../user.h" +#include "../tty.h" + +#define CATADDR 0167750 +#define PCAT 9 +#define CATHIWAT 60 +#define CATLOWAT 15 + +struct { + int catlock; + struct clist oq; +} cat; + +struct { + int catcsr; + int catbuf; +}; + +ctopen(dev) +{ + if (cat.catlock==0) { + cat.catlock++; + CATADDR->catcsr =| IENABLE; + } else + u.u_error = ENXIO; +} + +ctclose() +{ + cat.catlock = 0; +} + +ctwrite(dev) +{ + register c; + extern lbolt; + + while ((c=cpass()) >= 0) { + spl5(); + while (cat.oq.c_cc > CATHIWAT) + sleep(&cat.oq, PCAT); + while (putc(c, &cat.oq) < 0) + sleep(&lbolt, PCAT); + catintr(); + spl0(); + } +} + +catintr() +{ + register int c; + + if (CATADDR->catcsr&DONE && (c=getc(&cat.oq))>=0) { + CATADDR->catbuf = c; + if (cat.oq.c_cc==0 || cat.oq.c_cc==CATLOWAT) + wakeup(&cat.oq); + } else { + if (cat.catlock==0) + CATADDR->catcsr = 0; + } +} diff --git a/sys/dmr/dc.c b/sys/dmr/dc.c new file mode 100644 index 0000000..c3d132f --- /dev/null +++ b/sys/dmr/dc.c @@ -0,0 +1,231 @@ +# +/* + */ + +/* + * DC-11 driver + */ +#include "../param.h" +#include "../conf.h" +#include "../user.h" +#include "../tty.h" +#include "../proc.h" + +/* + * Base address of DC-11's. Minor device i is at + * DCADDR + 10*i. + */ +#define DCADDR 0174000 + +/* + * Number of DC's for which table space is allocated. + */ +#define NDC11 14 + +/* + * Control bits in device registers + */ +#define CDLEAD 01 +#define CARRIER 04 +#define SPEED1 010 +#define STOP1 0400 +#define RQSEND 01 +#define PARITY 040 +#define ERROR 0100000 +#define CTRANS 040000 +#define RINGIND 020000 + + +struct tty dc11[NDC11]; + +struct dcregs { + int dcrcsr; + int dcrbuf; + int dctcsr; + int dctbuf; +}; + +/* + * Input-side speed and control bit table. + * Each DC11 has 4 speeds which correspond to the 4 non-zero entries. + * The table index is the same as the speed-selector + * number for the DH11. + * Attempts to set the speed to a zero entry are ignored. + */ +int dcrstab[] { + 0, /* 0 baud */ + 0, /* 50 baud */ + 0, /* 75 baud */ + 0, /* 110 baud */ + 01101, /* 134.5 baud: 7b/ch, speed 0 */ + 0111, /* 150 baud: 8b/ch, speed 1 */ + 0, /* 200 baud */ + 0121, /* 300 baud: 8b/ch, speed 2 */ + 0, /* 600 baud */ + 0131, /* 1200 baud */ + 0, /* 1800 baud */ + 0, /* 2400 baud */ + 0, /* 4800 baud */ + 0, /* 9600 baud */ + 0, /* X0 */ + 0, /* X1 */ +}; + +/* + * Transmitter speed table + */ +int dctstab[] { + 0, /* 0 baud */ + 0, /* 50 baud */ + 0, /* 75 baud */ + 0, /* 110 baud */ + 0501, /* 134.5 baud: stop 1 */ + 0511, /* 150 baud */ + 0, /* 200 baud */ + 0521, /* 300 baud */ + 0, /* 600 baud */ + 0531, /* 1200 baud */ + 0, /* 1800 baud */ + 0, /* 2400 baud */ + 0, /* 4800 baud */ + 0, /* 9600 baud */ + 0, /* X0 */ + 0, /* X1 */ +}; + +/* + * Open a DC11, waiting until carrier is established. + * Default initial conditions are set up on the first open. + * t_state's CARR_ON bit is a pure copy of the hardware + * CARRIER bit, and is only used to regularize + * carrier tests in general tty routines. + */ +dcopen(dev, flag) +{ + register struct tty *rtp; + register *addr; + + if (dev.d_minor >= NDC11) { + u.u_error = ENXIO; + return; + } + rtp = &dc11[dev.d_minor]; + rtp->t_addr = addr = DCADDR + dev.d_minor*8; + rtp->t_state =| WOPEN; + addr->dcrcsr =| IENABLE|CDLEAD; + if ((rtp->t_state&ISOPEN) == 0) { + rtp->t_erase = CERASE; + rtp->t_kill = CKILL; + addr->dcrcsr = IENABLE|CDLEAD|SPEED1; + addr->dctcsr = IENABLE|SPEED1|STOP1|RQSEND; + rtp->t_state = ISOPEN | WOPEN; + rtp->t_flags = ODDP|EVENP|ECHO; + } + if (addr->dcrcsr & CARRIER) + rtp->t_state =| CARR_ON; + while ((rtp->t_state & CARR_ON) == 0) + sleep(&rtp->t_rawq, TTIPRI); + rtp->t_state =& ~WOPEN; + if (u.u_procp->p_ttyp == 0) { + u.u_procp->p_ttyp = rtp; + rtp->t_dev = dev; + } +} + +/* + * Close a dc11 + */ +dcclose(dev) +{ + register struct tty *tp; + + (tp = &dc11[dev.d_minor])->t_state = 0; + if (tp->t_flags&HUPCL) + tp->t_addr->dcrcsr =& ~CDLEAD; + wflushtty(tp); +} + +/* + * Read a DC11 + */ +dcread(dev) +{ + ttread(&dc11[dev.d_minor]); +} + +/* + * Write a DC11 + */ +dcwrite(dev) +{ + ttwrite(&dc11[dev.d_minor]); +} + +/* + * DC11 transmitter interrupt. + */ +dcxint(dev) +{ + register struct tty *tp; + + ttstart(tp = &dc11[dev.d_minor]); + if (tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT) + wakeup(&tp->t_outq); +} + +/* + * DC11 receiver interrupt. + */ +dcrint(dev) +{ + register struct tty *tp; + register int c, csr; + + tp = &dc11[dev.d_minor]; + c = tp->t_addr->dcrbuf; + /* + * If carrier is off, and an open is not in progress, + * knock down the CD lead to hang up the local dataset + * and signal a hangup. + */ + if (((csr = tp->t_addr->dcrcsr) & CARRIER) == 0) { + if ((tp->t_state&WOPEN) == 0) { + tp->t_addr->dcrcsr =& ~CDLEAD; + if (tp->t_state & CARR_ON) + signal(tp, SIGHUP); + flushtty(tp); + } + tp->t_state =& ~CARR_ON; + return; + } + if (csr&ERROR || (tp->t_state&ISOPEN)==0) { + if (tp->t_state&WOPEN && csr&CARRIER) + tp->t_state =| CARR_ON; + wakeup(tp); + return; + } + csr =& PARITY; + if (csr&&(tp->t_flags&ODDP) || !csr&&(tp->t_flags&EVENP)) + ttyinput(c, tp); +} + +/* + * DC11 stty/gtty. + * Perform general functions and set speeds. + */ +dcsgtty(dev, av) +int *av; +{ + register struct tty *tp; + register r; + + tp = &dc11[dev.d_minor]; + if (ttystty(tp, av)) + return; + if (r = dcrstab[tp->t_speeds.lobyte&017]) + tp->t_addr->dcrcsr = r; + else + tp->t_addr->dcrcsr =& ~CDLEAD; + if (r = dctstab[tp->t_speeds.hibyte&017]) + tp->t_addr->dctcsr = r; +} diff --git a/sys/dmr/dh.c b/sys/dmr/dh.c new file mode 100644 index 0000000..bf92f3c --- /dev/null +++ b/sys/dmr/dh.c @@ -0,0 +1,300 @@ +# +/* + */ + +/* + * DH-11 driver + * This driver calls on the DHDM driver. + * If the DH has no DM11-BB, then the latter will + * be fake. To insure loading of the correct DM code, + * lib2 should have dhdm.o, dh.o and dhfdm.o in that order. + */ + +#include "../param.h" +#include "../conf.h" +#include "../user.h" +#include "../tty.h" +#include "../proc.h" + +#define DHADDR 0160020 +#define NDH11 16 /* number of lines */ +#define DHNCH 8 /* max number of DMA chars */ + +struct tty dh11[NDH11]; +/* + * Place from which to do DMA on output + */ +char dh_clist[NDH11][DHNCH]; + +/* + * Used to communicate the number of lines to the DM + */ +int ndh11 NDH11; + +/* + * Hardware control bits + */ +#define BITS6 01 +#define BITS7 02 +#define BITS8 03 +#define TWOSB 04 +#define PENABLE 020 +/* DEC manuals incorrectly say this bit causes generation of even parity. */ +#define OPAR 040 +#define HDUPLX 040000 + +#define IENABLE 030100 +#define PERROR 010000 +#define FRERROR 020000 +#define XINT 0100000 +#define SSPEED 7 /* standard speed: 300 baud */ + +/* + * Software copy of last dhbar + */ +int dhsar; + +struct dhregs { + int dhcsr; + int dhnxch; + int dhlpr; + int dhcar; + int dhbcr; + int dhbar; + int dhbreak; + int dhsilo; +}; + +/* + * Open a DH11 line. + */ +dhopen(dev, flag) +{ + register struct tty *tp; + extern dhstart(); + + if (dev.d_minor >= NDH11) { + u.u_error = ENXIO; + return; + } + tp = &dh11[dev.d_minor]; + tp->t_addr = dhstart; + tp->t_dev = dev; + DHADDR->dhcsr =| IENABLE; + tp->t_state =| WOPEN|SSTART; + if ((tp->t_state&ISOPEN) == 0) { + tp->t_erase = CERASE; + tp->t_kill = CKILL; + tp->t_speeds = SSPEED | (SSPEED<<8); + tp->t_flags = ODDP|EVENP|ECHO; + dhparam(tp); + } + dmopen(dev); + tp->t_state =& ~WOPEN; + tp->t_state =| ISOPEN; + if (u.u_procp->p_ttyp == 0) + u.u_procp->p_ttyp = tp; +} + +/* + * Close a DH11 line. + */ +dhclose(dev) +{ + register struct tty *tp; + + tp = &dh11[dev.d_minor]; + dmclose(dev); + tp->t_state =& (CARR_ON|SSTART); + wflushtty(tp); +} + +/* + * Read from a DH11 line. + */ +dhread(dev) +{ + ttread(&dh11[dev.d_minor]); +} + +/* + * write on a DH11 line + */ +dhwrite(dev) +{ + ttwrite(&dh11[dev.d_minor]); +} + +/* + * DH11 receiver interrupt. + */ +dhrint() +{ + register struct tty *tp; + register int c; + + while ((c = DHADDR->dhnxch) < 0) { /* char. present */ + tp = &dh11[(c>>8)&017]; + if (tp >= &dh11[NDH11]) + continue; + if((tp->t_state&ISOPEN)==0 || (c&PERROR)) { + wakeup(tp); + continue; + } + if (c&FRERROR) /* break */ + if (tp->t_flags&RAW) + c = 0; /* null (for getty) */ + else + c = 0177; /* DEL (intr) */ + ttyinput(c, tp); + } +} + +/* + * stty/gtty for DH11 + */ +dhsgtty(dev, av) +int *av; +{ + register struct tty *tp; + register r; + + tp = &dh11[dev.d_minor]; + if (ttystty(tp, av)) + return; + dhparam(tp); +} + +/* + * Set parameters from open or stty into the DH hardware + * registers. + */ +dhparam(atp) +struct tty *atp; +{ + register struct tty *tp; + register int lpr; + + tp = atp; + spl5(); + DHADDR->dhcsr.lobyte = tp->t_dev.d_minor | IENABLE; + /* + * Hang up line? + */ + if (tp->t_speeds.lobyte==0) { + tp->t_flags =| HUPCL; + dmclose(tp->t_dev); + return; + } + lpr = (tp->t_speeds.hibyte<<10) | (tp->t_speeds.lobyte<<6); + if (tp->t_speeds.lobyte == 4) /* 134.5 baud */ + lpr =| BITS6|PENABLE|HDUPLX; else + if (tp->t_flags&EVENP) + if (tp->t_flags&ODDP) + lpr =| BITS8; else + lpr =| BITS7|PENABLE; else + lpr =| BITS7|OPAR|PENABLE; + if (tp->t_speeds.lobyte == 3) /* 110 baud */ + lpr =| TWOSB; + DHADDR->dhlpr = lpr; + spl0(); +} + +/* + * DH11 transmitter interrupt. + * Restart each line which used to be active but has + * terminated transmission since the last interrupt. + */ +dhxint() +{ + register struct tty *tp; + register ttybit, bar; + + bar = dhsar & ~DHADDR->dhbar; + DHADDR->dhcsr =& ~XINT; + ttybit = 1; + for (tp = dh11; bar; tp++) { + if(bar&ttybit) { + dhsar =& ~ttybit; + bar =& ~ttybit; + tp->t_state =& ~BUSY; + dhstart(tp); + } + ttybit =<< 1; + } +} + +/* + * Start (restart) transmission on the given DH11 line. + */ +dhstart(atp) +struct tty *atp; +{ + extern ttrstrt(); + register c, nch; + register struct tty *tp; + int sps; + char *cp; + + sps = PS->integ; + spl5(); + tp = atp; + /* + * If it's currently active, or delaying, + * no need to do anything. + */ + if (tp->t_state&(TIMEOUT|BUSY)) + goto out; + /* + * t_char is a delay indicator which may have been + * left over from the last start. + * Arrange for the delay. + */ + if (c = tp->t_char) { + tp->t_char = 0; + timeout(ttrstrt, tp, (c&0177)+6); + tp->t_state =| TIMEOUT; + goto out; + } + cp = dh_clist[tp->t_dev.d_minor]; + nch = 0; + /* + * Copy DHNCH characters, or up to a delay indicator, + * to the DMA area. + */ + while (nch > -DHNCH && (c = getc(&tp->t_outq))>=0) { + if (c >= 0200) { + tp->t_char = c; + break; + } + *cp++ = c; + nch--; + } + /* + * If the writer was sleeping on output overflow, + * wake him when low tide is reached. + */ + if (tp->t_outq.c_cc<=TTLOWAT && tp->t_state&ASLEEP) { + tp->t_state =& ~ASLEEP; + wakeup(&tp->t_outq); + } + /* + * If any characters were set up, start transmission; + * otherwise, check for possible delay. + */ + if (nch) { + DHADDR->dhcsr.lobyte = tp->t_dev.d_minor | IENABLE; + DHADDR->dhcar = cp+nch; + DHADDR->dhbcr = nch; + c = 1<t_dev.d_minor; + DHADDR->dhbar =| c; + dhsar =| c; + tp->t_state =| BUSY; + } else if (c = tp->t_char) { + tp->t_char = 0; + timeout(ttrstrt, tp, (c&0177)+6); + tp->t_state =| TIMEOUT; + } + out: + PS->integ = sps; +} diff --git a/sys/dmr/dhdm.c b/sys/dmr/dhdm.c new file mode 100644 index 0000000..74c1991 --- /dev/null +++ b/sys/dmr/dhdm.c @@ -0,0 +1,88 @@ +# +/* + */ + +/* + * DM-BB driver + */ +#include "../param.h" +#include "../tty.h" +#include "../conf.h" + +#define DMADDR 0170500 + +struct tty dh11[]; +int ndh11; /* Set by dh.c to number of lines */ + +#define DONE 0200 +#define SCENABL 040 +#define CLSCAN 01000 +#define TURNON 07 /* RQ send, CD lead, line enable */ +#define TURNOFF 1 /* line enable only */ +#define CARRIER 0100 + +struct dmregs { + int dmcsr; + int dmlstat; +}; + +/* + * Turn on the line associated with the (DH) device dev. + */ +dmopen(dev) +{ + register struct tty *tp; + + tp = &dh11[dev.d_minor]; + DMADDR->dmcsr = dev.d_minor; + DMADDR->dmlstat = TURNON; + if (DMADDR->dmlstat&CARRIER) + tp->t_state =| CARR_ON; + DMADDR->dmcsr = IENABLE|SCENABL; + spl5(); + while ((tp->t_state&CARR_ON)==0) + sleep(&tp->t_rawq, TTIPRI); + spl0(); +} + +/* + * If a DH line has the HUPCL mode, + * turn off carrier when it is closed. + */ +dmclose(dev) +{ + register struct tty *tp; + + tp = &dh11[dev.d_minor]; + if (tp->t_flags&HUPCL) { + DMADDR->dmcsr = dev.d_minor; + DMADDR->dmlstat = TURNOFF; + DMADDR->dmcsr = IENABLE|SCENABL; + } +} + +/* + * DM11 interrupt. + * Mainly, deal with carrier transitions. + */ +dmint() +{ + register struct tty *tp; + + if (DMADDR->dmcsr&DONE) { + tp = &dh11[DMADDR->dmcsr&017]; + if (tp < &dh11[ndh11]) { + wakeup(tp); + if ((DMADDR->dmlstat&CARRIER)==0) { + if ((tp->t_state&WOPEN)==0) { + signal(tp, SIGHUP); + DMADDR->dmlstat = 0; + flushtty(tp); + } + tp->t_state =& ~CARR_ON; + } else + tp->t_state =| CARR_ON; + } + DMADDR->dmcsr = IENABLE|SCENABL; + } +} diff --git a/sys/dmr/dhfdm.c b/sys/dmr/dhfdm.c new file mode 100644 index 0000000..1f36243 --- /dev/null +++ b/sys/dmr/dhfdm.c @@ -0,0 +1,23 @@ +# +/* + */ + +/* + * DM-BB fake driver + */ +#include "../tty.h" +#include "../conf.h" + +struct tty dh11[]; + +dmopen(dev) +{ + register struct tty *tp; + + tp = &dh11[dev.d_minor]; + tp->t_state =| CARR_ON; +} + +dmclose(dev) +{ +} diff --git a/sys/dmr/dn.c b/sys/dmr/dn.c new file mode 100644 index 0000000..5ad0d52 --- /dev/null +++ b/sys/dmr/dn.c @@ -0,0 +1,89 @@ +# +/* + */ + +/* + * DN-11 ACU interface + */ + +#include "../param.h" +#include "../conf.h" +#include "../user.h" + +struct dn { + struct { + char dn_stat; + char dn_reg; + } dn11[3]; +} + +#define DNADDR 0175200 + +#define PWI 00200 +#define ACR 00100 +#define DLO 0020 +#define DONE 0200 +#define IENABLE 0100 +#define DSS 040 +#define PND 020 +#define MENABLE 04 +#define DPR 02 +#define CRQ 01 + +#define DNPRI 5 + +dnopen(dev, flag) +{ + register struct dn *dp; + register int rdev; + + rdev = dev.d_minor; + dp = &DNADDR->dn11[rdev]; + if (dp->dn_reg&(PWI|DLO)) + u.u_error = ENXIO; + else { + DNADDR->dn11[0].dn_stat =| MENABLE; + dp->dn_stat = IENABLE|MENABLE|CRQ; + } +} + +dnclose(dev) +{ + DNADDR->dn11[dev.d_minor].dn_stat =& MENABLE; +} + +dnwrite(dev) +{ + register struct dn *dp; + register c; + extern lbolt; + + dp = &DNADDR->dn11[dev.d_minor]; + for(;;) { + while ((dp->dn_stat&DONE)==0) + sleep(DNADDR, DNPRI); + dp->dn_stat =& ~DONE; + contin: + if (dp->dn_reg&(PWI|ACR)) { + u.u_error = EIO; + return; + } + if (dp->dn_stat&DSS) + return; + c = 0; + if (u.u_count==0 || (dp->dn_stat&PND)==0 || (c=cpass())<0) + continue; + if (c=='-') { + sleep(&lbolt, DNPRI); + sleep(&lbolt, DNPRI); + goto contin; + } + dp->dn_reg = c-'0'; + dp->dn_stat =| DPR; + } +} + +dnint(dev) +{ + wakeup(DNADDR); +} diff --git a/sys/dmr/dp.c b/sys/dmr/dp.c new file mode 100644 index 0000000..462bed8 --- /dev/null +++ b/sys/dmr/dp.c @@ -0,0 +1,255 @@ +# +/* + */ + +/* + * DP-11 Synchronous interface driver + * This driver is rather insensitive to the remote + * device it talks to, which is to say most of the protocol + * must be supplied by the calling program. + * Exceptions: parity is even; 7 data bits per character; + * max. of 512 characters per record; 10 second timeout + * on waiting to receive; half-duplex transmission. + */ + +#include "../param.h" +#include "../conf.h" +#include "../user.h" +#include "../buf.h" + +/* control info */ +struct { + char *dp_buf; + char *dp_bufp; + int dp_nxmit; + char dp_state; + char dp_timer; + int dp_proc; +} dp11; + +/* device registers */ +struct { + int dprcsr; + char dprbuf; + char dpsyn0; + int dptcsr; + char dptbuf; + char dpsyn1; +}; + +/* bits */ +#define ODDPAR 010000 +#define IENABLE 0100 +#define HDUPLX 02 + +#define CTRANS 0100000 +#define RORUN 040000 +#define RING 020000 +#define DSRDY 010000 +#define CARRIER 04000 +#define DONE 0200 +#define IENABLE 0100 +#define SIENABL 040 + +#define WRITE 1 +#define READ 0 + +#define DTRDY 01 +#define RCVACT 04000 + +#define DPADDR 0174770 +#define DPPRI 5 +#define SYN 026 /* (receive) sync character */ + +/* + * The open fails unless the device is not open or + * the opening process is the one that has it open already. + */ +dpopen(dev, flag) +{ + int dptimeout(); + + if (dp11.dp_proc!=0 && dp11.dp_proc!=u.u_procp) { + u.u_error = ENXIO; + return; + } + dp11.dp_proc = u.u_procp; + dp11.dp_state = READ; + if (dp11.dp_buf==0) { + dp11.dp_buf = getblk(NODEV); + dp11.dp_bufp = dp11.dp_buf->b_addr; + dp11.dp_timer = HZ; + timeout(dptimeout, 0, HZ); + } + DPADDR->dpsyn0 = SYN; + DPADDR->dprcsr = HDUPLX|IENABLE; + DPADDR->dptcsr = IENABLE|SIENABL|DTRDY; +} + +dpclose() +{ + DPADDR->dprcsr = 0; + DPADDR->dptcsr = 0; + dp11.dp_timer = 0; + dp11.dp_proc = 0; + if (dp11.dp_buf != 0) { + brelse(dp11.dp_buf); + dp11.dp_buf = 0; + } +} + +/* + * Read waits until: + * there is loss of "data set ready", or + * a timeout occurs, or + * a full record has been received. + * The former two result in an error. + */ +dpread() +{ + register char *bp, **epp; + + bp = dp11.dp_buf->b_addr; + epp = &dp11.dp_bufp; + for(;;) { + if(dpwait()) + return; + if (*epp > bp) + break; + spl6(); + if (dp11.dp_timer <= 1) { + spl0(); + return; + } + sleep(&dp11, DPPRI); + spl0(); + } + iomove(dp11.dp_buf, 0, min(u.u_count, *epp-bp), B_READ); +} + +/* + * write checks to make sure that the data set is not reading, + * and that it is ready. Then the record is copied + * and transmission started. + */ +dpwrite() +{ + register char *bp; + + if (u.u_count==0 || dpwait()) + return; + dp11.dp_state = WRITE; + bp = dp11.dp_buf->b_addr; + dp11.dp_bufp = bp; + if (u.u_count>512) + u.u_count = 512; + dp11.dp_nxmit = u.u_count; + iomove(dp11.dp_buf, 0, u.u_count, B_WRITE); + dpstart(); +} + +/* + * If "data set ready" is down return an error; otherwise + * wait until the dataset is in read state with no carrier, + * which means a record has just been received. + */ +dpwait() +{ + for(;;) { + if ((DPADDR->dptcsr&DSRDY)==0 || dp11.dp_buf==0) { + u.u_error = EIO; + return(1); + } + spl6(); + if (dp11.dp_state==READ && (DPADDR->dptcsr&CARRIER)==0) { + spl0(); + return(0); + } + sleep(&dp11, DPPRI); + spl0(); + } +} + +/* + * Start off the next character to be transmitted; + * when the record is done, drop back into read state. + */ +dpstart() +{ + register int c; + extern char partab[]; + + dp11.dp_timer = 10; + if (--dp11.dp_nxmit >= 0) { + c = (*dp11.dp_bufp++) & 0177; + DPADDR->dptbuf = c | ~partab[c]&0200; + } else { + dp11.dp_bufp = dp11.dp_buf->b_addr; + dp11.dp_state = READ; + } +} + +/* + * Count down the DP timer (once per second) + * If it runs out, it presumably means the other station + * won't speak. + */ +dptimeout() +{ + if (dp11.dp_timer==0) + return; + if (--dp11.dp_timer==0) { + dpturnaround(); + dp11.dp_timer = 1; + } + timeout(dptimeout, 0, HZ); +} + +/* + * Receiver interrupt: if reading, stash character + * unless there is an overrun. + */ +dprint() +{ + register int c; + + c = DPADDR->dprbuf & 0177; + if (dp11.dp_state==READ) { + if ((DPADDR->dprcsr&ODDPAR) == 0) + c =| 0200; + if (dp11.dp_bufp < dp11.dp_buf->b_addr+512) + *dp11.dp_bufp++ = c; + } +} + +/* + * Transmitter interrupt: + * Knock down hardware bits. + * If carrier has dropped, the record is done, so turn the line around; + * otherwise start another character. + */ +dpxint() +{ + register int dpstat; + + dpstat = DPADDR->dptcsr; + DPADDR->dptcsr =& ~(CTRANS|RORUN|RING|DONE); + if (dpstat & (CTRANS|RORUN)) + dpturnaround(); + else if (dpstat&DONE && dp11.dp_state==WRITE) + dpstart(); +} + +/* + * Change the state from writing to reading at the end of a record. + */ +dpturnaround() +{ + DPADDR->dprcsr =& ~RCVACT; + if (dp11.dp_state==WRITE) { + dp11.dp_timer = 10; + dp11.dp_state = READ; + dp11.dp_bufp = dp11.dp_buf->b_addr; + } + wakeup(&dp11); +} diff --git a/sys/dmr/hp.c b/sys/dmr/hp.c new file mode 100644 index 0000000..b3ef9ff --- /dev/null +++ b/sys/dmr/hp.c @@ -0,0 +1,218 @@ +# +/* + */ + +/* + * RP04 disk driver + * + * This driver has been tested on a working RP04 for a few hours. + * It does not attempt ECC error correction and is probably + * deficient in general in the case of errors and when packs + * are dismounted. + */ + +#include "../param.h" +#include "../buf.h" +#include "../conf.h" +#include "../user.h" + +struct { + int hpcs1; /* Control and Status register 1 */ + int hpwc; /* Word count register */ + int hpba; /* UNIBUS address register */ + int hpda; /* Desired address register */ + int hpcs2; /* Control and Status register 2*/ + int hpds; /* Drive Status */ + int hper1; /* Error register 1 */ + int hpas; /* Attention Summary */ + int hpla; /* Look ahead */ + int hpdb; /* Data buffer */ + int hpmr; /* Maintenance register */ + int hpdt; /* Drive type */ + int hpsn; /* Serial number */ + int hpof; /* Offset register */ + int hpca; /* Desired Cylinder address register*/ + int hpcc; /* Current Cylinder */ + int hper2; /* Error register 2 */ + int hper3; /* Error register 3 */ + int hppos; /* Burst error bit position */ + int hppat; /* Burst error bit pattern */ + int hpbae; /* 11/70 bus extension */ +}; + +#define HPADDR 0176700 +#define NHP 8 + +struct { + char *nblocks; + int cyloff; +} hp_sizes[] { + 9614, 0, /* cyl 0 thru 23 */ + /* cyl 24 thru 43 available */ + -1, 44, /* cyl 44 thru 200 */ + -1, 201, /* cyl 201 thru 357 */ + 20900, 358, /* cyl 358 thru 407 */ + /* cyl 408 thru 410 blank */ + 40600, 0, + 40600, 100, + 40600, 200, + 40600, 300, +}; + + +struct devtab hptab; +struct buf hpbuf; + +char hp_openf; + + /* Drive Commands */ +#define GO 01 +#define PRESET 020 +#define RECAL 06 +#define RCLR 010 +#define OFFSET 014 + +#define READY 0200 /* hpds - drive ready */ +#define PIP 020000 /* hpds - Positioning Operation in Progress */ +#define ERR 040000 /* hpcs1 - composite error */ + +#define DU 040000 /* hper1 - Drive Unsafe */ +#define DTE 010000 /* hper1 - Drive Timing Error */ +#define OPI 020000 /* hper1 - Operation Incomplete */ + /* Error Correction Code errors */ +#define DCK 0100000 /* hper1 - Data Check error */ +#define ECH 0100 /* hper1 - ECC hard error */ + +#define CLR 040 /* hpcs2 - Controller Clear */ + +#define FMT22 010000 /* hpof - 16 bit /word format */ +/* + * Use av_back to save track+sector, + * b_resid for cylinder. + */ + +#define trksec av_back +#define cylin b_resid + +hpopen() +{ + + if(!hp_openf){ + hp_openf++; + HPADDR->hpcs2 = CLR; + HPADDR->hpcs1 = RCLR|GO; + HPADDR->hpcs1 = PRESET|GO; + HPADDR->hpof = FMT22; + } +} + +hpstrategy(abp) +struct buf *abp; +{ + register struct buf *bp; + register char *p1, *p2; + + bp = abp; + p1 = &hp_sizes[bp->b_dev.d_minor&07]; + if (bp->b_dev.d_minor >= (NHP<<3) || + bp->b_blkno >= p1->nblocks) { + bp->b_flags =| B_ERROR; + iodone(bp); + return; + } + bp->av_forw = 0; + bp->cylin = p1->cyloff; + p1 = bp->b_blkno; + p2 = lrem(p1, 22); + p1 = ldiv(p1, 22); + bp->trksec = (p1%19)<<8 | p2; + bp->cylin =+ p1/19; + spl5(); + if ((p1 = hptab.d_actf)==0) + hptab.d_actf = bp; + else { + for (; p2 = p1->av_forw; p1 = p2) { + if (p1->cylin <= bp->cylin + && bp->cylin < p2->cylin + || p1->cylin >= bp->cylin + && bp->cylin > p2->cylin) + break; + } + bp->av_forw = p2; + p1->av_forw = bp; + } + if (hptab.d_active==0) + hpstart(); + spl0(); +} + +hpstart() +{ + register struct buf *bp; + + if ((bp = hptab.d_actf) == 0) + return; + hptab.d_active++; + HPADDR->hpcs2 = bp->b_dev.d_minor >> 3; + HPADDR->hpca = bp->cylin; + rhstart(bp, &HPADDR->hpda, bp->trksec, &HPADDR->hpbae); +} + +hpintr() +{ + register struct buf *bp; + register int ctr; + + if (hptab.d_active == 0) + return; + bp = hptab.d_actf; + hptab.d_active = 0; + if (HPADDR->hpcs1 & ERR) { /* error bit */ + deverror(bp, HPADDR->hpcs2, 0); + if(HPADDR->hper1 & (DU|DTE|OPI)) { + HPADDR->hpcs2 = CLR; + HPADDR->hpcs1 = RECAL|GO; + ctr = 0; + while ((HPADDR->hpds&PIP) && --ctr); + } + HPADDR->hpcs1 = RCLR|GO; + if (++hptab.d_errcnt <= 10) { + hpstart(); + return; + } + bp->b_flags =| B_ERROR; + } + hptab.d_errcnt = 0; + hptab.d_actf = bp->av_forw; + bp->b_resid = HPADDR->hpwc; + iodone(bp); + hpstart(); +} + +hpread(dev) +{ + + if(hpphys(dev)) + physio(hpstrategy, &hpbuf, dev, B_READ); +} + +hpwrite(dev) +{ + + if(hpphys(dev)) + physio(hpstrategy, &hpbuf, dev, B_WRITE); +} + +hpphys(dev) +{ + register c; + + c = lshift(u.u_offset, -9); + c =+ ldiv(u.u_count+511, 512); + if(c > hp_sizes[dev.d_minor & 07].nblocks) { + u.u_error = ENXIO; + return(0); + } + return(1); +} + diff --git a/sys/dmr/hs.c b/sys/dmr/hs.c new file mode 100644 index 0000000..edf5206 --- /dev/null +++ b/sys/dmr/hs.c @@ -0,0 +1,116 @@ +# +/* + */ + +/* + * RS03/04 disk driver + */ + +#include "../param.h" +#include "../buf.h" +#include "../conf.h" +#include "../user.h" + + +struct { + int hscs1; /* Control and Status register 1 */ + int hswc; /* Word count register */ + int hsba; /* UNIBUS address register */ + int hsda; /* Desired address register */ + int hscs2; /* Control and Status register 2 */ + int hsds; /* Drive Status */ + int hser; /* Error register */ + int hsas; /* not used */ + int hsla; /* not used */ + int hsdb; /* not used */ + int hsmr; /* not used */ + int hsdt; /* not used */ + int hsbae; /* 11/70 bus extension */ +}; + +struct devtab hstab; +struct buf rhsbuf; + +#define HSADDR 0172040 + +#define ERR 040000 /* hscs1 - composite error */ + +#define GO 01 +#define RCLR 010 +#define DRY 0200 /* hsds - Drive Ready */ + +hsstrategy(abp) +struct buf *abp; +{ + register struct buf *bp; + register mblks; + + bp = abp; + mblks = 1024; /* RJS03 */ + if(bp->b_dev.d_minor >= 8) + mblks = 2048; /* RJS04 */ + if(bp->b_blkno >= mblks) { + bp->b_flags =| B_ERROR; + iodone(bp); + return; + } + bp->av_forw = 0; + spl5(); + if (hstab.d_actf==0) + hstab.d_actf = bp; else + hstab.d_actl->av_forw = bp; + hstab.d_actl = bp; + if (hstab.d_active==0) + hsstart(); + spl0(); +} + +hsstart() +{ + register struct buf *bp; + register addr; + + if ((bp = hstab.d_actf) == 0) + return; + hstab.d_active++; + addr = bp->b_blkno; + if(bp->b_dev.d_minor < 8) + addr =<< 1; /* RJS03 */ + HSADDR->hscs2 = bp->b_dev.d_minor & 07; + rhstart(bp, &HSADDR->hsda, addr<<1, &HSADDR->hsbae); +} + +hsintr() +{ + register struct buf *bp; + + if (hstab.d_active == 0) + return; + bp = hstab.d_actf; + hstab.d_active = 0; + if(HSADDR->hscs1 & ERR){ /* error bit */ + deverror(bp, HSADDR->hscs2, 0); + HSADDR->hscs1 = RCLR|GO; + if (++hstab.d_errcnt <= 10) { + hsstart(); + return; + } + bp->b_flags =| B_ERROR; + } + hstab.d_errcnt = 0; + hstab.d_actf = bp->av_forw; + iodone(bp); + hsstart(); +} + +hsread(dev) +{ + + physio(hsstrategy, &rhsbuf, dev, B_READ); +} + +hswrite(dev) +{ + + physio(hsstrategy, &rhsbuf, dev, B_WRITE); +} diff --git a/sys/dmr/ht.c b/sys/dmr/ht.c new file mode 100644 index 0000000..92440c2 --- /dev/null +++ b/sys/dmr/ht.c @@ -0,0 +1,248 @@ +# +/* + */ + +/* + * TJU16 tape driver + */ + +#include "../param.h" +#include "../buf.h" +#include "../conf.h" +#include "../user.h" + +struct { + int htcs1; + int htwc; + int htba; + int htfc; + int htcs2; + int htds; + int hter; + int htas; + int htck; + int htdb; + int htmr; + int htdt; + int htsn; + int httc; + int htbae; /* 11/70 bus extension */ +}; + +struct devtab httab; +struct buf rhtbuf; + +#define NUNIT 8 + +char h_openf[NUNIT]; +char *h_blkno[NUNIT]; +char *h_nxrec[NUNIT]; + +#define HTADDR 0172440 + +#define GO 01 +#define NOP 0 +#define WEOF 026 +#define SFORW 030 +#define SREV 032 +#define ERASE 024 +#define REW 06 +#define CLR 010 +#define P800 01300 /* 800 + pdp11 mode */ +#define P1600 02300 /* 1600 + pdp11 mode */ +#define IENABLE 0100 +#define CRDY 0200 +#define EOF 04 +#define DRY 0200 +#define MOL 010000 +#define PIP 020000 +#define ERR 040000 + +#define SSEEK 1 +#define SIO 2 + +htopen(dev, flag) +{ + register unit; + + unit = dev.d_minor&077; + if (unit >= NUNIT || h_openf[unit]) + u.u_error = ENXIO; + else { + h_openf[unit]++; + h_blkno[unit] = 0; + h_nxrec[unit] = 65535; + hcommand(dev, NOP); + } +} + +htclose(dev, flag) +{ + register int unit; + + unit = dev.d_minor&077; + h_openf[unit] = 0; + if (flag) { + hcommand(dev, WEOF); + hcommand(dev, WEOF); + } + hcommand(dev, REW); +} + +hcommand(dev, com) +{ + register unit; + extern lbolt; + + unit = dev.d_minor; + while (httab.d_active || (HTADDR->htcs1 & CRDY)==0) + sleep(&lbolt, 1); + HTADDR->htcs2 = (unit>>3)&07; + while((HTADDR->htds&DRY) == 0) + sleep(&lbolt, 1); + if(unit >= 64) + HTADDR->httc = P800 | (unit&07); else + HTADDR->httc = P1600 | (unit&07); + while((HTADDR->htds&(MOL|PIP)) != MOL) + sleep(&lbolt, 1); + HTADDR->htcs1 = com | GO; +} + +htstrategy(abp) +struct buf *abp; +{ + register struct buf *bp; + register char **p; + + bp = abp; + p = &h_nxrec[bp->b_dev.d_minor&077]; + if (*p <= bp->b_blkno) { + if (*p < bp->b_blkno) { + bp->b_flags =| B_ERROR; + iodone(bp); + return; + } + if (bp->b_flags&B_READ) { + clrbuf(bp); + iodone(bp); + return; + } + } + if ((bp->b_flags&B_READ)==0) + *p = bp->b_blkno + 1; + bp->av_forw = 0; + spl5(); + if (httab.d_actf==0) + httab.d_actf = bp; + else + httab.d_actl->av_forw = bp; + httab.d_actl = bp; + if (httab.d_active==0) + htstart(); + spl0(); +} + +htstart() +{ + register struct buf *bp; + register int unit; + register char *blkno; + + loop: + if ((bp = httab.d_actf) == 0) + return; + unit = bp->b_dev.d_minor; + HTADDR->htcs2 = (unit>>3)&07; + if(unit >= 64) + HTADDR->httc = P800 | (unit&07); else + HTADDR->httc = P1600 | (unit&07); + unit =& 077; + blkno = h_blkno[unit]; + if (h_openf[unit] < 0 || (HTADDR->htcs1 & CRDY)==0) { + bp->b_flags =| B_ERROR; + httab.d_actf = bp->av_forw; + iodone(bp); + goto loop; + } + if (blkno != bp->b_blkno) { + httab.d_active = SSEEK; + if (blkno < bp->b_blkno) { + HTADDR->htfc = blkno - bp->b_blkno; + HTADDR->htcs1 = SFORW|IENABLE|GO; + } else { + if (bp->b_blkno == 0) + HTADDR->htcs1 = REW|IENABLE|GO; + else { + HTADDR->htfc = bp->b_blkno - blkno; + HTADDR->htcs1 = SREV|IENABLE|GO; + } + } + return; + } + httab.d_active = SIO; + rhstart(bp, &HTADDR->htfc, bp->b_wcount<<1, &HTADDR->htbae); +} + +htintr() +{ + register struct buf *bp; + register int unit; + + if ((bp = httab.d_actf)==0) + return; + unit = bp->b_dev.d_minor&077; + if (HTADDR->htcs1 & ERR) { +/* + deverror(bp, HTADDR->hter, 0); + */ + if(HTADDR->htds&EOF) { + if(bp != &rhtbuf && h_openf[unit]) + h_openf[unit] = -1; + } + HTADDR->htcs1 = ERR|CLR|GO; + if ((HTADDR->htds&DRY)!=0 && httab.d_active==SIO) { + if (++httab.d_errcnt < 10) { + h_blkno[unit]++; + httab.d_active = 0; + htstart(); + return; + } + } + bp->b_flags =| B_ERROR; + httab.d_active = SIO; + } + if (httab.d_active == SIO) { + httab.d_errcnt = 0; + h_blkno[unit]++; + httab.d_actf = bp->av_forw; + httab.d_active = 0; + iodone(bp); + bp->b_resid = HTADDR->htfc; + } else + h_blkno[unit] = bp->b_blkno; + htstart(); +} + +htread(dev) +{ + htphys(dev); + physio(htstrategy, &rhtbuf, dev, B_READ); + u.u_count = -rhtbuf.b_resid; +} + +htwrite(dev) +{ + htphys(dev); + physio(htstrategy, &rhtbuf, dev, B_WRITE); + u.u_count = 0; +} + +htphys(dev) +{ + register unit, a; + + unit = dev.d_minor; + a = lshift(u.u_offset, -9); + h_blkno[unit] = a; + h_nxrec[unit] = ++a; +} diff --git a/sys/dmr/kl.c b/sys/dmr/kl.c new file mode 100644 index 0000000..c6079d5 --- /dev/null +++ b/sys/dmr/kl.c @@ -0,0 +1,117 @@ +# +/* + */ + +/* + * KL/DL-11 driver + */ +#include "../param.h" +#include "../conf.h" +#include "../user.h" +#include "../tty.h" +#include "../proc.h" + +/* base address */ +#define KLADDR 0177560 /* console */ +#define KLBASE 0176500 /* kl and dl11-a */ +#define DLBASE 0175610 /* dl-e */ +#define NKL11 1 +#define NDL11 0 +#define DSRDY 02 +#define RDRENB 01 + +struct tty kl11[NKL11+NDL11]; + +struct klregs { + int klrcsr; + int klrbuf; + int kltcsr; + int kltbuf; +} + +klopen(dev, flag) +{ + register char *addr; + register struct tty *tp; + + if(dev.d_minor >= NKL11+NDL11) { + u.u_error = ENXIO; + return; + } + tp = &kl11[dev.d_minor]; + if (u.u_procp->p_ttyp == 0) { + u.u_procp->p_ttyp = tp; + tp->t_dev = dev; + } + /* + * set up minor 0 to address KLADDR + * set up minor 1 thru NKL11-1 to address from KLBASE + * set up minor NKL11 on to address from DLBASE + */ + addr = KLADDR + 8*dev.d_minor; + if(dev.d_minor) + addr =+ KLBASE-KLADDR-8; + if(dev.d_minor >= NKL11) + addr =+ DLBASE-KLBASE-8*NKL11+8; + tp->t_addr = addr; + if ((tp->t_state&ISOPEN) == 0) { + tp->t_state = ISOPEN|CARR_ON; + tp->t_flags = XTABS|LCASE|ECHO|CRMOD; + tp->t_erase = CERASE; + tp->t_kill = CKILL; + } + addr->klrcsr =| IENABLE|DSRDY|RDRENB; + addr->kltcsr =| IENABLE; +} + +klclose(dev) +{ + register struct tty *tp; + + tp = &kl11[dev.d_minor]; + wflushtty(tp); + tp->t_state = 0; +} + +klread(dev) +{ + ttread(&kl11[dev.d_minor]); +} + +klwrite(dev) +{ + ttwrite(&kl11[dev.d_minor]); +} + +klxint(dev) +{ + register struct tty *tp; + + tp = &kl11[dev.d_minor]; + ttstart(tp); + if (tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT) + wakeup(&tp->t_outq); +} + +klrint(dev) +{ + register int c, *addr; + register struct tty *tp; + + tp = &kl11[dev.d_minor]; + addr = tp->t_addr; + c = addr->klrbuf; + addr->klrcsr =| RDRENB; + if ((c&0177)==0) + addr->kltbuf = c; /* hardware botch */ + ttyinput(c, tp); +} + +klsgtty(dev, v) +int *v; +{ + register struct tty *tp; + + tp = &kl11[dev.d_minor]; + ttystty(tp, v); +} diff --git a/sys/dmr/lp.c b/sys/dmr/lp.c new file mode 100644 index 0000000..190b2f0 --- /dev/null +++ b/sys/dmr/lp.c @@ -0,0 +1,184 @@ +# +/* + */ + +/* + * LP-11 Line printer driver + */ + +#include "../param.h" +#include "../conf.h" +#include "../user.h" + +#define LPADDR 0177514 + +#define IENABLE 0100 +#define DONE 0200 + +#define LPPRI 10 +#define LPLWAT 50 +#define LPHWAT 100 +#define EJLINE 60 +#define MAXCOL 80 + +struct { + int lpsr; + int lpbuf; +}; + +struct { + int cc; + int cf; + int cl; + int flag; + int mcc; + int ccc; + int mlc; +} lp11; + +#define CAP 01 /* Set to 0 for 96-char printer, else to 01 */ +#define EJECT 02 +#define OPEN 04 +#define IND 010 /* Set to 0 for no indent, else to 010 */ + +#define FORM 014 + +lpopen(dev, flag) +{ + + if(lp11.flag & OPEN || LPADDR->lpsr < 0) { + u.u_error = EIO; + return; + } + lp11.flag =| (IND|EJECT|OPEN); + LPADDR->lpsr =| IENABLE; + lpcanon(FORM); +} + +lpclose(dev, flag) +{ + lpcanon(FORM); + lp11.flag = 0; +} + +lpwrite() +{ + register int c; + + while ((c=cpass())>=0) + lpcanon(c); +} + +lpcanon(c) +{ + register c1, c2; + + c1 = c; + if(lp11.flag&CAP) { + if(c1>='a' && c1<='z') + c1 =+ 'A'-'a'; else + switch(c1) { + + case '{': + c2 = '('; + goto esc; + + case '}': + c2 = ')'; + goto esc; + + case '`': + c2 = '\''; + goto esc; + + case '|': + c2 = '!'; + goto esc; + + case '~': + c2 = '^'; + + esc: + lpcanon(c2); + lp11.ccc--; + c1 = '-'; + } + } + + switch(c1) { + + case '\t': + lp11.ccc = (lp11.ccc+8) & ~7; + return; + + case FORM: + case '\n': + if((lp11.flag&EJECT) == 0 || + lp11.mcc!=0 || lp11.mlc!=0) { + lp11.mcc = 0; + lp11.mlc++; + if(lp11.mlc >= EJLINE && lp11.flag&EJECT) + c1 = FORM; + lpoutput(c1); + if(c1 == FORM) + lp11.mlc = 0; + } + + case '\r': + lp11.ccc = 0; + if(lp11.flag&IND) + lp11.ccc = 8; + return; + + case 010: + if(lp11.ccc > 0) + lp11.ccc--; + return; + + case ' ': + lp11.ccc++; + return; + + default: + if(lp11.ccc < lp11.mcc) { + lpoutput('\r'); + lp11.mcc = 0; + } + if(lp11.ccc < MAXCOL) { + while(lp11.ccc > lp11.mcc) { + lpoutput(' '); + lp11.mcc++; + } + lpoutput(c1); + lp11.mcc++; + } + lp11.ccc++; + } +} + +lpstart() +{ + register int c; + + while (LPADDR->lpsr&DONE && (c = getc(&lp11)) >= 0) + LPADDR->lpbuf = c; +} + +lpint() +{ + register int c; + + lpstart(); + if (lp11.cc == LPLWAT || lp11.cc == 0) + wakeup(&lp11); +} + +lpoutput(c) +{ + if (lp11.cc >= LPHWAT) + sleep(&lp11, LPPRI); + putc(c, &lp11); + spl4(); + lpstart(); + spl0(); +} diff --git a/sys/dmr/mem.c b/sys/dmr/mem.c new file mode 100644 index 0000000..55f3fb3 --- /dev/null +++ b/sys/dmr/mem.c @@ -0,0 +1,70 @@ +# +/* + */ + +/* + * Memory special file + * minor device 0 is physical memory + * minor device 1 is kernel memory + * minor device 2 is EOF/RATHOLE + */ + +#include "../param.h" +#include "../user.h" +#include "../conf.h" +#include "../seg.h" + +mmread(dev) +{ + register c, bn, on; + int a, d; + + if(dev.d_minor == 2) + return; + do { + bn = lshift(u.u_offset, -6); + on = u.u_offset[1] & 077; + a = UISA->r[0]; + d = UISD->r[0]; + spl7(); + UISA->r[0] = bn; + UISD->r[0] = 077406; + if(dev.d_minor == 1) + UISA->r[0] = (ka6-6)->r[(bn>>7)&07] + (bn & 0177); + c = fuibyte(on); + UISA->r[0] = a; + UISD->r[0] = d; + spl0(); + } while(u.u_error==0 && passc(c)>=0); +} + +mmwrite(dev) +{ + register c, bn, on; + int a, d; + + if(dev.d_minor == 2) { + c = u.u_count; + u.u_count = 0; + u.u_base =+ c; + dpadd(u.u_offset, c); + return; + } + for(;;) { + bn = lshift(u.u_offset, -6); + on = u.u_offset[1] & 077; + if ((c=cpass())<0 || u.u_error!=0) + break; + a = UISA->r[0]; + d = UISD->r[0]; + spl7(); + UISA->r[0] = bn; + UISD->r[0] = 077406; + if(dev.d_minor == 1) + UISA->r[0] = (ka6-6)->r[(bn>>7)&07] + (bn & 0177); + suibyte(on, c); + UISA->r[0] = a; + UISD->r[0] = d; + spl0(); + } +} diff --git a/sys/dmr/partab.c b/sys/dmr/partab.c new file mode 100644 index 0000000..4bff819 --- /dev/null +++ b/sys/dmr/partab.c @@ -0,0 +1,21 @@ +/* + */ + +char partab[] { + 0001,0201,0201,0001,0201,0001,0001,0201, + 0202,0004,0003,0205,0005,0206,0201,0001, + 0201,0001,0001,0201,0001,0201,0201,0001, + 0001,0201,0201,0001,0201,0001,0001,0201, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0000,0200,0200,0000,0200,0000,0000,0200, + 0000,0200,0200,0000,0200,0000,0000,0200, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0000,0200,0200,0000,0200,0000,0000,0200, + 0000,0200,0200,0000,0200,0000,0000,0200, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0000,0200,0200,0000,0200,0000,0000,0200, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0000,0200,0200,0000,0200,0000,0000,0201 +}; diff --git a/sys/dmr/pc.c b/sys/dmr/pc.c new file mode 100644 index 0000000..f966249 --- /dev/null +++ b/sys/dmr/pc.c @@ -0,0 +1,166 @@ +# +/* + */ + +/* + * PC-11 Paper tape reader/punch driver + */ + +#include "../param.h" +#include "../conf.h" +#include "../user.h" + +#define PCADDR 0177550 + +#define CLOSED 0 +#define WAITING 1 +#define READING 2 +#define EOF 3 + +#define RDRENB 01 +#define IENABLE 0100 +#define DONE 0200 +#define BUSY 04000 +#define ERROR 0100000 + +#define PCIPRI 30 +#define PCOPRI 40 +#define PCOLWAT 50 +#define PCOHWAT 100 +#define PCIHWAT 250 + +struct { + int pcrcsr; + int pcrbuf; + int pcpcsr; + int pcpbuf; +}; + +struct clist { + int cc; + int cf; + int cl; +}; + +struct pc11 { + int pcstate; + struct clist pcin; + struct clist pcout; +} pc11; + +pcopen(dev, flag) +{ + extern lbolt; + + if (flag==0) { + if (pc11.pcstate!=CLOSED) { + u.u_error = ENXIO; + return; + } + pc11.pcstate = WAITING; + while(pc11.pcstate==WAITING) { + PCADDR->pcrcsr = IENABLE|RDRENB; + sleep(&lbolt, PCIPRI); + } + } else { + PCADDR->pcpcsr =| IENABLE; + pcleader(); + } +} + +pcclose(dev, flag) +{ + if (flag==0) { + spl4(); + while (getc(&pc11.pcin) >= 0); + PCADDR->pcrcsr = 0; + pc11.pcstate = CLOSED; + spl0(); + } else + pcleader(); +} + +pcread() +{ + register int c; + + spl4(); + do { + while ((c = getc(&pc11.pcin)) < 0) { + if (pc11.pcstate==EOF) + goto out; + if ((PCADDR->pcrcsr&(ERROR|BUSY|DONE))==0) + PCADDR->pcrcsr =| IENABLE|RDRENB; + sleep(&pc11.pcin, PCIPRI); + } + } while (passc(c)>=0); +out: + spl0(); +} + +pcwrite() +{ + register int c; + + while ((c=cpass())>=0) + pcoutput(c); +} + +pcstart() +{ + register int c; + + if (PCADDR->pcpcsr&DONE && (c = getc(&pc11.pcout)) >= 0) + PCADDR->pcpbuf = c; +} + +pcrint() +{ + if (pc11.pcstate==WAITING) { + if (PCADDR->pcrcsr&ERROR) + return; + pc11.pcstate = READING; + } + if (pc11.pcstate==READING) { + if (PCADDR->pcrcsr&ERROR) + pc11.pcstate = EOF; + else { + putc(PCADDR->pcrbuf, &pc11.pcin); + if (pc11.pcin.cc < PCIHWAT) + PCADDR->pcrcsr =| IENABLE|RDRENB; + } + wakeup(&pc11.pcin); + } +} + +pcpint() +{ + + pcstart(); + if (pc11.pcout.cc <= PCOLWAT) + wakeup(&pc11.pcout); +} + +pcoutput(c) +{ + if (PCADDR->pcpcsr&ERROR) { + u.u_error = EIO; + return; + } + if (pc11.pcout.cc >= PCOHWAT) + sleep(&pc11.pcout, PCOPRI); + putc(c, &pc11.pcout); + spl4(); + pcstart(); + spl0(); +} + +pcleader() +{ + register int i; + + i = 100; + do + pcoutput(0); + while (--i); +} diff --git a/sys/dmr/rf.c b/sys/dmr/rf.c new file mode 100644 index 0000000..e47d5a4 --- /dev/null +++ b/sys/dmr/rf.c @@ -0,0 +1,103 @@ +# +/* + */ + +/* + * RF disk driver + */ + +#include "../param.h" +#include "../buf.h" +#include "../conf.h" +#include "../user.h" + +struct { + int rfcs; + int rfwc; + int rfba; + int rfda; + int rfdae; +}; + +struct devtab rftab; +struct buf rrfbuf; + +#define NRFBLK 1024 +#define RFADDR 0177460 + +#define GO 01 +#define RCOM 02 +#define WCOM 04 +#define CTLCLR 0400 +#define IENABLE 0100 + +rfstrategy(abp) +struct buf *abp; +{ + register struct buf *bp; + + bp = abp; + if(bp->b_flags&B_PHYS) + mapalloc(bp); + if (bp->b_blkno >= NRFBLK*(bp->b_dev.d_minor+1)) { + bp->b_flags =| B_ERROR; + iodone(bp); + return; + } + bp->av_forw = 0; + spl5(); + if (rftab.d_actf==0) + rftab.d_actf = bp; + else + rftab.d_actl->av_forw = bp; + rftab.d_actl = bp; + if (rftab.d_active==0) + rfstart(); + spl0(); +} + +rfstart() +{ + register struct buf *bp; + + if ((bp = rftab.d_actf) == 0) + return; + rftab.d_active++; + RFADDR->rfdae = bp->b_blkno.hibyte; + devstart(bp, &RFADDR->rfda, bp->b_blkno<<8, 0); +} + +rfintr() +{ + register struct buf *bp; + + if (rftab.d_active == 0) + return; + bp = rftab.d_actf; + rftab.d_active = 0; + if (RFADDR->rfcs < 0) { /* error bit */ + deverror(bp, RFADDR->rfcs, RFADDR->rfdae); + RFADDR->rfcs = CTLCLR; + if (++rftab.d_errcnt <= 10) { + rfstart(); + return; + } + bp->b_flags =| B_ERROR; + } + rftab.d_errcnt = 0; + rftab.d_actf = bp->av_forw; + iodone(bp); + rfstart(); +} + +rfread(dev) +{ + + physio(rfstrategy, &rrfbuf, dev, B_READ); +} + +rfwrite(dev) +{ + + physio(rfstrategy, &rrfbuf, dev, B_WRITE); +} diff --git a/sys/dmr/rk.c b/sys/dmr/rk.c new file mode 100644 index 0000000..afce316 --- /dev/null +++ b/sys/dmr/rk.c @@ -0,0 +1,132 @@ +# +/* + */ + +/* + * RK disk driver + */ + +#include "../param.h" +#include "../buf.h" +#include "../conf.h" +#include "../user.h" + +#define RKADDR 0177400 +#define NRK 4 +#define NRKBLK 4872 + +#define RESET 0 +#define GO 01 +#define DRESET 014 +#define IENABLE 0100 +#define DRY 0200 +#define ARDY 0100 +#define WLO 020000 +#define CTLRDY 0200 + +struct { + int rkds; + int rker; + int rkcs; + int rkwc; + int rkba; + int rkda; +}; + +struct devtab rktab; +struct buf rrkbuf; + +rkstrategy(abp) +struct buf *abp; +{ + register struct buf *bp; + register *qc, *ql; + int d; + + bp = abp; + if(bp->b_flags&B_PHYS) + mapalloc(bp); + d = bp->b_dev.d_minor-7; + if(d <= 0) + d = 1; + if (bp->b_blkno >= NRKBLK*d) { + bp->b_flags =| B_ERROR; + iodone(bp); + return; + } + bp->av_forw = 0; + spl5(); + if (rktab.d_actf==0) + rktab.d_actf = bp; + else + rktab.d_actl->av_forw = bp; + rktab.d_actl = bp; + if (rktab.d_active==0) + rkstart(); + spl0(); +} + +rkaddr(bp) +struct buf *bp; +{ + register struct buf *p; + register int b; + int d, m; + + p = bp; + b = p->b_blkno; + m = p->b_dev.d_minor - 7; + if(m <= 0) + d = p->b_dev.d_minor; + else { + d = lrem(b, m); + b = ldiv(b, m); + } + return(d<<13 | (b/12)<<4 | b%12); +} + +rkstart() +{ + register struct buf *bp; + + if ((bp = rktab.d_actf) == 0) + return; + rktab.d_active++; + devstart(bp, &RKADDR->rkda, rkaddr(bp), 0); +} + +rkintr() +{ + register struct buf *bp; + + if (rktab.d_active == 0) + return; + bp = rktab.d_actf; + rktab.d_active = 0; + if (RKADDR->rkcs < 0) { /* error bit */ + deverror(bp, RKADDR->rker, RKADDR->rkds); + RKADDR->rkcs = RESET|GO; + while((RKADDR->rkcs&CTLRDY) == 0) ; + if (++rktab.d_errcnt <= 10) { + rkstart(); + return; + } + bp->b_flags =| B_ERROR; + } + rktab.d_errcnt = 0; + rktab.d_actf = bp->av_forw; + iodone(bp); + rkstart(); +} + +rkread(dev) +{ + + physio(rkstrategy, &rrkbuf, dev, B_READ); +} + +rkwrite(dev) +{ + + physio(rkstrategy, &rrkbuf, dev, B_WRITE); +} diff --git a/sys/dmr/rp.c b/sys/dmr/rp.c new file mode 100644 index 0000000..973a92f --- /dev/null +++ b/sys/dmr/rp.c @@ -0,0 +1,174 @@ +# +/* + */ + +/* + * RP disk driver + */ + +#include "../param.h" +#include "../buf.h" +#include "../conf.h" +#include "../user.h" + +struct { + int rpds; + int rper; + int rpcs; + int rpwc; + int rpba; + int rpca; + int rpda; +}; + +#define RPADDR 0176710 +#define NRP 8 + +struct { + char *nblocks; + int cyloff; +} rp_sizes[] { + 40600, 0, /* cyl 0 thru 202 */ + 40600, 203, /* cyl 203 thru 405 */ + 9200, 0, /* cyl 0 thru 45 */ + 9200, 360, /* cyl 360 thru 405 */ + -1, 0, /* cyl 0 thru 327 */ + -1, 78, /* cyl 78 thru 405 */ + 15600, 0, /* cyl 0 thru 77 */ + 15600, 328, /* cyl 328 thru 405 */ +}; + +struct devtab rptab; +struct buf rrpbuf; + +#define GO 01 +#define RESET 0 +#define HSEEK 014 + +#define IENABLE 0100 +#define READY 0200 + +#define SUFU 01000 +#define SUSU 02000 +#define SUSI 04000 +#define HNF 010000 + +/* + * Use av_back to save track+sector, + * b_resid for cylinder. + */ + +#define trksec av_back +#define cylin b_resid + +rpstrategy(abp) +struct buf *abp; +{ + register struct buf *bp; + register char *p1, *p2; + + bp = abp; + if(bp->b_flags&B_PHYS) + mapalloc(bp); + p1 = &rp_sizes[bp->b_dev.d_minor&07]; + if (bp->b_dev.d_minor >= (NRP<<3) || + bp->b_blkno >= p1->nblocks) { + bp->b_flags =| B_ERROR; + iodone(bp); + return; + } + bp->av_forw = 0; + bp->cylin = p1->cyloff; + p1 = bp->b_blkno; + p2 = lrem(p1, 10); + p1 = ldiv(p1, 10); + bp->trksec = (p1%20)<<8 | p2; + bp->cylin =+ p1/20; + spl5(); + if ((p1 = rptab.d_actf)==0) + rptab.d_actf = bp; + else { + for (; p2 = p1->av_forw; p1 = p2) { + if (p1->cylin <= bp->cylin + && bp->cylin < p2->cylin + || p1->cylin >= bp->cylin + && bp->cylin > p2->cylin) + break; + } + bp->av_forw = p2; + p1->av_forw = bp; + } + if (rptab.d_active==0) + rpstart(); + spl0(); +} + +rpstart() +{ + register struct buf *bp; + + if ((bp = rptab.d_actf) == 0) + return; + rptab.d_active++; + RPADDR->rpda = bp->trksec; + devstart(bp, &RPADDR->rpca, bp->cylin, bp->b_dev.d_minor>>3); +} + +rpintr() +{ + register struct buf *bp; + register int ctr; + + if (rptab.d_active == 0) + return; + bp = rptab.d_actf; + rptab.d_active = 0; + if (RPADDR->rpcs < 0) { /* error bit */ + deverror(bp, RPADDR->rper, RPADDR->rpds); + if(RPADDR->rpds & (SUFU|SUSI|HNF)) { + RPADDR->rpcs.lobyte = HSEEK|GO; + ctr = 0; + while ((RPADDR->rpds&SUSU) && --ctr); + } + RPADDR->rpcs = RESET|GO; + ctr = 0; + while ((RPADDR->rpcs&READY) == 0 && --ctr); + if (++rptab.d_errcnt <= 10) { + rpstart(); + return; + } + bp->b_flags =| B_ERROR; + } + rptab.d_errcnt = 0; + rptab.d_actf = bp->av_forw; + bp->b_resid = RPADDR->rpwc; + iodone(bp); + rpstart(); +} + +rpread(dev) +{ + + if(rpphys(dev)) + physio(rpstrategy, &rrpbuf, dev, B_READ); +} + +rpwrite(dev) +{ + + if(rpphys(dev)) + physio(rpstrategy, &rrpbuf, dev, B_WRITE); +} + +rpphys(dev) +{ + register c; + + c = lshift(u.u_offset, -9); + c =+ ldiv(u.u_count+511, 512); + if(c > rp_sizes[dev.d_minor & 07].nblocks) { + u.u_error = ENXIO; + return(0); + } + return(1); +} diff --git a/sys/dmr/sys.c b/sys/dmr/sys.c new file mode 100644 index 0000000..09538b7 --- /dev/null +++ b/sys/dmr/sys.c @@ -0,0 +1,54 @@ +# +/* + */ + +/* + * indirect driver for controlling tty. + */ +#include "../param.h" +#include "../conf.h" +#include "../user.h" +#include "../tty.h" +#include "../proc.h" + +syopen(dev, flag) +{ + register *tp; + + if(tp = syttyp()) + (*cdevsw[tp->t_dev.d_major].d_open)(tp->t_dev, flag); +} + +syread(dev) +{ + register *tp; + + if(tp = syttyp()) + (*cdevsw[tp->t_dev.d_major].d_read)(tp->t_dev); +} + +sywrite(dev) +{ + register *tp; + + if(tp = syttyp()) + (*cdevsw[tp->t_dev.d_major].d_write)(tp->t_dev); +} + +sysgtty(dev, flag) +{ + register *tp; + + if(tp = syttyp()) + (*cdevsw[tp->t_dev.d_major].d_sgtty)(tp->t_dev, flag); +} + +syttyp() +{ + register tp; + + tp = u.u_procp->p_ttyp; + if(tp == NULL) + u.u_error = ENXIO; + return(tp); +} diff --git a/sys/dmr/tc.c b/sys/dmr/tc.c new file mode 100644 index 0000000..ff496b3 --- /dev/null +++ b/sys/dmr/tc.c @@ -0,0 +1,171 @@ +# +/* + */ + +/* + * TC-11 DECtape driver + */ + +#include "../param.h" +#include "../conf.h" +#include "../buf.h" +#include "../user.h" + +struct { + int tccsr; + int tccm; + int tcwc; + int tcba; + int tcdt; +}; + +struct devtab tctab; +char tcper[8]; + +#define TCADDR 0177340 +#define NTCBLK 578 + +#define TAPERR 0100000 +#define TREV 04000 +#define READY 0200 +#define IENABLE 0100 +#define UPS 0200 +#define ENDZ 0100000 +#define BLKM 02000 +#define ILGOP 010000 +#define SELERR 04000 + +#define SAT 0 +#define RNUM 02 +#define RDATA 04 +#define SST 010 +#define WDATA 014 +#define GO 01 + +#define SFORW 1 +#define SREV 2 +#define SIO 3 + +tcclose(dev) +{ + bflush(dev); + tcper[dev&07] = 0; +} + +tcstrategy(abp) +struct buf *abp; +{ + register struct buf *bp; + + bp = abp; + if(bp->b_flags&B_PHYS) + mapalloc(bp); + if(bp->b_blkno >= NTCBLK || tcper[bp->b_dev&07]) { + bp->b_flags =| B_ERROR; + iodone(bp); + return; + } + bp->av_forw = 0; + spl6(); + if (tctab.d_actf==0) + tctab.d_actf = bp; + else + tctab.d_actl->av_forw = bp; + tctab.d_actl = bp; + if (tctab.d_active==0) + tcstart(); + spl0(); +} + +tcstart() +{ + register struct buf *bp; + register int *tccmp, com; + +loop: + tccmp = &TCADDR->tccm; + if ((bp = tctab.d_actf) == 0) + return; + if(tcper[bp->b_dev&07]) { + if((tctab.d_actf = bp->av_forw) == 0) + (*tccmp).lobyte = SAT|GO; + bp->b_flags =| B_ERROR; + iodone(bp); + goto loop; + } + if (((*tccmp).hibyte&07) != bp->b_dev.d_minor) + (*tccmp).lobyte = SAT|GO; + tctab.d_errcnt = 20; + tctab.d_active = SFORW; + com = (bp->b_dev.d_minor<<8) | IENABLE|RNUM|GO; + if ((TCADDR->tccsr & UPS) == 0) { + com =| TREV; + tctab.d_active = SREV; + } + *tccmp = com; +} + +tcintr() +{ + register struct buf *bp; + register int *tccmp; + register int *tcdtp; + + tccmp = &TCADDR->tccm; + tcdtp = &TCADDR->tccsr; + bp = tctab.d_actf; + if (*tccmp&TAPERR) { + if((*tcdtp&(ENDZ|BLKM)) == 0) + deverror(bp, *tcdtp, 0); + if(*tcdtp & (ILGOP|SELERR)) { + tcper[bp->b_dev&07]++; + tctab.d_errcnt = 0; + } + *tccmp =& ~TAPERR; + if (--tctab.d_errcnt <= 0) { + bp->b_flags =| B_ERROR; + goto done; + } + if (*tccmp&TREV) { + setforw: + tctab.d_active = SFORW; + *tccmp =& ~TREV; + } else { + setback: + tctab.d_active = SREV; + *tccmp =| TREV; + } + (*tccmp).lobyte = IENABLE|RNUM|GO; + return; + } + tcdtp = &TCADDR->tcdt; + switch (tctab.d_active) { + + case SIO: + done: + tctab.d_active = 0; + if (tctab.d_actf = bp->av_forw) + tcstart(); + else + TCADDR->tccm.lobyte = SAT|GO; + iodone(bp); + return; + + case SFORW: + if (*tcdtp > bp->b_blkno) + goto setback; + if (*tcdtp < bp->b_blkno) + goto setforw; + *--tcdtp = bp->b_addr; /* core address */ + *--tcdtp = bp->b_wcount; + tccmp->lobyte = ((bp->b_xmem & 03) << 4) | IENABLE|GO + | (bp->b_flags&B_READ?RDATA:WDATA); + tctab.d_active = SIO; + return; + + case SREV: + if (*tcdtp+3 > bp->b_blkno) + goto setback; + goto setforw; + } +} diff --git a/sys/dmr/tm.c b/sys/dmr/tm.c new file mode 100644 index 0000000..a203fbd --- /dev/null +++ b/sys/dmr/tm.c @@ -0,0 +1,221 @@ +# +/* + */ + +/* + * TM tape driver + */ + +#include "../param.h" +#include "../buf.h" +#include "../conf.h" +#include "../user.h" + +struct { + int tmer; + int tmcs; + int tmbc; + int tmba; + int tmdb; + int tmrd; +}; + +struct devtab tmtab; +struct buf rtmbuf; + +char t_openf[8]; +char *t_blkno[8]; +char *t_nxrec[8]; + +#define TMADDR 0172520 + +#define GO 01 +#define RCOM 02 +#define WCOM 04 +#define WEOF 06 +#define SFORW 010 +#define SREV 012 +#define WIRG 014 +#define REW 016 +#define DENS 060000 /* 9-channel */ +#define IENABLE 0100 +#define CRDY 0200 +#define GAPSD 010000 +#define TUR 1 +#define HARD 0102200 /* ILC, EOT, NXM */ +#define EOF 0040000 + +#define SSEEK 1 +#define SIO 2 + +tmopen(dev, flag) +{ + register dminor; + + dminor = dev.d_minor; + if (t_openf[dminor]) + u.u_error = ENXIO; + else { + t_openf[dminor]++; + t_blkno[dminor] = 0; + t_nxrec[dminor] = 65535; + } +} + +tmclose(dev, flag) +{ + register int dminor; + + dminor = dev.d_minor; + t_openf[dminor] = 0; + if (flag) + tcommand(dminor, WEOF); + tcommand(dminor, REW); +} + +tcommand(unit, com) +{ + extern lbolt; + + while (tmtab.d_active || (TMADDR->tmcs & CRDY)==0) + sleep(&lbolt, 1); + TMADDR->tmcs = DENS|com|GO | (unit<<8); +} + +tmstrategy(abp) +struct buf *abp; +{ + register struct buf *bp; + register char **p; + + bp = abp; + p = &t_nxrec[bp->b_dev.d_minor]; + if (*p <= bp->b_blkno) { + if (*p < bp->b_blkno) { + bp->b_flags =| B_ERROR; + iodone(bp); + return; + } + if (bp->b_flags&B_READ) { + clrbuf(bp); + iodone(bp); + return; + } + } + if ((bp->b_flags&B_READ)==0) + *p = bp->b_blkno + 1; + bp->av_forw = 0; + spl5(); + if (tmtab.d_actf==0) + tmtab.d_actf = bp; + else + tmtab.d_actl->av_forw = bp; + tmtab.d_actl = bp; + if (tmtab.d_active==0) + tmstart(); + spl0(); +} + +tmstart() +{ + register struct buf *bp; + register int com; + int unit; + register char *blkno; + + loop: + if ((bp = tmtab.d_actf) == 0) + return; + unit = bp->b_dev.d_minor; + blkno = t_blkno[unit]; + if (t_openf[unit] < 0 || (TMADDR->tmcs & CRDY)==0) { + bp->b_flags =| B_ERROR; + tmtab.d_actf = bp->av_forw; + iodone(bp); + goto loop; + } + com = (unit<<8) | ((bp->b_xmem & 03) << 4) | IENABLE|DENS; + if (blkno != bp->b_blkno) { + tmtab.d_active = SSEEK; + if (blkno < bp->b_blkno) { + com =| SFORW|GO; + TMADDR->tmbc = blkno - bp->b_blkno; + } else { + if (bp->b_blkno == 0) + com =| REW|GO; + else { + com =| SREV|GO; + TMADDR->tmbc = bp->b_blkno - blkno; + } + } + TMADDR->tmcs = com; + return; + } + tmtab.d_active = SIO; + TMADDR->tmbc = bp->b_wcount << 1; + TMADDR->tmba = bp->b_addr; /* core address */ + TMADDR->tmcs = com | ((bp->b_flags&B_READ)? RCOM|GO: + ((tmtab.d_errcnt)? WIRG|GO: WCOM|GO)); +} + +tmintr() +{ + register struct buf *bp; + register int unit; + + if ((bp = tmtab.d_actf)==0) + return; + unit = bp->b_dev.d_minor; + if (TMADDR->tmcs < 0) { /* error bit */ +/* + deverror(bp, TMADDR->tmer); + */ + while(TMADDR->tmrd & GAPSD) ; /* wait for gap shutdown */ + if ((TMADDR->tmer&(HARD|EOF))==0 && tmtab.d_active==SIO) { + if (++tmtab.d_errcnt < 10) { + t_blkno[unit]++; + tmtab.d_active = 0; + tmstart(); + return; + } + } else + if(bp != &rtmbuf && (TMADDR->tmer&EOF)==0) + t_openf[unit] = -1; + bp->b_flags =| B_ERROR; + tmtab.d_active = SIO; + } + if (tmtab.d_active == SIO) { + tmtab.d_errcnt = 0; + t_blkno[unit]++; + tmtab.d_actf = bp->av_forw; + tmtab.d_active = 0; + iodone(bp); + bp->b_resid = TMADDR->tmbc; + } else + t_blkno[unit] = bp->b_blkno; + tmstart(); +} + +tmread(dev) +{ + tmphys(dev); + physio(tmstrategy, &rtmbuf, dev, B_READ); + u.u_count = -rtmbuf.b_resid; +} + +tmwrite(dev) +{ + tmphys(dev); + physio(tmstrategy, &rtmbuf, dev, B_WRITE); + u.u_count = 0; +} + +tmphys(dev) +{ + register unit, a; + + unit = dev.d_minor; + a = lshift(u.u_offset, -9); + t_blkno[unit] = a; + t_nxrec[unit] = ++a; +} diff --git a/sys/dmr/tty.c b/sys/dmr/tty.c new file mode 100644 index 0000000..e430584 --- /dev/null +++ b/sys/dmr/tty.c @@ -0,0 +1,537 @@ +# +/* + */ + +/* + * general TTY subroutines + */ +#include "../param.h" +#include "../systm.h" +#include "../user.h" +#include "../tty.h" +#include "../proc.h" +#include "../inode.h" +#include "../file.h" +#include "../reg.h" +#include "../conf.h" + +/* + * Input mapping table-- if an entry is non-zero, when the + * corresponding character is typed preceded by "\" the escape + * sequence is replaced by the table value. Mostly used for + * upper-case only terminals. + */ +char maptab[] +{ + 000,000,000,000,004,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,'|',000,'#',000,000,000,'`', + '{','}',000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + '@',000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,'~',000, + 000,'A','B','C','D','E','F','G', + 'H','I','J','K','L','M','N','O', + 'P','Q','R','S','T','U','V','W', + 'X','Y','Z',000,000,000,000,000, +}; + +/* + * The actual structure of a clist block manipulated by + * getc and putc (mch.s) + */ +struct cblock { + struct cblock *c_next; + char info[6]; +}; + +/* The character lists-- space for 6*NCLIST characters */ +struct cblock cfree[NCLIST]; +/* List head for unused character blocks. */ +struct cblock *cfreelist; + +/* + * structure of device registers for KL, DL, and DC + * interfaces-- more particularly, those for which the + * SSTART bit is off and can be treated by general routines + * (that is, not DH). + */ +struct { + int ttrcsr; + int ttrbuf; + int tttcsr; + int tttbuf; +}; + +/* + * The routine implementing the gtty system call. + * Just call lower level routine and pass back values. + */ +gtty() +{ + int v[3]; + register *up, *vp; + + vp = v; + sgtty(vp); + if (u.u_error) + return; + up = u.u_arg[0]; + suword(up, *vp++); + suword(++up, *vp++); + suword(++up, *vp++); +} + +/* + * The routine implementing the stty system call. + * Read in values and call lower level. + */ +stty() +{ + register int *up; + + up = u.u_arg[0]; + u.u_arg[0] = fuword(up); + u.u_arg[1] = fuword(++up); + u.u_arg[2] = fuword(++up); + sgtty(0); +} + +/* + * Stuff common to stty and gtty. + * Check legality and switch out to individual + * device routine. + * v is 0 for stty; the parameters are taken from u.u_arg[]. + * c is non-zero for gtty and is the place in which the device + * routines place their information. + */ +sgtty(v) +int *v; +{ + register struct file *fp; + register struct inode *ip; + + if ((fp = getf(u.u_ar0[R0])) == NULL) + return; + ip = fp->f_inode; + if ((ip->i_mode&IFMT) != IFCHR) { + u.u_error = ENOTTY; + return; + } + (*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v); +} + +/* + * Wait for output to drain, then flush input waiting. + */ +wflushtty(atp) +struct tty *atp; +{ + register struct tty *tp; + + tp = atp; + spl5(); + while (tp->t_outq.c_cc) { + tp->t_state =| ASLEEP; + sleep(&tp->t_outq, TTOPRI); + } + flushtty(tp); + spl0(); +} + +/* + * Initialize clist by freeing all character blocks, then count + * number of character devices. (Once-only routine) + */ +cinit() +{ + register int ccp; + register struct cblock *cp; + register struct cdevsw *cdp; + + ccp = cfree; + for (cp=(ccp+07)&~07; cp <= &cfree[NCLIST-1]; cp++) { + cp->c_next = cfreelist; + cfreelist = cp; + } + ccp = 0; + for(cdp = cdevsw; cdp->d_open; cdp++) + ccp++; + nchrdev = ccp; +} + +/* + * flush all TTY queues + */ +flushtty(atp) +struct tty *atp; +{ + register struct tty *tp; + register int sps; + + tp = atp; + while (getc(&tp->t_canq) >= 0); + while (getc(&tp->t_outq) >= 0); + wakeup(&tp->t_rawq); + wakeup(&tp->t_outq); + sps = PS->integ; + spl5(); + while (getc(&tp->t_rawq) >= 0); + tp->t_delct = 0; + PS->integ = sps; +} + +/* + * transfer raw input list to canonical list, + * doing erase-kill processing and handling escapes. + * It waits until a full line has been typed in cooked mode, + * or until any character has been typed in raw mode. + */ +canon(atp) +struct tty *atp; +{ + register char *bp; + char *bp1; + register struct tty *tp; + register int c; + + tp = atp; + spl5(); + while (tp->t_delct==0) { + if ((tp->t_state&CARR_ON)==0) + return(0); + sleep(&tp->t_rawq, TTIPRI); + } + spl0(); +loop: + bp = &canonb[2]; + while ((c=getc(&tp->t_rawq)) >= 0) { + if (c==0377) { + tp->t_delct--; + break; + } + if ((tp->t_flags&RAW)==0) { + if (bp[-1]!='\\') { + if (c==tp->t_erase) { + if (bp > &canonb[2]) + bp--; + continue; + } + if (c==tp->t_kill) + goto loop; + if (c==CEOT) + continue; + } else + if (maptab[c] && (maptab[c]==c || (tp->t_flags&LCASE))) { + if (bp[-2] != '\\') + c = maptab[c]; + bp--; + } + } + *bp++ = c; + if (bp>=canonb+CANBSIZ) + break; + } + bp1 = bp; + bp = &canonb[2]; + c = &tp->t_canq; + while (bpt_flags; + if ((c =& 0177) == '\r' && t_flags&CRMOD) + c = '\n'; + if ((t_flags&RAW)==0 && (c==CQUIT || c==CINTR)) { + signal(tp, c==CINTR? SIGINT:SIGQIT); + flushtty(tp); + return; + } + if (tp->t_rawq.c_cc>=TTYHOG) { + flushtty(tp); + return; + } + if (t_flags&LCASE && c>='A' && c<='Z') + c =+ 'a'-'A'; + putc(c, &tp->t_rawq); + if (t_flags&RAW || c=='\n' || c==004) { + wakeup(&tp->t_rawq); + if (putc(0377, &tp->t_rawq)==0) + tp->t_delct++; + } + if (t_flags&ECHO) { + ttyoutput(c, tp); + ttstart(tp); + } +} + +/* + * put character on TTY output queue, adding delays, + * expanding tabs, and handling the CR/NL bit. + * It is called both from the top half for output, and from + * interrupt level for echoing. + * The arguments are the character and the tty structure. + */ +ttyoutput(ac, tp) +struct tty *tp; +{ + register int c; + register struct tty *rtp; + register char *colp; + int ctype; + + rtp = tp; + c = ac&0177; + /* + * Ignore EOT in normal mode to avoid hanging up + * certain terminals. + */ + if (c==004 && (rtp->t_flags&RAW)==0) + return; + /* + * Turn tabs to spaces as required + */ + if (c=='\t' && rtp->t_flags&XTABS) { + do + ttyoutput(' ', rtp); + while (rtp->t_col&07); + return; + } + /* + * for upper-case-only terminals, + * generate escapes. + */ + if (rtp->t_flags&LCASE) { + colp = "({)}!|^~'`"; + while(*colp++) + if(c == *colp++) { + ttyoutput('\\', rtp); + c = colp[-2]; + break; + } + if ('a'<=c && c<='z') + c =+ 'A' - 'a'; + } + /* + * turn to if desired. + */ + if (c=='\n' && rtp->t_flags&CRMOD) + ttyoutput('\r', rtp); + if (putc(c, &rtp->t_outq)) + return; + /* + * Calculate delays. + * The numbers here represent clock ticks + * and are not necessarily optimal for all terminals. + * The delays are indicated by characters above 0200, + * thus (unfortunately) restricting the transmission + * path to 7 bits. + */ + colp = &rtp->t_col; + ctype = partab[c]; + c = 0; + switch (ctype&077) { + + /* ordinary */ + case 0: + (*colp)++; + + /* non-printing */ + case 1: + break; + + /* backspace */ + case 2: + if (*colp) + (*colp)--; + break; + + /* newline */ + case 3: + ctype = (rtp->t_flags >> 8) & 03; + if(ctype == 1) { /* tty 37 */ + if (*colp) + c = max((*colp>>4) + 3, 6); + } else + if(ctype == 2) { /* vt05 */ + c = 6; + } + *colp = 0; + break; + + /* tab */ + case 4: + ctype = (rtp->t_flags >> 10) & 03; + if(ctype == 1) { /* tty 37 */ + c = 1 - (*colp | ~07); + if(c < 5) + c = 0; + } + *colp =| 07; + (*colp)++; + break; + + /* vertical motion */ + case 5: + if(rtp->t_flags & VTDELAY) /* tty 37 */ + c = 0177; + break; + + /* carriage return */ + case 6: + ctype = (rtp->t_flags >> 12) & 03; + if(ctype == 1) { /* tn 300 */ + c = 5; + } else + if(ctype == 2) { /* ti 700 */ + c = 10; + } + *colp = 0; + } + if(c) + putc(c|0200, &rtp->t_outq); +} + +/* + * Restart typewriter output following a delay + * timeout. + * The name of the routine is passed to the timeout + * subroutine and it is called during a clock interrupt. + */ +ttrstrt(atp) +{ + register struct tty *tp; + + tp = atp; + tp->t_state =& ~TIMEOUT; + ttstart(tp); +} + +/* + * Start output on the typewriter. It is used from the top half + * after some characters have been put on the output queue, + * from the interrupt routine to transmit the next + * character, and after a timeout has finished. + * If the SSTART bit is off for the tty the work is done here, + * using the protocol of the single-line interfaces (KL, DL, DC); + * otherwise the address word of the tty structure is + * taken to be the name of the device-dependent startup routine. + */ +ttstart(atp) +struct tty *atp; +{ + register int *addr, c; + register struct tty *tp; + struct { int (*func)(); }; + + tp = atp; + addr = tp->t_addr; + if (tp->t_state&SSTART) { + (*addr.func)(tp); + return; + } + if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT) + return; + if ((c=getc(&tp->t_outq)) >= 0) { + if (c<=0177) + addr->tttbuf = c | (partab[c]&0200); + else { + timeout(ttrstrt, tp, c&0177); + tp->t_state =| TIMEOUT; + } + } +} + +/* + * Called from device's read routine after it has + * calculated the tty-structure given as argument. + * The pc is backed up for the duration of this call. + * In case of a caught interrupt, an RTI will re-execute. + */ +ttread(atp) +struct tty *atp; +{ + register struct tty *tp; + + tp = atp; + if ((tp->t_state&CARR_ON)==0) + return; + if (tp->t_canq.c_cc || canon(tp)) + while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0); +} + +/* + * Called from the device's write routine after it has + * calculated the tty-structure given as argument. + */ +ttwrite(atp) +struct tty *atp; +{ + register struct tty *tp; + register int c; + + tp = atp; + if ((tp->t_state&CARR_ON)==0) + return; + while ((c=cpass())>=0) { + spl5(); + while (tp->t_outq.c_cc > TTHIWAT) { + ttstart(tp); + tp->t_state =| ASLEEP; + sleep(&tp->t_outq, TTOPRI); + } + spl0(); + ttyoutput(c, tp); + } + ttstart(tp); +} + +/* + * Common code for gtty and stty functions on typewriters. + * If v is non-zero then gtty is being done and information is + * passed back therein; + * if it is zero stty is being done and the input information is in the + * u_arg array. + */ +ttystty(atp, av) +int *atp, *av; +{ + register *tp, *v; + + tp = atp; + if(v = av) { + *v++ = tp->t_speeds; + v->lobyte = tp->t_erase; + v->hibyte = tp->t_kill; + v[1] = tp->t_flags; + return(1); + } + wflushtty(tp); + v = u.u_arg; + tp->t_speeds = *v++; + tp->t_erase = v->lobyte; + tp->t_kill = v->hibyte; + tp->t_flags = v[1]; + return(0); +} diff --git a/sys/dmr/vs.c b/sys/dmr/vs.c new file mode 100644 index 0000000..829bf49 --- /dev/null +++ b/sys/dmr/vs.c @@ -0,0 +1,122 @@ +# +/* + */ + +/* + * Screw Works interface via DC-11 + */ + +#include "../tty.h" + +#define VSADDR 0174150 +#define CDLEAD 01 +#define B1200 030 +#define STOP1 0400 +#define CLSEND 02 +#define RQSEND 01 + +#define MAGIC_MAP 0377 + +struct { + int vsrcsr; + int vsrbuf; + int vsxcsr; + int vsxbuf; +}; + +struct { + struct clist iq; + struct clist oq; +} vs; + +vsopen(dev) +{ + VSADDR->vsrcsr = IENABLE|B1200|CDLEAD; + VSADDR->vsxcsr = STOP1|IENABLE|B1200; + vschar(0); +} + +vsclose(dev) +{ + vschar(0); + VSADDR->vsrcsr =& ~IENABLE; + while (getc(&vs.iq) >= 0); +} + +vswrite(dev) +{ + register int count, c; + + count = 0; + while ((c=cpass()) >= 0) { + if (--count <= 0) { + count = 60; + vschar(0); + } + vschar(c); + } + vschar(0); +} + +vschar(c) +{ + + c =^ MAGIC_MAP; + spl5(); + while (vs.oq.c_cc > 60) { + vsxintr(); + sleep(&vs.oq, TTIPRI); + } + putc(c, &vs.oq); + vsxintr(); + spl0(); +} + +vsxintr() +{ + static lchar; + register c; + register int *xcsr; + + xcsr = &VSADDR->vsxcsr; + if (*xcsr&DONE) { + if (lchar==MAGIC_MAP) { + *xcsr =& ~RQSEND; + lchar = 0; + if (vs.oq.c_cc==0) + goto wake; + } + if ((*xcsr&CLSEND) == 0) { + *xcsr =& ~RQSEND; + *xcsr =| RQSEND; + if ((*xcsr&CLSEND) == 0) + goto wake; + } + if ((c = getc(&vs.oq)) >= 0) + VSADDR->vsxbuf = lchar = c; + if (vs.oq.c_cc <= 15) + wake: + wakeup(&vs.oq); + } +} + +vsread(dev) +{ + register int c; + + spl5(); + while ((c = getc(&vs.iq)) < 0) + sleep(&vs.iq, TTIPRI); + spl0(); + passc("?0*#?546?213?879?"[c&017]); +} + +vsrintr() +{ + register int c; + + c = VSADDR->vsrbuf; + if (vs.iq.c_cc<=10) + putc(c, &vs.iq); + wakeup(&vs.iq); +} diff --git a/sys/dmr/vt.c b/sys/dmr/vt.c new file mode 100644 index 0000000..392e638 --- /dev/null +++ b/sys/dmr/vt.c @@ -0,0 +1,70 @@ +# +/* + */ + +/* + * VT01 driver via DR11C to 11/20 + */ + +#include "../param.h" +#include "../user.h" + +int vtflag; + +struct vtreg { + int csr; + int buf; +}; + +#define VTADDR 0167770 +#define RQINT 01 +#define BIENABL 040 +#define SEOF 0100000 +#define VTPRI 8 + +vtopen(dev, flag) +{ + if (!flag) + u.u_error = ENXIO; + else + VTADDR->csr = BIENABL; +} + +vtclose() +{ + VTADDR->buf = SEOF; + VTADDR->csr =| RQINT; +} + +vtwrite() +{ + register int c; + int register count; + + while ((c=cpass()) >= 0) { + retry: + for (count=0; count<10; count++) + if ((VTADDR->csr&RQINT)==0) { + VTADDR->buf = c&0377; + VTADDR->csr =| RQINT; + goto contin; + } + spl5(); + if (VTADDR->csr&RQINT) { + vtflag++; + sleep(VTADDR, VTPRI); + } + spl0(); + goto retry; + contin:; + } +} + +vtintr() +{ + VTADDR->csr =& ~RQINT; + if (vtflag) { + vtflag = 0; + wakeup(VTADDR); + } +} diff --git a/sys/file.h b/sys/file.h new file mode 100644 index 0000000..9c44ab3 --- /dev/null +++ b/sys/file.h @@ -0,0 +1,19 @@ +/* + * One file structure is allocated + * for each open/creat/pipe call. + * Main use is to hold the read/write + * pointer associated with each open + * file. + */ +struct file +{ + char f_flag; + char f_count; /* reference count */ + int f_inode; /* pointer to inode structure */ + char *f_offset[2]; /* read/write character pointer */ +} file[NFILE]; + +/* flags */ +#define FREAD 01 +#define FWRITE 02 +#define FPIPE 04 diff --git a/sys/filsys.h b/sys/filsys.h new file mode 100644 index 0000000..6a53d78 --- /dev/null +++ b/sys/filsys.h @@ -0,0 +1,26 @@ +/* + * Definition of the unix super block. + * The root super block is allocated and + * read in iinit/alloc.c. Subsequently + * a super block is allocated and read + * with each mount (smount/sys3.c) and + * released with unmount (sumount/sys3.c). + * A disk block is ripped off for storage. + * See alloc.c for general alloc/free + * routines for free list and I list. + */ +struct filsys +{ + int s_isize; /* size in blocks of I list */ + int s_fsize; /* size in blocks of entire volume */ + int s_nfree; /* number of in core free blocks (0-100) */ + int s_free[100]; /* in core free blocks */ + int s_ninode; /* number of in core I nodes (0-100) */ + int s_inode[100]; /* in core free I nodes */ + char s_flock; /* lock during free list manipulation */ + char s_ilock; /* lock during I list manipulation */ + char s_fmod; /* super block modified flag */ + char s_ronly; /* mounted read-only flag */ + int s_time[2]; /* current date of last update */ + int pad[50]; +}; diff --git a/sys/ino.h b/sys/ino.h new file mode 100644 index 0000000..d9fbd4f --- /dev/null +++ b/sys/ino.h @@ -0,0 +1,31 @@ +/* + * Inode structure as it appears on + * the disk. Not used by the system, + * but by things like check, df, dump. + */ +struct inode +{ + int i_mode; + char i_nlink; + char i_uid; + char i_gid; + char i_size0; + char *i_size1; + int i_addr[8]; + int i_atime[2]; + int i_mtime[2]; +}; + +/* modes */ +#define IALLOC 0100000 +#define IFMT 060000 +#define IFDIR 040000 +#define IFCHR 020000 +#define IFBLK 060000 +#define ILARG 010000 +#define ISUID 04000 +#define ISGID 02000 +#define ISVTX 01000 +#define IREAD 0400 +#define IWRITE 0200 +#define IEXEC 0100 diff --git a/sys/inode.h b/sys/inode.h new file mode 100644 index 0000000..88c7fe6 --- /dev/null +++ b/sys/inode.h @@ -0,0 +1,47 @@ +/* + * The I node is the focus of all + * file activity in unix. There is a unique + * inode allocated for each active file, + * each current directory, each mounted-on + * file, text file, and the root. An inode is 'named' + * by its dev/inumber pair. (iget/iget.c) + * Data, from mode on, is read in + * from permanent inode on volume. + */ +struct inode +{ + char i_flag; + char i_count; /* reference count */ + int i_dev; /* device where inode resides */ + int i_number; /* i number, 1-to-1 with device address */ + int i_mode; + char i_nlink; /* directory entries */ + char i_uid; /* owner */ + char i_gid; /* group of owner */ + char i_size0; /* most significant of size */ + char *i_size1; /* least sig */ + int i_addr[8]; /* device addresses constituting file */ + int i_lastr; /* last logical block read (for read-ahead) */ +} inode[NINODE]; + +/* flags */ +#define ILOCK 01 /* inode is locked */ +#define IUPD 02 /* inode has been modified */ +#define IACC 04 /* inode access time to be updated */ +#define IMOUNT 010 /* inode is mounted on */ +#define IWANT 020 /* some process waiting on lock */ +#define ITEXT 040 /* inode is pure text prototype */ + +/* modes */ +#define IALLOC 0100000 /* file is used */ +#define IFMT 060000 /* type of file */ +#define IFDIR 040000 /* directory */ +#define IFCHR 020000 /* character special */ +#define IFBLK 060000 /* block special, 0 is regular */ +#define ILARG 010000 /* large addressing algorithm */ +#define ISUID 04000 /* set user id on execution */ +#define ISGID 02000 /* set group id on execution */ +#define ISVTX 01000 /* save swapped text even after use */ +#define IREAD 0400 /* read, write, execute permissions */ +#define IWRITE 0200 +#define IEXEC 0100 diff --git a/sys/ken/alloc.c b/sys/ken/alloc.c new file mode 100644 index 0000000..781f8e2 --- /dev/null +++ b/sys/ken/alloc.c @@ -0,0 +1,314 @@ +# +/* + */ + +#include "../param.h" +#include "../systm.h" +#include "../filsys.h" +#include "../conf.h" +#include "../buf.h" +#include "../inode.h" +#include "../user.h" + +/* + * iinit is called once (from main) + * very early in initialization. + * It reads the root's super block + * and initializes the current date + * from the last modified date. + * + * panic: iinit -- cannot read the super + * block. Usually because of an IO error. + */ +iinit() +{ + register *cp, *bp; + + (*bdevsw[rootdev.d_major].d_open)(rootdev, 1); + bp = bread(rootdev, 1); + cp = getblk(NODEV); + if(u.u_error) + panic("iinit"); + bcopy(bp->b_addr, cp->b_addr, 256); + brelse(bp); + mount[0].m_bufp = cp; + mount[0].m_dev = rootdev; + cp = cp->b_addr; + cp->s_flock = 0; + cp->s_ilock = 0; + cp->s_ronly = 0; + time[0] = cp->s_time[0]; + time[1] = cp->s_time[1]; +} + +/* + * alloc will obtain the next available + * free disk block from the free list of + * the specified device. + * The super block has up to 100 remembered + * free blocks; the last of these is read to + * obtain 100 more . . . + * + * no space on dev x/y -- when + * the free list is exhausted. + */ +alloc(dev) +{ + int bno; + register *bp, *ip, *fp; + + fp = getfs(dev); + while(fp->s_flock) + sleep(&fp->s_flock, PINOD); + do { + if(fp->s_nfree <= 0) + goto nospace; + bno = fp->s_free[--fp->s_nfree]; + if(bno == 0) + goto nospace; + } while (badblock(fp, bno, dev)); + if(fp->s_nfree <= 0) { + fp->s_flock++; + bp = bread(dev, bno); + ip = bp->b_addr; + fp->s_nfree = *ip++; + bcopy(ip, fp->s_free, 100); + brelse(bp); + fp->s_flock = 0; + wakeup(&fp->s_flock); + } + bp = getblk(dev, bno); + clrbuf(bp); + fp->s_fmod = 1; + return(bp); + +nospace: + fp->s_nfree = 0; + prdev("no space", dev); + u.u_error = ENOSPC; + return(NULL); +} + +/* + * place the specified disk block + * back on the free list of the + * specified device. + */ +free(dev, bno) +{ + register *fp, *bp, *ip; + + fp = getfs(dev); + fp->s_fmod = 1; + while(fp->s_flock) + sleep(&fp->s_flock, PINOD); + if (badblock(fp, bno, dev)) + return; + if(fp->s_nfree <= 0) { + fp->s_nfree = 1; + fp->s_free[0] = 0; + } + if(fp->s_nfree >= 100) { + fp->s_flock++; + bp = getblk(dev, bno); + ip = bp->b_addr; + *ip++ = fp->s_nfree; + bcopy(fp->s_free, ip, 100); + fp->s_nfree = 0; + bwrite(bp); + fp->s_flock = 0; + wakeup(&fp->s_flock); + } + fp->s_free[fp->s_nfree++] = bno; + fp->s_fmod = 1; +} + +/* + * Check that a block number is in the + * range between the I list and the size + * of the device. + * This is used mainly to check that a + * garbage file system has not been mounted. + * + * bad block on dev x/y -- not in range + */ +badblock(afp, abn, dev) +{ + register struct filsys *fp; + register char *bn; + + fp = afp; + bn = abn; + if (bn < fp->s_isize+2 || bn >= fp->s_fsize) { + prdev("bad block", dev); + return(1); + } + return(0); +} + +/* + * Allocate an unused I node + * on the specified device. + * Used with file creation. + * The algorithm keeps up to + * 100 spare I nodes in the + * super block. When this runs out, + * a linear search through the + * I list is instituted to pick + * up 100 more. + */ +ialloc(dev) +{ + register *fp, *bp, *ip; + int i, j, k, ino; + + fp = getfs(dev); + while(fp->s_ilock) + sleep(&fp->s_ilock, PINOD); +loop: + if(fp->s_ninode > 0) { + ino = fp->s_inode[--fp->s_ninode]; + ip = iget(dev, ino); + if (ip==NULL) + return(NULL); + if(ip->i_mode == 0) { + for(bp = &ip->i_mode; bp < &ip->i_addr[8];) + *bp++ = 0; + fp->s_fmod = 1; + return(ip); + } + /* + * Inode was allocated after all. + * Look some more. + */ + iput(ip); + goto loop; + } + fp->s_ilock++; + ino = 0; + for(i=0; is_isize; i++) { + bp = bread(dev, i+2); + ip = bp->b_addr; + for(j=0; j<256; j=+16) { + ino++; + if(ip[j] != 0) + continue; + for(k=0; ks_inode[fp->s_ninode++] = ino; + if(fp->s_ninode >= 100) + break; + cont:; + } + brelse(bp); + if(fp->s_ninode >= 100) + break; + } + fp->s_ilock = 0; + wakeup(&fp->s_ilock); + if (fp->s_ninode > 0) + goto loop; + prdev("Out of inodes", dev); + u.u_error = ENOSPC; + return(NULL); +} + +/* + * Free the specified I node + * on the specified device. + * The algorithm stores up + * to 100 I nodes in the super + * block and throws away any more. + */ +ifree(dev, ino) +{ + register *fp; + + fp = getfs(dev); + if(fp->s_ilock) + return; + if(fp->s_ninode >= 100) + return; + fp->s_inode[fp->s_ninode++] = ino; + fp->s_fmod = 1; +} + +/* + * getfs maps a device number into + * a pointer to the incore super + * block. + * The algorithm is a linear + * search through the mount table. + * A consistency check of the + * in core free-block and i-node + * counts. + * + * bad count on dev x/y -- the count + * check failed. At this point, all + * the counts are zeroed which will + * almost certainly lead to "no space" + * diagnostic + * panic: no fs -- the device is not mounted. + * this "cannot happen" + */ +getfs(dev) +{ + register struct mount *p; + register char *n1, *n2; + + for(p = &mount[0]; p < &mount[NMOUNT]; p++) + if(p->m_bufp != NULL && p->m_dev == dev) { + p = p->m_bufp->b_addr; + n1 = p->s_nfree; + n2 = p->s_ninode; + if(n1 > 100 || n2 > 100) { + prdev("bad count", dev); + p->s_nfree = 0; + p->s_ninode = 0; + } + return(p); + } + panic("no fs"); +} + +/* + * update is the internal name of + * 'sync'. It goes through the disk + * queues to initiate sandbagged IO; + * goes through the I nodes to write + * modified nodes; and it goes through + * the mount table to initiate modified + * super blocks. + */ +update() +{ + register struct inode *ip; + register struct mount *mp; + register *bp; + + if(updlock) + return; + updlock++; + for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) + if(mp->m_bufp != NULL) { + ip = mp->m_bufp->b_addr; + if(ip->s_fmod==0 || ip->s_ilock!=0 || + ip->s_flock!=0 || ip->s_ronly!=0) + continue; + bp = getblk(mp->m_dev, 1); + ip->s_fmod = 0; + ip->s_time[0] = time[0]; + ip->s_time[1] = time[1]; + bcopy(ip, bp->b_addr, 256); + bwrite(bp); + } + for(ip = &inode[0]; ip < &inode[NINODE]; ip++) + if((ip->i_flag&ILOCK) == 0) { + ip->i_flag =| ILOCK; + iupdat(ip, time); + prele(ip); + } + updlock = 0; + bflush(NODEV); +} diff --git a/sys/ken/clock.c b/sys/ken/clock.c new file mode 100644 index 0000000..2b782b1 --- /dev/null +++ b/sys/ken/clock.c @@ -0,0 +1,173 @@ +# +#include "../param.h" +#include "../systm.h" +#include "../user.h" +#include "../proc.h" + +#define UMODE 0170000 +#define SCHMAG 10 + +/* + * clock is called straight from + * the real time clock interrupt. + * + * Functions: + * reprime clock + * copy *switches to display + * implement callouts + * maintain user/system times + * maintain date + * profile + * tout wakeup (sys sleep) + * lightning bolt wakeup (every 4 sec) + * alarm clock signals + * jab the scheduler + */ +clock(dev, sp, r1, nps, r0, pc, ps) +{ + register struct callo *p1, *p2; + register struct proc *pp; + + /* + * restart clock + */ + + *lks = 0115; + + /* + * display register + */ + + display(); + + /* + * callouts + * if none, just return + * else update first non-zero time + */ + + if(callout[0].c_func == 0) + goto out; + p2 = &callout[0]; + while(p2->c_time<=0 && p2->c_func!=0) + p2++; + p2->c_time--; + + /* + * if ps is high, just return + */ + + if((ps&0340) != 0) + goto out; + + /* + * callout + */ + + spl5(); + if(callout[0].c_time <= 0) { + p1 = &callout[0]; + while(p1->c_func != 0 && p1->c_time <= 0) { + (*p1->c_func)(p1->c_arg); + p1++; + } + p2 = &callout[0]; + while(p2->c_func = p1->c_func) { + p2->c_time = p1->c_time; + p2->c_arg = p1->c_arg; + p1++; + p2++; + } + } + + /* + * lightning bolt time-out + * and time of day + */ + +out: + if((ps&UMODE) == UMODE) { + u.u_utime++; + if(u.u_prof[3]) + incupc(pc, u.u_prof); + } else + u.u_stime++; + pp = u.u_procp; + if(++pp->p_cpu == 0) + pp->p_cpu--; + if(++lbolt >= HZ) { + if((ps&0340) != 0) + return; + lbolt =- HZ; + if(++time[1] == 0) + ++time[0]; + spl1(); + if(time[1]==tout[1] && time[0]==tout[0]) + wakeup(tout); + if((time[1]&03) == 0) { + runrun++; + wakeup(&lbolt); + } + for(pp = &proc[0]; pp < &proc[NPROC]; pp++) + if (pp->p_stat) { + if(pp->p_time != 127) + pp->p_time++; + if((pp->p_cpu & 0377) > SCHMAG) + pp->p_cpu =- SCHMAG; else + pp->p_cpu = 0; + if(pp->p_pri > PUSER) + setpri(pp); + } + if(runin!=0) { + runin = 0; + wakeup(&runin); + } + if((ps&UMODE) == UMODE) { + u.u_ar0 = &r0; + if(issig()) + psig(); + setpri(u.u_procp); + } + } +} + +/* + * timeout is called to arrange that + * fun(arg) is called in tim/HZ seconds. + * An entry is sorted into the callout + * structure. The time in each structure + * entry is the number of HZ's more + * than the previous entry. + * In this way, decrementing the + * first entry has the effect of + * updating all entries. + */ +timeout(fun, arg, tim) +{ + register struct callo *p1, *p2; + register t; + int s; + + t = tim; + s = PS->integ; + p1 = &callout[0]; + spl7(); + while(p1->c_func != 0 && p1->c_time <= t) { + t =- p1->c_time; + p1++; + } + p1->c_time =- t; + p2 = p1; + while(p2->c_func != 0) + p2++; + while(p2 >= p1) { + (p2+1)->c_time = p2->c_time; + (p2+1)->c_func = p2->c_func; + (p2+1)->c_arg = p2->c_arg; + p2--; + } + p1->c_time = t; + p1->c_func = fun; + p1->c_arg = arg; + PS->integ = s; +} diff --git a/sys/ken/fio.c b/sys/ken/fio.c new file mode 100644 index 0000000..cff2a0d --- /dev/null +++ b/sys/ken/fio.c @@ -0,0 +1,258 @@ +# +/* + */ + +#include "../param.h" +#include "../user.h" +#include "../filsys.h" +#include "../file.h" +#include "../conf.h" +#include "../inode.h" +#include "../reg.h" + +/* + * Convert a user supplied + * file descriptor into a pointer + * to a file structure. + * Only task is to check range + * of the descriptor. + */ +getf(f) +{ + register *fp, rf; + + rf = f; + if(rf<0 || rf>=NOFILE) + goto bad; + fp = u.u_ofile[rf]; + if(fp != NULL) + return(fp); +bad: + u.u_error = EBADF; + return(NULL); +} + +/* + * Internal form of close. + * Decrement reference count on + * file structure and call closei + * on last closef. + * Also make sure the pipe protocol + * does not constipate. + */ +closef(fp) +int *fp; +{ + register *rfp, *ip; + + rfp = fp; + if(rfp->f_flag&FPIPE) { + ip = rfp->f_inode; + ip->i_mode =& ~(IREAD|IWRITE); + wakeup(ip+1); + wakeup(ip+2); + } + if(rfp->f_count <= 1) + closei(rfp->f_inode, rfp->f_flag&FWRITE); + rfp->f_count--; +} + +/* + * Decrement reference count on an + * inode due to the removal of a + * referencing file structure. + * On the last closei, switchout + * to the close entry point of special + * device handler. + * Note that the handler gets called + * on every open and only on the last + * close. + */ +closei(ip, rw) +int *ip; +{ + register *rip; + register dev, maj; + + rip = ip; + dev = rip->i_addr[0]; + maj = rip->i_addr[0].d_major; + if(rip->i_count <= 1) + switch(rip->i_mode&IFMT) { + + case IFCHR: + (*cdevsw[maj].d_close)(dev, rw); + break; + + case IFBLK: + (*bdevsw[maj].d_close)(dev, rw); + } + iput(rip); +} + +/* + * openi called to allow handler + * of special files to initialize and + * validate before actual IO. + * Called on all sorts of opens + * and also on mount. + */ +openi(ip, rw) +int *ip; +{ + register *rip; + register dev, maj; + + rip = ip; + dev = rip->i_addr[0]; + maj = rip->i_addr[0].d_major; + switch(rip->i_mode&IFMT) { + + case IFCHR: + if(maj >= nchrdev) + goto bad; + (*cdevsw[maj].d_open)(dev, rw); + break; + + case IFBLK: + if(maj >= nblkdev) + goto bad; + (*bdevsw[maj].d_open)(dev, rw); + } + return; + +bad: + u.u_error = ENXIO; +} + +/* + * Check mode permission on inode pointer. + * Mode is READ, WRITE or EXEC. + * In the case of WRITE, the + * read-only status of the file + * system is checked. + * Also in WRITE, prototype text + * segments cannot be written. + * The mode is shifted to select + * the owner/group/other fields. + * The super user is granted all + * permissions except for EXEC where + * at least one of the EXEC bits must + * be on. + */ +access(aip, mode) +int *aip; +{ + register *ip, m; + + ip = aip; + m = mode; + if(m == IWRITE) { + if(getfs(ip->i_dev)->s_ronly != 0) { + u.u_error = EROFS; + return(1); + } + if(ip->i_flag & ITEXT) { + u.u_error = ETXTBSY; + return(1); + } + } + if(u.u_uid == 0) { + if(m == IEXEC && (ip->i_mode & + (IEXEC | (IEXEC>>3) | (IEXEC>>6))) == 0) + goto bad; + return(0); + } + if(u.u_uid != ip->i_uid) { + m =>> 3; + if(u.u_gid != ip->i_gid) + m =>> 3; + } + if((ip->i_mode&m) != 0) + return(0); + +bad: + u.u_error = EACCES; + return(1); +} + +/* + * Look up a pathname and test if + * the resultant inode is owned by the + * current user. + * If not, try for super-user. + * If permission is granted, + * return inode pointer. + */ +owner() +{ + register struct inode *ip; + extern uchar(); + + if ((ip = namei(uchar, 0)) == NULL) + return(NULL); + if(u.u_uid == ip->i_uid) + return(ip); + if (suser()) + return(ip); + iput(ip); + return(NULL); +} + +/* + * Test if the current user is the + * super user. + */ +suser() +{ + + if(u.u_uid == 0) + return(1); + u.u_error = EPERM; + return(0); +} + +/* + * Allocate a user file descriptor. + */ +ufalloc() +{ + register i; + + for (i=0; if_count==0) { + u.u_ofile[i] = fp; + fp->f_count++; + fp->f_offset[0] = 0; + fp->f_offset[1] = 0; + return(fp); + } + printf("no file\n"); + u.u_error = ENFILE; + return(NULL); +} diff --git a/sys/ken/iget.c b/sys/ken/iget.c new file mode 100644 index 0000000..333b91c --- /dev/null +++ b/sys/ken/iget.c @@ -0,0 +1,234 @@ +# +#include "../param.h" +#include "../systm.h" +#include "../user.h" +#include "../inode.h" +#include "../filsys.h" +#include "../conf.h" +#include "../buf.h" + +/* + * Look up an inode by device,inumber. + * If it is in core (in the inode structure), + * honor the locking protocol. + * If it is not in core, read it in from the + * specified device. + * If the inode is mounted on, perform + * the indicated indirection. + * In all cases, a pointer to a locked + * inode structure is returned. + * + * printf warning: no inodes -- if the inode + * structure is full + * panic: no imt -- if the mounted file + * system is not in the mount table. + * "cannot happen" + */ +iget(dev, ino) +{ + register struct inode *p; + register *ip2; + int *ip1; + register struct mount *ip; + +loop: + ip = NULL; + for(p = &inode[0]; p < &inode[NINODE]; p++) { + if(dev==p->i_dev && ino==p->i_number) { + if((p->i_flag&ILOCK) != 0) { + p->i_flag =| IWANT; + sleep(p, PINOD); + goto loop; + } + if((p->i_flag&IMOUNT) != 0) { + for(ip = &mount[0]; ip < &mount[NMOUNT]; ip++) + if(ip->m_inodp == p) { + dev = ip->m_dev; + ino = ROOTINO; + goto loop; + } + panic("no imt"); + } + p->i_count++; + p->i_flag =| ILOCK; + return(p); + } + if(ip==NULL && p->i_count==0) + ip = p; + } + if((p=ip) == NULL) { + printf("Inode table overflow\n"); + u.u_error = ENFILE; + return(NULL); + } + p->i_dev = dev; + p->i_number = ino; + p->i_flag = ILOCK; + p->i_count++; + p->i_lastr = -1; + ip = bread(dev, ldiv(ino+31,16)); + /* + * Check I/O errors + */ + if (ip->b_flags&B_ERROR) { + brelse(ip); + iput(p); + return(NULL); + } + ip1 = ip->b_addr + 32*lrem(ino+31, 16); + ip2 = &p->i_mode; + while(ip2 < &p->i_addr[8]) + *ip2++ = *ip1++; + brelse(ip); + return(p); +} + +/* + * Decrement reference count of + * an inode structure. + * On the last reference, + * write the inode out and if necessary, + * truncate and deallocate the file. + */ +iput(p) +struct inode *p; +{ + register *rp; + + rp = p; + if(rp->i_count == 1) { + rp->i_flag =| ILOCK; + if(rp->i_nlink <= 0) { + itrunc(rp); + rp->i_mode = 0; + ifree(rp->i_dev, rp->i_number); + } + iupdat(rp, time); + prele(rp); + rp->i_flag = 0; + rp->i_number = 0; + } + rp->i_count--; + prele(rp); +} + +/* + * Check accessed and update flags on + * an inode structure. + * If either is on, update the inode + * with the corresponding dates + * set to the argument tm. + */ +iupdat(p, tm) +int *p; +int *tm; +{ + register *ip1, *ip2, *rp; + int *bp, i; + + rp = p; + if((rp->i_flag&(IUPD|IACC)) != 0) { + if(getfs(rp->i_dev)->s_ronly) + return; + i = rp->i_number+31; + bp = bread(rp->i_dev, ldiv(i,16)); + ip1 = bp->b_addr + 32*lrem(i, 16); + ip2 = &rp->i_mode; + while(ip2 < &rp->i_addr[8]) + *ip1++ = *ip2++; + if(rp->i_flag&IACC) { + *ip1++ = time[0]; + *ip1++ = time[1]; + } else + ip1 =+ 2; + if(rp->i_flag&IUPD) { + *ip1++ = *tm++; + *ip1++ = *tm; + } + bwrite(bp); + } +} + +/* + * Free all the disk blocks associated + * with the specified inode structure. + * The blocks of the file are removed + * in reverse order. This FILO + * algorithm will tend to maintain + * a contiguous free list much longer + * than FIFO. + */ +itrunc(ip) +int *ip; +{ + register *rp, *bp, *cp; + int *dp, *ep; + + rp = ip; + if((rp->i_mode&(IFCHR&IFBLK)) != 0) + return; + for(ip = &rp->i_addr[7]; ip >= &rp->i_addr[0]; ip--) + if(*ip) { + if((rp->i_mode&ILARG) != 0) { + bp = bread(rp->i_dev, *ip); + for(cp = bp->b_addr+512; cp >= bp->b_addr; cp--) + if(*cp) { + if(ip == &rp->i_addr[7]) { + dp = bread(rp->i_dev, *cp); + for(ep = dp->b_addr+512; ep >= dp->b_addr; ep--) + if(*ep) + free(rp->i_dev, *ep); + brelse(dp); + } + free(rp->i_dev, *cp); + } + brelse(bp); + } + free(rp->i_dev, *ip); + *ip = 0; + } + rp->i_mode =& ~ILARG; + rp->i_size0 = 0; + rp->i_size1 = 0; + rp->i_flag =| IUPD; +} + +/* + * Make a new file. + */ +maknode(mode) +{ + register *ip; + + ip = ialloc(u.u_pdir->i_dev); + if (ip==NULL) + return(NULL); + ip->i_flag =| IACC|IUPD; + ip->i_mode = mode|IALLOC; + ip->i_nlink = 1; + ip->i_uid = u.u_uid; + ip->i_gid = u.u_gid; + wdir(ip); + return(ip); +} + +/* + * Write a directory entry with + * parameters left as side effects + * to a call to namei. + */ +wdir(ip) +int *ip; +{ + register char *cp1, *cp2; + + u.u_dent.u_ino = ip->i_number; + cp1 = &u.u_dent.u_name[0]; + for(cp2 = &u.u_dbuf[0]; cp2 < &u.u_dbuf[DIRSIZ];) + *cp1++ = *cp2++; + u.u_count = DIRSIZ+2; + u.u_segflg = 1; + u.u_base = &u.u_dent; + writei(u.u_pdir); + iput(u.u_pdir); +} diff --git a/sys/ken/main.c b/sys/ken/main.c new file mode 100644 index 0000000..eb048f7 --- /dev/null +++ b/sys/ken/main.c @@ -0,0 +1,266 @@ +# +#include "../param.h" +#include "../user.h" +#include "../systm.h" +#include "../proc.h" +#include "../text.h" +#include "../inode.h" +#include "../seg.h" + +#define CLOCK1 0177546 +#define CLOCK2 0172540 +/* + * Icode is the octal bootstrap + * program executed in user mode + * to bring up the system. + */ +int icode[] +{ + 0104413, /* sys exec; init; initp */ + 0000014, + 0000010, + 0000777, /* br . */ + 0000014, /* initp: init; 0 */ + 0000000, + 0062457, /* init: */ + 0061564, + 0064457, + 0064556, + 0000164, +}; + +/* + * Initialization code. + * Called from m40.s or m45.s as + * soon as a stack and segmentation + * have been established. + * Functions: + * clear and free user core + * find which clock is configured + * hand craft 0th process + * call all initialization routines + * fork - process 0 to schedule + * - process 1 execute bootstrap + * + * panic: no clock -- neither clock responds + * loop at loc 6 in user mode -- /etc/init + * cannot be executed. + */ +main() +{ + extern schar; + register i, *p; + + /* + * zero and free all of core + */ + + updlock = 0; + i = *ka6 + USIZE; + UISD->r[0] = 077406; + for(;;) { + UISA->r[0] = i; + if(fuibyte(0) < 0) + break; + clearseg(i); + maxmem++; + mfree(coremap, 1, i); + i++; + } + if(cputype == 70) + for(i=0; i<62; i=+2) { + UBMAP->r[i] = i<<12; + UBMAP->r[i+1] = 0; + } + printf("mem = %l\n", maxmem*5/16); + maxmem = min(maxmem, MAXMEM); + mfree(swapmap, nswap, swplo); + + /* + * determine clock + */ + + UISA->r[7] = ka6[1]; /* io segment */ + UISD->r[7] = 077406; + lks = CLOCK1; + if(fuiword(lks) == -1) { + lks = CLOCK2; + if(fuiword(lks) == -1) + panic("no clock"); + } + + /* + * set up system process + */ + + proc[0].p_addr = *ka6; + proc[0].p_size = USIZE; + proc[0].p_stat = SRUN; + proc[0].p_flag =| SLOAD|SSYS; + u.u_procp = &proc[0]; + + /* + * set up 'known' i-nodes + */ + + *lks = 0115; + cinit(); + binit(); + iinit(); + rootdir = iget(rootdev, ROOTINO); + rootdir->i_flag =& ~ILOCK; + u.u_cdir = iget(rootdev, ROOTINO); + u.u_cdir->i_flag =& ~ILOCK; + + /* + * make init process + * enter scheduling loop + * with system process + */ + + if(newproc()) { + expand(USIZE+1); + estabur(0, 1, 0, 0); + copyout(icode, 0, sizeof icode); + /* + * Return goes to loc. 0 of user init + * code just copied out. + */ + return; + } + sched(); +} + +/* + * Load the user hardware segmentation + * registers from the software prototype. + * The software registers must have + * been setup prior by estabur. + */ +sureg() +{ + register *up, *rp, a; + + a = u.u_procp->p_addr; + up = &u.u_uisa[16]; + rp = &UISA->r[16]; + if(cputype == 40) { + up =- 8; + rp =- 8; + } + while(rp > &UISA->r[0]) + *--rp = *--up + a; + if((up=u.u_procp->p_textp) != NULL) + a =- up->x_caddr; + up = &u.u_uisd[16]; + rp = &UISD->r[16]; + if(cputype == 40) { + up =- 8; + rp =- 8; + } + while(rp > &UISD->r[0]) { + *--rp = *--up; + if((*rp & WO) == 0) + rp[(UISA-UISD)/2] =- a; + } +} + +/* + * Set up software prototype segmentation + * registers to implement the 3 pseudo + * text,data,stack segment sizes passed + * as arguments. + * The argument sep specifies if the + * text and data+stack segments are to + * be separated. + */ +estabur(nt, nd, ns, sep) +{ + register a, *ap, *dp; + + if(sep) { + if(cputype == 40) + goto err; + if(nseg(nt) > 8 || nseg(nd)+nseg(ns) > 8) + goto err; + } else + if(nseg(nt)+nseg(nd)+nseg(ns) > 8) + goto err; + if(nt+nd+ns+USIZE > maxmem) + goto err; + a = 0; + ap = &u.u_uisa[0]; + dp = &u.u_uisd[0]; + while(nt >= 128) { + *dp++ = (127<<8) | RO; + *ap++ = a; + a =+ 128; + nt =- 128; + } + if(nt) { + *dp++ = ((nt-1)<<8) | RO; + *ap++ = a; + } + if(sep) + while(ap < &u.u_uisa[8]) { + *ap++ = 0; + *dp++ = 0; + } + a = USIZE; + while(nd >= 128) { + *dp++ = (127<<8) | RW; + *ap++ = a; + a =+ 128; + nd =- 128; + } + if(nd) { + *dp++ = ((nd-1)<<8) | RW; + *ap++ = a; + a =+ nd; + } + while(ap < &u.u_uisa[8]) { + *dp++ = 0; + *ap++ = 0; + } + if(sep) + while(ap < &u.u_uisa[16]) { + *dp++ = 0; + *ap++ = 0; + } + a =+ ns; + while(ns >= 128) { + a =- 128; + ns =- 128; + *--dp = (127<<8) | RW; + *--ap = a; + } + if(ns) { + *--dp = ((128-ns)<<8) | RW | ED; + *--ap = a-128; + } + if(!sep) { + ap = &u.u_uisa[0]; + dp = &u.u_uisa[8]; + while(ap < &u.u_uisa[8]) + *dp++ = *ap++; + ap = &u.u_uisd[0]; + dp = &u.u_uisd[8]; + while(ap < &u.u_uisd[8]) + *dp++ = *ap++; + } + sureg(); + return(0); + +err: + u.u_error = ENOMEM; + return(-1); +} + +/* + * Return the arg/128 rounded up. + */ +nseg(n) +{ + + return((n+127)>>7); +} diff --git a/sys/ken/malloc.c b/sys/ken/malloc.c new file mode 100644 index 0000000..ecc1e92 --- /dev/null +++ b/sys/ken/malloc.c @@ -0,0 +1,87 @@ +# +/* + */ + +/* + * Structure of the coremap and swapmap + * arrays. Consists of non-zero count + * and base address of that many + * contiguous units. + * (The coremap unit is 64 bytes, + * the swapmap unit is 512 bytes) + * The addresses are increasing and + * the list is terminated with the + * first zero count. + */ +struct map +{ + char *m_size; + char *m_addr; +}; + +/* + * Allocate size units from the given + * map. Return the base of the allocated + * space. + * Algorithm is first fit. + */ +malloc(mp, size) +struct map *mp; +{ + register int a; + register struct map *bp; + + for (bp = mp; bp->m_size; bp++) { + if (bp->m_size >= size) { + a = bp->m_addr; + bp->m_addr =+ size; + if ((bp->m_size =- size) == 0) + do { + bp++; + (bp-1)->m_addr = bp->m_addr; + } while ((bp-1)->m_size = bp->m_size); + return(a); + } + } + return(0); +} + +/* + * Free the previously allocated space aa + * of size units into the specified map. + * Sort aa into map and combine on + * one or both ends if possible. + */ +mfree(mp, size, aa) +struct map *mp; +{ + register struct map *bp; + register int t; + register int a; + + a = aa; + for (bp = mp; bp->m_addr<=a && bp->m_size!=0; bp++); + if (bp>mp && (bp-1)->m_addr+(bp-1)->m_size == a) { + (bp-1)->m_size =+ size; + if (a+size == bp->m_addr) { + (bp-1)->m_size =+ bp->m_size; + while (bp->m_size) { + bp++; + (bp-1)->m_addr = bp->m_addr; + (bp-1)->m_size = bp->m_size; + } + } + } else { + if (a+size == bp->m_addr && bp->m_size) { + bp->m_addr =- size; + bp->m_size =+ size; + } else if (size) do { + t = bp->m_addr; + bp->m_addr = a; + a = t; + t = bp->m_size; + bp->m_size = size; + bp++; + } while (size = t); + } +} diff --git a/sys/ken/nami.c b/sys/ken/nami.c new file mode 100644 index 0000000..42a82b1 --- /dev/null +++ b/sys/ken/nami.c @@ -0,0 +1,200 @@ +# +#include "../param.h" +#include "../inode.h" +#include "../user.h" +#include "../systm.h" +#include "../buf.h" + +/* + * Convert a pathname into a pointer to + * an inode. Note that the inode is locked. + * + * func = function called to get next char of name + * &uchar if name is in user space + * &schar if name is in system space + * flag = 0 if name is sought + * 1 if name is to be created + * 2 if name is to be deleted + */ +namei(func, flag) +int (*func)(); +{ + register struct inode *dp; + register c; + register char *cp; + int eo, *bp; + + /* + * If name starts with '/' start from + * root; otherwise start from current dir. + */ + + dp = u.u_cdir; + if((c=(*func)()) == '/') + dp = rootdir; + iget(dp->i_dev, dp->i_number); + while(c == '/') + c = (*func)(); + if(c == '\0' && flag != 0) { + u.u_error = ENOENT; + goto out; + } + +cloop: + /* + * Here dp contains pointer + * to last component matched. + */ + + if(u.u_error) + goto out; + if(c == '\0') + return(dp); + + /* + * If there is another component, + * dp must be a directory and + * must have x permission. + */ + + if((dp->i_mode&IFMT) != IFDIR) { + u.u_error = ENOTDIR; + goto out; + } + if(access(dp, IEXEC)) + goto out; + + /* + * Gather up name into + * users' dir buffer. + */ + + cp = &u.u_dbuf[0]; + while(c!='/' && c!='\0' && u.u_error==0) { + if(cp < &u.u_dbuf[DIRSIZ]) + *cp++ = c; + c = (*func)(); + } + while(cp < &u.u_dbuf[DIRSIZ]) + *cp++ = '\0'; + while(c == '/') + c = (*func)(); + if(u.u_error) + goto out; + + /* + * Set up to search a directory. + */ + + u.u_offset[1] = 0; + u.u_offset[0] = 0; + u.u_segflg = 1; + eo = 0; + u.u_count = ldiv(dp->i_size1, DIRSIZ+2); + bp = NULL; + +eloop: + + /* + * If at the end of the directory, + * the search failed. Report what + * is appropriate as per flag. + */ + + if(u.u_count == 0) { + if(bp != NULL) + brelse(bp); + if(flag==1 && c=='\0') { + if(access(dp, IWRITE)) + goto out; + u.u_pdir = dp; + if(eo) + u.u_offset[1] = eo-DIRSIZ-2; else + dp->i_flag =| IUPD; + return(NULL); + } + u.u_error = ENOENT; + goto out; + } + + /* + * If offset is on a block boundary, + * read the next directory block. + * Release previous if it exists. + */ + + if((u.u_offset[1]&0777) == 0) { + if(bp != NULL) + brelse(bp); + bp = bread(dp->i_dev, + bmap(dp, ldiv(u.u_offset[1], 512))); + } + + /* + * Note first empty directory slot + * in eo for possible creat. + * String compare the directory entry + * and the current component. + * If they do not match, go back to eloop. + */ + + bcopy(bp->b_addr+(u.u_offset[1]&0777), &u.u_dent, (DIRSIZ+2)/2); + u.u_offset[1] =+ DIRSIZ+2; + u.u_count--; + if(u.u_dent.u_ino == 0) { + if(eo == 0) + eo = u.u_offset[1]; + goto eloop; + } + for(cp = &u.u_dbuf[0]; cp < &u.u_dbuf[DIRSIZ]; cp++) + if(*cp != cp[u.u_dent.u_name - u.u_dbuf]) + goto eloop; + + /* + * Here a component matched in a directory. + * If there is more pathname, go back to + * cloop, otherwise return. + */ + + if(bp != NULL) + brelse(bp); + if(flag==2 && c=='\0') { + if(access(dp, IWRITE)) + goto out; + return(dp); + } + bp = dp->i_dev; + iput(dp); + dp = iget(bp, u.u_dent.u_ino); + if(dp == NULL) + return(NULL); + goto cloop; + +out: + iput(dp); + return(NULL); +} + +/* + * Return the next character from the + * kernel string pointed at by dirp. + */ +schar() +{ + + return(*u.u_dirp++ & 0377); +} + +/* + * Return the next character from the + * user string pointed at by dirp. + */ +uchar() +{ + register c; + + c = fubyte(u.u_dirp++); + if(c == -1) + u.u_error = EFAULT; + return(c); +} diff --git a/sys/ken/pipe.c b/sys/ken/pipe.c new file mode 100644 index 0000000..1bb432e --- /dev/null +++ b/sys/ken/pipe.c @@ -0,0 +1,222 @@ +# +/* + */ + +#include "../param.h" +#include "../systm.h" +#include "../user.h" +#include "../inode.h" +#include "../file.h" +#include "../reg.h" + +/* + * Max allowable buffering per pipe. + * This is also the max size of the + * file created to implement the pipe. + * If this size is bigger than 4096, + * pipes will be implemented in LARG + * files, which is probably not good. + */ +#define PIPSIZ 4096 + +/* + * The sys-pipe entry. + * Allocate an inode on the root device. + * Allocate 2 file structures. + * Put it all together with flags. + */ +pipe() +{ + register *ip, *rf, *wf; + int r; + + ip = ialloc(rootdev); + if(ip == NULL) + return; + rf = falloc(); + if(rf == NULL) { + iput(ip); + return; + } + r = u.u_ar0[R0]; + wf = falloc(); + if(wf == NULL) { + rf->f_count = 0; + u.u_ofile[r] = NULL; + iput(ip); + return; + } + u.u_ar0[R1] = u.u_ar0[R0]; + u.u_ar0[R0] = r; + wf->f_flag = FWRITE|FPIPE; + wf->f_inode = ip; + rf->f_flag = FREAD|FPIPE; + rf->f_inode = ip; + ip->i_count = 2; + ip->i_flag = IACC|IUPD; + ip->i_mode = IALLOC; +} + +/* + * Read call directed to a pipe. + */ +readp(fp) +int *fp; +{ + register *rp, *ip; + + rp = fp; + ip = rp->f_inode; + +loop: + /* + * Very conservative locking. + */ + + plock(ip); + + /* + * If the head (read) has caught up with + * the tail (write), reset both to 0. + */ + + if(rp->f_offset[1] == ip->i_size1) { + if(rp->f_offset[1] != 0) { + rp->f_offset[1] = 0; + ip->i_size1 = 0; + if(ip->i_mode&IWRITE) { + ip->i_mode =& ~IWRITE; + wakeup(ip+1); + } + } + + /* + * If there are not both reader and + * writer active, return without + * satisfying read. + */ + + prele(ip); + if(ip->i_count < 2) + return; + ip->i_mode =| IREAD; + sleep(ip+2, PPIPE); + goto loop; + } + + /* + * Read and return + */ + + u.u_offset[0] = 0; + u.u_offset[1] = rp->f_offset[1]; + readi(ip); + rp->f_offset[1] = u.u_offset[1]; + prele(ip); +} + +/* + * Write call directed to a pipe. + */ +writep(fp) +{ + register *rp, *ip, c; + + rp = fp; + ip = rp->f_inode; + c = u.u_count; + +loop: + + /* + * If all done, return. + */ + + plock(ip); + if(c == 0) { + prele(ip); + u.u_count = 0; + return; + } + + /* + * If there are not both read and + * write sides of the pipe active, + * return error and signal too. + */ + + if(ip->i_count < 2) { + prele(ip); + u.u_error = EPIPE; + psignal(u.u_procp, SIGPIPE); + return; + } + + /* + * If the pipe is full, + * wait for reads to deplete + * and truncate it. + */ + + if(ip->i_size1 == PIPSIZ) { + ip->i_mode =| IWRITE; + prele(ip); + sleep(ip+1, PPIPE); + goto loop; + } + + /* + * Write what is possible and + * loop back. + */ + + u.u_offset[0] = 0; + u.u_offset[1] = ip->i_size1; + u.u_count = min(c, PIPSIZ-u.u_offset[1]); + c =- u.u_count; + writei(ip); + prele(ip); + if(ip->i_mode&IREAD) { + ip->i_mode =& ~IREAD; + wakeup(ip+2); + } + goto loop; +} + +/* + * Lock a pipe. + * If its already locked, + * set the WANT bit and sleep. + */ +plock(ip) +int *ip; +{ + register *rp; + + rp = ip; + while(rp->i_flag&ILOCK) { + rp->i_flag =| IWANT; + sleep(rp, PPIPE); + } + rp->i_flag =| ILOCK; +} + +/* + * Unlock a pipe. + * If WANT bit is on, + * wakeup. + * This routine is also used + * to unlock inodes in general. + */ +prele(ip) +int *ip; +{ + register *rp; + + rp = ip; + rp->i_flag =& ~ILOCK; + if(rp->i_flag&IWANT) { + rp->i_flag =& ~IWANT; + wakeup(rp); + } +} diff --git a/sys/ken/prf.c b/sys/ken/prf.c new file mode 100644 index 0000000..71d661c --- /dev/null +++ b/sys/ken/prf.c @@ -0,0 +1,150 @@ +# +/* + */ + +#include "../param.h" +#include "../seg.h" +#include "../buf.h" +#include "../conf.h" + +/* + * Address and structure of the + * KL-11 console device registers. + */ +struct +{ + int rsr; + int rbr; + int xsr; + int xbr; +}; + +/* + * In case console is off, + * panicstr contains argument to last + * call to panic. + */ + +char *panicstr; + +/* + * Scaled down version of C Library printf. + * Only %s %l %d (==%l) %o are recognized. + * Used to print diagnostic information + * directly on console tty. + * Since it is not interrupt driven, + * all system activities are pretty much + * suspended. + * Printf should not be used for chit-chat. + */ +printf(fmt,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc) +char fmt[]; +{ + register char *s; + register *adx, c; + + adx = &x1; +loop: + while((c = *fmt++) != '%') { + if(c == '\0') + return; + putchar(c); + } + c = *fmt++; + if(c == 'd' || c == 'l' || c == 'o') + printn(*adx, c=='o'? 8: 10); + if(c == 's') { + s = *adx; + while(c = *s++) + putchar(c); + } + adx++; + goto loop; +} + +/* + * Print an unsigned integer in base b. + */ +printn(n, b) +{ + register a; + + if(a = ldiv(n, b)) + printn(a, b); + putchar(lrem(n, b) + '0'); +} + +/* + * Print a character on console. + * Attempts to save and restore device + * status. + * If the switches are 0, all + * printing is inhibited. + */ +putchar(c) +{ + register rc, s; + + rc = c; + if(SW->integ == 0) + return; + while((KL->xsr&0200) == 0) + ; + if(rc == 0) + return; + s = KL->xsr; + KL->xsr = 0; + KL->xbr = rc; + if(rc == '\n') { + putchar('\r'); + putchar(0177); + putchar(0177); + } + putchar(0); + KL->xsr = s; +} + +/* + * Panic is called on unresolvable + * fatal errors. + * It syncs, prints "panic: mesg" and + * then loops. + */ +panic(s) +char *s; +{ + panicstr = s; + update(); + printf("panic: %s\n", s); + for(;;) + idle(); +} + +/* + * prdev prints a warning message of the + * form "mesg on dev x/y". + * x and y are the major and minor parts of + * the device argument. + */ +prdev(str, dev) +{ + + printf("%s on dev %l/%l\n", str, dev.d_major, dev.d_minor); +} + +/* + * deverr prints a diagnostic from + * a device driver. + * It prints the device, block number, + * and an octal word (usually some error + * status register) passed as argument. + */ +deverror(bp, o1, o2) +int *bp; +{ + register *rbp; + + rbp = bp; + prdev("err", rbp->b_dev); + printf("bn%l er%o %o\n", rbp->b_blkno, o1, o2); +} diff --git a/sys/ken/rdwri.c b/sys/ken/rdwri.c new file mode 100644 index 0000000..7f07f2f --- /dev/null +++ b/sys/ken/rdwri.c @@ -0,0 +1,195 @@ +# +/* + */ + +#include "../param.h" +#include "../inode.h" +#include "../user.h" +#include "../buf.h" +#include "../conf.h" +#include "../systm.h" + +/* + * Read the file corresponding to + * the inode pointed at by the argument. + * The actual read arguments are found + * in the variables: + * u_base core address for destination + * u_offset byte offset in file + * u_count number of bytes to read + * u_segflg read to kernel/user + */ +readi(aip) +struct inode *aip; +{ + int *bp; + int lbn, bn, on; + register dn, n; + register struct inode *ip; + + ip = aip; + if(u.u_count == 0) + return; + ip->i_flag =| IACC; + if((ip->i_mode&IFMT) == IFCHR) { + (*cdevsw[ip->i_addr[0].d_major].d_read)(ip->i_addr[0]); + return; + } + + do { + lbn = bn = lshift(u.u_offset, -9); + on = u.u_offset[1] & 0777; + n = min(512-on, u.u_count); + if((ip->i_mode&IFMT) != IFBLK) { + dn = dpcmp(ip->i_size0&0377, ip->i_size1, + u.u_offset[0], u.u_offset[1]); + if(dn <= 0) + return; + n = min(n, dn); + if ((bn = bmap(ip, lbn)) == 0) + return; + dn = ip->i_dev; + } else { + dn = ip->i_addr[0]; + rablock = bn+1; + } + if (ip->i_lastr+1 == lbn) + bp = breada(dn, bn, rablock); + else + bp = bread(dn, bn); + ip->i_lastr = lbn; + iomove(bp, on, n, B_READ); + brelse(bp); + } while(u.u_error==0 && u.u_count!=0); +} + +/* + * Write the file corresponding to + * the inode pointed at by the argument. + * The actual write arguments are found + * in the variables: + * u_base core address for source + * u_offset byte offset in file + * u_count number of bytes to write + * u_segflg write to kernel/user + */ +writei(aip) +struct inode *aip; +{ + int *bp; + int n, on; + register dn, bn; + register struct inode *ip; + + ip = aip; + ip->i_flag =| IACC|IUPD; + if((ip->i_mode&IFMT) == IFCHR) { + (*cdevsw[ip->i_addr[0].d_major].d_write)(ip->i_addr[0]); + return; + } + if (u.u_count == 0) + return; + + do { + bn = lshift(u.u_offset, -9); + on = u.u_offset[1] & 0777; + n = min(512-on, u.u_count); + if((ip->i_mode&IFMT) != IFBLK) { + if ((bn = bmap(ip, bn)) == 0) + return; + dn = ip->i_dev; + } else + dn = ip->i_addr[0]; + if(n == 512) + bp = getblk(dn, bn); else + bp = bread(dn, bn); + iomove(bp, on, n, B_WRITE); + if(u.u_error != 0) + brelse(bp); else + if ((u.u_offset[1]&0777)==0) + bawrite(bp); else + bdwrite(bp); + if(dpcmp(ip->i_size0&0377, ip->i_size1, + u.u_offset[0], u.u_offset[1]) < 0 && + (ip->i_mode&(IFBLK&IFCHR)) == 0) { + ip->i_size0 = u.u_offset[0]; + ip->i_size1 = u.u_offset[1]; + } + ip->i_flag =| IUPD; + } while(u.u_error==0 && u.u_count!=0); +} + +/* + * Return the logical maximum + * of the 2 arguments. + */ +max(a, b) +char *a, *b; +{ + + if(a > b) + return(a); + return(b); +} + +/* + * Return the logical minimum + * of the 2 arguments. + */ +min(a, b) +char *a, *b; +{ + + if(a < b) + return(a); + return(b); +} + +/* + * Move 'an' bytes at byte location + * &bp->b_addr[o] to/from (flag) the + * user/kernel (u.segflg) area starting at u.base. + * Update all the arguments by the number + * of bytes moved. + * + * There are 2 algorithms, + * if source address, dest address and count + * are all even in a user copy, + * then the machine language copyin/copyout + * is called. + * If not, its done byte-by-byte with + * cpass and passc. + */ +iomove(bp, o, an, flag) +struct buf *bp; +{ + register char *cp; + register int n, t; + + n = an; + cp = bp->b_addr + o; + if(u.u_segflg==0 && ((n | cp | u.u_base)&01)==0) { + if (flag==B_WRITE) + cp = copyin(u.u_base, cp, n); + else + cp = copyout(cp, u.u_base, n); + if (cp) { + u.u_error = EFAULT; + return; + } + u.u_base =+ n; + dpadd(u.u_offset, n); + u.u_count =- n; + return; + } + if (flag==B_WRITE) { + while(n--) { + if ((t = cpass()) < 0) + return; + *cp++ = t; + } + } else + while (n--) + if(passc(*cp++) < 0) + return; +} diff --git a/sys/ken/sig.c b/sys/ken/sig.c new file mode 100644 index 0000000..04ebf46 --- /dev/null +++ b/sys/ken/sig.c @@ -0,0 +1,374 @@ +# +/* + */ + +#include "../param.h" +#include "../systm.h" +#include "../user.h" +#include "../proc.h" +#include "../inode.h" +#include "../reg.h" + +/* + * Priority for tracing + */ +#define IPCPRI (-1) + +/* + * Structure to access an array of integers. + */ +struct +{ + int inta[]; +}; + +/* + * Tracing variables. + * Used to pass trace command from + * parent to child being traced. + * This data base cannot be + * shared and is locked + * per user. + */ +struct +{ + int ip_lock; + int ip_req; + int ip_addr; + int ip_data; +} ipc; + +/* + * Send the specified signal to + * all processes with 'tp' as its + * controlling teletype. + * Called by tty.c for quits and + * interrupts. + */ +signal(tp, sig) +{ + register struct proc *p; + + for(p = &proc[0]; p < &proc[NPROC]; p++) + if(p->p_ttyp == tp) + psignal(p, sig); +} + +/* + * Send the specified signal to + * the specified process. + */ +psignal(p, sig) +int *p; +{ + register *rp; + + if(sig >= NSIG) + return; + rp = p; + if(rp->p_sig != SIGKIL) + rp->p_sig = sig; + if(rp->p_stat > PUSER) + rp->p_stat = PUSER; + if(rp->p_stat == SWAIT) + setrun(rp); +} + +/* + * Returns true if the current + * process has a signal to process. + * This is asked at least once + * each time a process enters the + * system. + * A signal does not do anything + * directly to a process; it sets + * a flag that asks the process to + * do something to itself. + */ +issig() +{ + register n; + register struct proc *p; + + p = u.u_procp; + if(n = p->p_sig) { + if (p->p_flag&STRC) { + stop(); + if ((n = p->p_sig) == 0) + return(0); + } + if((u.u_signal[n]&1) == 0) + return(n); + } + return(0); +} + +/* + * Enter the tracing STOP state. + * In this state, the parent is + * informed and the process is able to + * receive commands from the parent. + */ +stop() +{ + register struct proc *pp, *cp; + +loop: + cp = u.u_procp; + if(cp->p_ppid != 1) + for (pp = &proc[0]; pp < &proc[NPROC]; pp++) + if (pp->p_pid == cp->p_ppid) { + wakeup(pp); + cp->p_stat = SSTOP; + swtch(); + if ((cp->p_flag&STRC)==0 || procxmt()) + return; + goto loop; + } + exit(); +} + +/* + * Perform the action specified by + * the current signal. + * The usual sequence is: + * if(issig()) + * psig(); + */ +psig() +{ + register n, p; + register *rp; + + rp = u.u_procp; + n = rp->p_sig; + rp->p_sig = 0; + if((p=u.u_signal[n]) != 0) { + u.u_error = 0; + if(n != SIGINS && n != SIGTRC) + u.u_signal[n] = 0; + n = u.u_ar0[R6] - 4; + grow(n); + suword(n+2, u.u_ar0[RPS]); + suword(n, u.u_ar0[R7]); + u.u_ar0[R6] = n; + u.u_ar0[RPS] =& ~TBIT; + u.u_ar0[R7] = p; + return; + } + switch(n) { + + case SIGQIT: + case SIGINS: + case SIGTRC: + case SIGIOT: + case SIGEMT: + case SIGFPT: + case SIGBUS: + case SIGSEG: + case SIGSYS: + u.u_arg[0] = n; + if(core()) + n =+ 0200; + } + u.u_arg[0] = (u.u_ar0[R0]<<8) | n; + exit(); +} + +/* + * Create a core image on the file "core" + * If you are looking for protection glitches, + * there are probably a wealth of them here + * when this occurs to a suid command. + * + * It writes USIZE block of the + * user.h area followed by the entire + * data+stack segments. + */ +core() +{ + register s, *ip; + extern schar; + + u.u_error = 0; + u.u_dirp = "core"; + ip = namei(&schar, 1); + if(ip == NULL) { + if(u.u_error) + return(0); + ip = maknode(0666); + if(ip == NULL) + return(0); + } + if(!access(ip, IWRITE) && + (ip->i_mode&IFMT) == 0 && + u.u_uid == u.u_ruid) { + itrunc(ip); + u.u_offset[0] = 0; + u.u_offset[1] = 0; + u.u_base = &u; + u.u_count = USIZE*64; + u.u_segflg = 1; + writei(ip); + s = u.u_procp->p_size - USIZE; + estabur(0, s, 0, 0); + u.u_base = 0; + u.u_count = s*64; + u.u_segflg = 0; + writei(ip); + } + iput(ip); + return(u.u_error==0); +} + +/* + * grow the stack to include the SP + * true return if successful. + */ + +grow(sp) +char *sp; +{ + register a, si, i; + + if(sp >= -u.u_ssize*64) + return(0); + si = ldiv(-sp, 64) - u.u_ssize + SINCR; + if(si <= 0) + return(0); + if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep)) + return(0); + expand(u.u_procp->p_size+si); + a = u.u_procp->p_addr + u.u_procp->p_size; + for(i=u.u_ssize; i; i--) { + a--; + copyseg(a-si, a); + } + for(i=si; i; i--) + clearseg(--a); + u.u_ssize =+ si; + return(1); +} + +/* + * sys-trace system call. + */ +ptrace() +{ + register struct proc *p; + + if (u.u_arg[2] <= 0) { + u.u_procp->p_flag =| STRC; + return; + } + for (p=proc; p < &proc[NPROC]; p++) + if (p->p_stat==SSTOP + && p->p_pid==u.u_arg[0] + && p->p_ppid==u.u_procp->p_pid) + goto found; + u.u_error = ESRCH; + return; + + found: + while (ipc.ip_lock) + sleep(&ipc, IPCPRI); + ipc.ip_lock = p->p_pid; + ipc.ip_data = u.u_ar0[R0]; + ipc.ip_addr = u.u_arg[1] & ~01; + ipc.ip_req = u.u_arg[2]; + p->p_flag =& ~SWTED; + setrun(p); + while (ipc.ip_req > 0) + sleep(&ipc, IPCPRI); + u.u_ar0[R0] = ipc.ip_data; + if (ipc.ip_req < 0) + u.u_error = EIO; + ipc.ip_lock = 0; + wakeup(&ipc); +} + +/* + * Code that the child process + * executes to implement the command + * of the parent process in tracing. + */ +procxmt() +{ + register int i; + register int *p; + + if (ipc.ip_lock != u.u_procp->p_pid) + return(0); + i = ipc.ip_req; + ipc.ip_req = 0; + wakeup(&ipc); + switch (i) { + + /* read user I */ + case 1: + if (fuibyte(ipc.ip_addr) == -1) + goto error; + ipc.ip_data = fuiword(ipc.ip_addr); + break; + + /* read user D */ + case 2: + if (fubyte(ipc.ip_addr) == -1) + goto error; + ipc.ip_data = fuword(ipc.ip_addr); + break; + + /* read u */ + case 3: + i = ipc.ip_addr; + if (i<0 || i >= (USIZE<<6)) + goto error; + ipc.ip_data = u.inta[i>>1]; + break; + + /* write user I (for now, always an error) */ + case 4: + if (suiword(ipc.ip_addr, 0) < 0) + goto error; + suiword(ipc.ip_addr, ipc.ip_data); + break; + + /* write user D */ + case 5: + if (suword(ipc.ip_addr, 0) < 0) + goto error; + suword(ipc.ip_addr, ipc.ip_data); + break; + + /* write u */ + case 6: + p = &u.inta[ipc.ip_addr>>1]; + if (p >= u.u_fsav && p < &u.u_fsav[25]) + goto ok; + for (i=0; i<9; i++) + if (p == &u.u_ar0[regloc[i]]) + goto ok; + goto error; + ok: + if (p == &u.u_ar0[RPS]) { + ipc.ip_data =| 0170000; /* assure user space */ + ipc.ip_data =& ~0340; /* priority 0 */ + } + *p = ipc.ip_data; + break; + + /* set signal and continue */ + case 7: + u.u_procp->p_sig = ipc.ip_data; + return(1); + + /* force exit */ + case 8: + exit(); + + default: + error: + ipc.ip_req = -1; + } + return(0); +} diff --git a/sys/ken/slp.c b/sys/ken/slp.c new file mode 100644 index 0000000..14f60eb --- /dev/null +++ b/sys/ken/slp.c @@ -0,0 +1,490 @@ +# +/* + */ + +#include "../param.h" +#include "../user.h" +#include "../proc.h" +#include "../text.h" +#include "../systm.h" +#include "../file.h" +#include "../inode.h" +#include "../buf.h" + +/* + * Give up the processor till a wakeup occurs + * on chan, at which time the process + * enters the scheduling queue at priority pri. + * The most important effect of pri is that when + * pri<0 a signal cannot disturb the sleep; + * if pri>=0 signals will be processed. + * Callers of this routine must be prepared for + * premature return, and check that the reason for + * sleeping has gone away. + */ +sleep(chan, pri) +{ + register *rp, s; + + s = PS->integ; + rp = u.u_procp; + if(pri >= 0) { + if(issig()) + goto psig; + spl6(); + rp->p_wchan = chan; + rp->p_stat = SWAIT; + rp->p_pri = pri; + spl0(); + if(runin != 0) { + runin = 0; + wakeup(&runin); + } + swtch(); + if(issig()) + goto psig; + } else { + spl6(); + rp->p_wchan = chan; + rp->p_stat = SSLEEP; + rp->p_pri = pri; + spl0(); + swtch(); + } + PS->integ = s; + return; + + /* + * If priority was low (>=0) and + * there has been a signal, + * execute non-local goto to + * the qsav location. + * (see trap1/trap.c) + */ +psig: + aretu(u.u_qsav); +} + +/* + * Wake up all processes sleeping on chan. + */ +wakeup(chan) +{ + register struct proc *p; + register c, i; + + c = chan; + p = &proc[0]; + i = NPROC; + do { + if(p->p_wchan == c) { + setrun(p); + } + p++; + } while(--i); +} + +/* + * Set the process running; + * arrange for it to be swapped in if necessary. + */ +setrun(p) +{ + register struct proc *rp; + + rp = p; + rp->p_wchan = 0; + rp->p_stat = SRUN; + if(rp->p_pri < curpri) + runrun++; + if(runout != 0 && (rp->p_flag&SLOAD) == 0) { + runout = 0; + wakeup(&runout); + } +} + +/* + * Set user priority. + * The rescheduling flag (runrun) + * is set if the priority is higher + * than the currently running process. + */ +setpri(up) +{ + register *pp, p; + + pp = up; + p = (pp->p_cpu & 0377)/16; + p =+ PUSER + pp->p_nice; + if(p > 127) + p = 127; + if(p > curpri) + runrun++; + pp->p_pri = p; +} + +/* + * The main loop of the scheduling (swapping) + * process. + * The basic idea is: + * see if anyone wants to be swapped in; + * swap out processes until there is room; + * swap him in; + * repeat. + * Although it is not remarkably evident, the basic + * synchronization here is on the runin flag, which is + * slept on and is set once per second by the clock routine. + * Core shuffling therefore takes place once per second. + * + * panic: swap error -- IO error while swapping. + * this is the one panic that should be + * handled in a less drastic way. Its + * very hard. + */ +sched() +{ + struct proc *p1; + register struct proc *rp; + register a, n; + + /* + * find user to swap in + * of users ready, select one out longest + */ + + goto loop; + +sloop: + runin++; + sleep(&runin, PSWP); + +loop: + spl6(); + n = -1; + for(rp = &proc[0]; rp < &proc[NPROC]; rp++) + if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 && + rp->p_time > n) { + p1 = rp; + n = rp->p_time; + } + if(n == -1) { + runout++; + sleep(&runout, PSWP); + goto loop; + } + + /* + * see if there is core for that process + */ + + spl0(); + rp = p1; + a = rp->p_size; + if((rp=rp->p_textp) != NULL) + if(rp->x_ccount == 0) + a =+ rp->x_size; + if((a=malloc(coremap, a)) != NULL) + goto found2; + + /* + * none found, + * look around for easy core + */ + + spl6(); + for(rp = &proc[0]; rp < &proc[NPROC]; rp++) + if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD && + (rp->p_stat == SWAIT || rp->p_stat==SSTOP)) + goto found1; + + /* + * no easy core, + * if this process is deserving, + * look around for + * oldest process in core + */ + + if(n < 3) + goto sloop; + n = -1; + for(rp = &proc[0]; rp < &proc[NPROC]; rp++) + if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD && + (rp->p_stat==SRUN || rp->p_stat==SSLEEP) && + rp->p_time > n) { + p1 = rp; + n = rp->p_time; + } + if(n < 2) + goto sloop; + rp = p1; + + /* + * swap user out + */ + +found1: + spl0(); + rp->p_flag =& ~SLOAD; + xswap(rp, 1, 0); + goto loop; + + /* + * swap user in + */ + +found2: + if((rp=p1->p_textp) != NULL) { + if(rp->x_ccount == 0) { + if(swap(rp->x_daddr, a, rp->x_size, B_READ)) + goto swaper; + rp->x_caddr = a; + a =+ rp->x_size; + } + rp->x_ccount++; + } + rp = p1; + if(swap(rp->p_addr, a, rp->p_size, B_READ)) + goto swaper; + mfree(swapmap, (rp->p_size+7)/8, rp->p_addr); + rp->p_addr = a; + rp->p_flag =| SLOAD; + rp->p_time = 0; + goto loop; + +swaper: + panic("swap error"); +} + +/* + * This routine is called to reschedule the CPU. + * if the calling process is not in RUN state, + * arrangements for it to restart must have + * been made elsewhere, usually by calling via sleep. + */ +swtch() +{ + static struct proc *p; + register i, n; + register struct proc *rp; + + if(p == NULL) + p = &proc[0]; + /* + * Remember stack of caller + */ + savu(u.u_rsav); + /* + * Switch to scheduler's stack + */ + retu(proc[0].p_addr); + +loop: + runrun = 0; + rp = p; + p = NULL; + n = 128; + /* + * Search for highest-priority runnable process + */ + i = NPROC; + do { + rp++; + if(rp >= &proc[NPROC]) + rp = &proc[0]; + if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) { + if(rp->p_pri < n) { + p = rp; + n = rp->p_pri; + } + } + } while(--i); + /* + * If no process is runnable, idle. + */ + if(p == NULL) { + p = rp; + idle(); + goto loop; + } + rp = p; + curpri = n; + /* + * Switch to stack of the new process and set up + * his segmentation registers. + */ + retu(rp->p_addr); + sureg(); + /* + * If the new process paused because it was + * swapped out, set the stack level to the last call + * to savu(u_ssav). This means that the return + * which is executed immediately after the call to aretu + * actually returns from the last routine which did + * the savu. + * + * You are not expected to understand this. + */ + if(rp->p_flag&SSWAP) { + rp->p_flag =& ~SSWAP; + aretu(u.u_ssav); + } + /* + * The value returned here has many subtle implications. + * See the newproc comments. + */ + return(1); +} + +/* + * Create a new process-- the internal version of + * sys fork. + * It returns 1 in the new process. + * How this happens is rather hard to understand. + * The essential fact is that the new process is created + * in such a way that appears to have started executing + * in the same call to newproc as the parent; + * but in fact the code that runs is that of swtch. + * The subtle implication of the returned value of swtch + * (see above) is that this is the value that newproc's + * caller in the new process sees. + */ +newproc() +{ + int a1, a2; + struct proc *p, *up; + register struct proc *rpp; + register *rip, n; + + p = NULL; + /* + * First, just locate a slot for a process + * and copy the useful info from this process into it. + * The panic "cannot happen" because fork has already + * checked for the existence of a slot. + */ +retry: + mpid++; + if(mpid < 0) { + mpid = 0; + goto retry; + } + for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) { + if(rpp->p_stat == NULL && p==NULL) + p = rpp; + if (rpp->p_pid==mpid) + goto retry; + } + if ((rpp = p)==NULL) + panic("no procs"); + + /* + * make proc entry for new proc + */ + + rip = u.u_procp; + up = rip; + rpp->p_stat = SRUN; + rpp->p_flag = SLOAD; + rpp->p_uid = rip->p_uid; + rpp->p_ttyp = rip->p_ttyp; + rpp->p_nice = rip->p_nice; + rpp->p_textp = rip->p_textp; + rpp->p_pid = mpid; + rpp->p_ppid = rip->p_pid; + rpp->p_time = 0; + + /* + * make duplicate entries + * where needed + */ + + for(rip = &u.u_ofile[0]; rip < &u.u_ofile[NOFILE];) + if((rpp = *rip++) != NULL) + rpp->f_count++; + if((rpp=up->p_textp) != NULL) { + rpp->x_count++; + rpp->x_ccount++; + } + u.u_cdir->i_count++; + /* + * Partially simulate the environment + * of the new process so that when it is actually + * created (by copying) it will look right. + */ + savu(u.u_rsav); + rpp = p; + u.u_procp = rpp; + rip = up; + n = rip->p_size; + a1 = rip->p_addr; + rpp->p_size = n; + a2 = malloc(coremap, n); + /* + * If there is not enough core for the + * new process, swap out the current process to generate the + * copy. + */ + if(a2 == NULL) { + rip->p_stat = SIDL; + rpp->p_addr = a1; + savu(u.u_ssav); + xswap(rpp, 0, 0); + rpp->p_flag =| SSWAP; + rip->p_stat = SRUN; + } else { + /* + * There is core, so just copy. + */ + rpp->p_addr = a2; + while(n--) + copyseg(a1++, a2++); + } + u.u_procp = rip; + return(0); +} + +/* + * Change the size of the data+stack regions of the process. + * If the size is shrinking, it's easy-- just release the extra core. + * If it's growing, and there is core, just allocate it + * and copy the image, taking care to reset registers to account + * for the fact that the system's stack has moved. + * If there is no core, arrange for the process to be swapped + * out after adjusting the size requirement-- when it comes + * in, enough core will be allocated. + * Because of the ssave and SSWAP flags, control will + * resume after the swap in swtch, which executes the return + * from this stack level. + * + * After the expansion, the caller will take care of copying + * the user's stack towards or away from the data area. + */ +expand(newsize) +{ + int i, n; + register *p, a1, a2; + + p = u.u_procp; + n = p->p_size; + p->p_size = newsize; + a1 = p->p_addr; + if(n >= newsize) { + mfree(coremap, n-newsize, a1+newsize); + return; + } + savu(u.u_rsav); + a2 = malloc(coremap, newsize); + if(a2 == NULL) { + savu(u.u_ssav); + xswap(p, 1, n); + p->p_flag =| SSWAP; + swtch(); + /* no return */ + } + p->p_addr = a2; + for(i=0; ip_addr); + sureg(); +} diff --git a/sys/ken/subr.c b/sys/ken/subr.c new file mode 100644 index 0000000..ee79a50 --- /dev/null +++ b/sys/ken/subr.c @@ -0,0 +1,207 @@ +# +/* + */ + +#include "../param.h" +#include "../conf.h" +#include "../inode.h" +#include "../user.h" +#include "../buf.h" +#include "../systm.h" + +/* + * Bmap defines the structure of file system storage + * by returning the physical block number on a device given the + * inode and the logical block number in a file. + * When convenient, it also leaves the physical + * block number of the next block of the file in rablock + * for use in read-ahead. + */ +bmap(ip, bn) +struct inode *ip; +int bn; +{ + register *bp, *bap, nb; + int *nbp, d, i; + + d = ip->i_dev; + if(bn & ~077777) { + u.u_error = EFBIG; + return(0); + } + + if((ip->i_mode&ILARG) == 0) { + + /* + * small file algorithm + */ + + if((bn & ~7) != 0) { + + /* + * convert small to large + */ + + if ((bp = alloc(d)) == NULL) + return(NULL); + bap = bp->b_addr; + for(i=0; i<8; i++) { + *bap++ = ip->i_addr[i]; + ip->i_addr[i] = 0; + } + ip->i_addr[0] = bp->b_blkno; + bdwrite(bp); + ip->i_mode =| ILARG; + goto large; + } + nb = ip->i_addr[bn]; + if(nb == 0 && (bp = alloc(d)) != NULL) { + bdwrite(bp); + nb = bp->b_blkno; + ip->i_addr[bn] = nb; + ip->i_flag =| IUPD; + } + rablock = 0; + if (bn<7) + rablock = ip->i_addr[bn+1]; + return(nb); + } + + /* + * large file algorithm + */ + + large: + i = bn>>8; + if(bn & 0174000) + i = 7; + if((nb=ip->i_addr[i]) == 0) { + ip->i_flag =| IUPD; + if ((bp = alloc(d)) == NULL) + return(NULL); + ip->i_addr[i] = bp->b_blkno; + } else + bp = bread(d, nb); + bap = bp->b_addr; + + /* + * "huge" fetch of double indirect block + */ + + if(i == 7) { + i = ((bn>>8) & 0377) - 7; + if((nb=bap[i]) == 0) { + if((nbp = alloc(d)) == NULL) { + brelse(bp); + return(NULL); + } + bap[i] = nbp->b_blkno; + bdwrite(bp); + } else { + brelse(bp); + nbp = bread(d, nb); + } + bp = nbp; + bap = bp->b_addr; + } + + /* + * normal indirect fetch + */ + + i = bn & 0377; + if((nb=bap[i]) == 0 && (nbp = alloc(d)) != NULL) { + nb = nbp->b_blkno; + bap[i] = nb; + bdwrite(nbp); + bdwrite(bp); + } else + brelse(bp); + rablock = 0; + if(i < 255) + rablock = bap[i+1]; + return(nb); +} + +/* + * Pass back c to the user at his location u_base; + * update u_base, u_count, and u_offset. Return -1 + * on the last character of the user's read. + * u_base is in the user address space unless u_segflg is set. + */ +passc(c) +char c; +{ + + if(u.u_segflg) + *u.u_base = c; else + if(subyte(u.u_base, c) < 0) { + u.u_error = EFAULT; + return(-1); + } + u.u_count--; + if(++u.u_offset[1] == 0) + u.u_offset[0]++; + u.u_base++; + return(u.u_count == 0? -1: 0); +} + +/* + * Pick up and return the next character from the user's + * write call at location u_base; + * update u_base, u_count, and u_offset. Return -1 + * when u_count is exhausted. u_base is in the user's + * address space unless u_segflg is set. + */ +cpass() +{ + register c; + + if(u.u_count == 0) + return(-1); + if(u.u_segflg) + c = *u.u_base; else + if((c=fubyte(u.u_base)) < 0) { + u.u_error = EFAULT; + return(-1); + } + u.u_count--; + if(++u.u_offset[1] == 0) + u.u_offset[0]++; + u.u_base++; + return(c&0377); +} + +/* + * Routine which sets a user error; placed in + * illegal entries in the bdevsw and cdevsw tables. + */ +nodev() +{ + + u.u_error = ENODEV; +} + +/* + * Null routine; placed in insignificant entries + * in the bdevsw and cdevsw tables. + */ +nulldev() +{ +} + +/* + * copy count words from from to to. + */ +bcopy(from, to, count) +int *from, *to; +{ + register *a, *b, c; + + a = from; + b = to; + c = count; + do + *b++ = *a++; + while(--c); +} diff --git a/sys/ken/sys1.c b/sys/ken/sys1.c new file mode 100644 index 0000000..e190381 --- /dev/null +++ b/sys/ken/sys1.c @@ -0,0 +1,407 @@ +# +/* + */ + +#include "../param.h" +#include "../systm.h" +#include "../user.h" +#include "../proc.h" +#include "../buf.h" +#include "../reg.h" +#include "../inode.h" + +/* + * exec system call. + * Because of the fact that an I/O buffer is used + * to store the caller's arguments during exec, + * and more buffers are needed to read in the text file, + * deadly embraces waiting for free buffers are possible. + * Therefore the number of processes simultaneously + * running in exec has to be limited to NEXEC. + */ +#define EXPRI -1 + +exec() +{ + int ap, na, nc, *bp; + int ts, ds, sep; + register c, *ip; + register char *cp; + extern uchar; + + /* + * pick up file names + * and check various modes + * for execute permission + */ + + ip = namei(&uchar, 0); + if(ip == NULL) + return; + while(execnt >= NEXEC) + sleep(&execnt, EXPRI); + execnt++; + bp = getblk(NODEV); + if(access(ip, IEXEC) || (ip->i_mode&IFMT)!=0) + goto bad; + + /* + * pack up arguments into + * allocated disk buffer + */ + + cp = bp->b_addr; + na = 0; + nc = 0; + while(ap = fuword(u.u_arg[1])) { + na++; + if(ap == -1) + goto bad; + u.u_arg[1] =+ 2; + for(;;) { + c = fubyte(ap++); + if(c == -1) + goto bad; + *cp++ = c; + nc++; + if(nc > 510) { + u.u_error = E2BIG; + goto bad; + } + if(c == 0) + break; + } + } + if((nc&1) != 0) { + *cp++ = 0; + nc++; + } + + /* + * read in first 8 bytes + * of file for segment + * sizes: + * w0 = 407/410/411 (410 implies RO text) (411 implies sep ID) + * w1 = text size + * w2 = data size + * w3 = bss size + */ + + u.u_base = &u.u_arg[0]; + u.u_count = 8; + u.u_offset[1] = 0; + u.u_offset[0] = 0; + u.u_segflg = 1; + readi(ip); + u.u_segflg = 0; + if(u.u_error) + goto bad; + sep = 0; + if(u.u_arg[0] == 0407) { + u.u_arg[2] =+ u.u_arg[1]; + u.u_arg[1] = 0; + } else + if(u.u_arg[0] == 0411) + sep++; else + if(u.u_arg[0] != 0410) { + u.u_error = ENOEXEC; + goto bad; + } + if(u.u_arg[1]!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { + u.u_error = ETXTBSY; + goto bad; + } + + /* + * find text and data sizes + * try them out for possible + * exceed of max sizes + */ + + ts = ((u.u_arg[1]+63)>>6) & 01777; + ds = ((u.u_arg[2]+u.u_arg[3]+63)>>6) & 01777; + if(estabur(ts, ds, SSIZE, sep)) + goto bad; + + /* + * allocate and clear core + * at this point, committed + * to the new image + */ + + u.u_prof[3] = 0; + xfree(); + expand(USIZE); + xalloc(ip); + c = USIZE+ds+SSIZE; + expand(c); + while(--c >= USIZE) + clearseg(u.u_procp->p_addr+c); + + /* + * read in data segment + */ + + estabur(0, ds, 0, 0); + u.u_base = 0; + u.u_offset[1] = 020+u.u_arg[1]; + u.u_count = u.u_arg[2]; + readi(ip); + + /* + * initialize stack segment + */ + + u.u_tsize = ts; + u.u_dsize = ds; + u.u_ssize = SSIZE; + u.u_sep = sep; + estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep); + cp = bp->b_addr; + ap = -nc - na*2 - 4; + u.u_ar0[R6] = ap; + suword(ap, na); + c = -nc; + while(na--) { + suword(ap=+2, c); + do + subyte(c++, *cp); + while(*cp++); + } + suword(ap+2, -1); + + /* + * set SUID/SGID protections, if no tracing + */ + + if ((u.u_procp->p_flag&STRC)==0) { + if(ip->i_mode&ISUID) + if(u.u_uid != 0) { + u.u_uid = ip->i_uid; + u.u_procp->p_uid = ip->i_uid; + } + if(ip->i_mode&ISGID) + u.u_gid = ip->i_gid; + } + + /* + * clear sigs, regs and return + */ + + c = ip; + for(ip = &u.u_signal[0]; ip < &u.u_signal[NSIG]; ip++) + if((*ip & 1) == 0) + *ip = 0; + for(cp = ®loc[0]; cp < ®loc[6];) + u.u_ar0[*cp++] = 0; + u.u_ar0[R7] = 0; + for(ip = &u.u_fsav[0]; ip < &u.u_fsav[25];) + *ip++ = 0; + ip = c; + +bad: + iput(ip); + brelse(bp); + if(execnt >= NEXEC) + wakeup(&execnt); + execnt--; +} + +/* + * exit system call: + * pass back caller's r0 + */ +rexit() +{ + + u.u_arg[0] = u.u_ar0[R0] << 8; + exit(); +} + +/* + * Release resources. + * Save u. area for parent to look at. + * Enter zombie state. + * Wake up parent and init processes, + * and dispose of children. + */ +exit() +{ + register int *q, a; + register struct proc *p; + + u.u_procp->p_flag =& ~STRC; + for(q = &u.u_signal[0]; q < &u.u_signal[NSIG];) + *q++ = 1; + for(q = &u.u_ofile[0]; q < &u.u_ofile[NOFILE]; q++) + if(a = *q) { + *q = NULL; + closef(a); + } + iput(u.u_cdir); + xfree(); + a = malloc(swapmap, 1); + if(a == NULL) + panic("out of swap"); + p = getblk(swapdev, a); + bcopy(&u, p->b_addr, 256); + bwrite(p); + q = u.u_procp; + mfree(coremap, q->p_size, q->p_addr); + q->p_addr = a; + q->p_stat = SZOMB; + +loop: + for(p = &proc[0]; p < &proc[NPROC]; p++) + if(q->p_ppid == p->p_pid) { + wakeup(&proc[1]); + wakeup(p); + for(p = &proc[0]; p < &proc[NPROC]; p++) + if(q->p_pid == p->p_ppid) { + p->p_ppid = 1; + if (p->p_stat == SSTOP) + setrun(p); + } + swtch(); + /* no return */ + } + q->p_ppid = 1; + goto loop; +} + +/* + * Wait system call. + * Search for a terminated (zombie) child, + * finally lay it to rest, and collect its status. + * Look also for stopped (traced) children, + * and pass back status from them. + */ +wait() +{ + register f, *bp; + register struct proc *p; + + f = 0; + +loop: + for(p = &proc[0]; p < &proc[NPROC]; p++) + if(p->p_ppid == u.u_procp->p_pid) { + f++; + if(p->p_stat == SZOMB) { + u.u_ar0[R0] = p->p_pid; + bp = bread(swapdev, f=p->p_addr); + mfree(swapmap, 1, f); + p->p_stat = NULL; + p->p_pid = 0; + p->p_ppid = 0; + p->p_sig = 0; + p->p_ttyp = 0; + p->p_flag = 0; + p = bp->b_addr; + u.u_cstime[0] =+ p->u_cstime[0]; + dpadd(u.u_cstime, p->u_cstime[1]); + dpadd(u.u_cstime, p->u_stime); + u.u_cutime[0] =+ p->u_cutime[0]; + dpadd(u.u_cutime, p->u_cutime[1]); + dpadd(u.u_cutime, p->u_utime); + u.u_ar0[R1] = p->u_arg[0]; + brelse(bp); + return; + } + if(p->p_stat == SSTOP) { + if((p->p_flag&SWTED) == 0) { + p->p_flag =| SWTED; + u.u_ar0[R0] = p->p_pid; + u.u_ar0[R1] = (p->p_sig<<8) | 0177; + return; + } + p->p_flag =& ~(STRC|SWTED); + setrun(p); + } + } + if(f) { + sleep(u.u_procp, PWAIT); + goto loop; + } + u.u_error = ECHILD; +} + +/* + * fork system call. + */ +fork() +{ + register struct proc *p1, *p2; + + p1 = u.u_procp; + for(p2 = &proc[0]; p2 < &proc[NPROC]; p2++) + if(p2->p_stat == NULL) + goto found; + u.u_error = EAGAIN; + goto out; + +found: + if(newproc()) { + u.u_ar0[R0] = p1->p_pid; + u.u_cstime[0] = 0; + u.u_cstime[1] = 0; + u.u_stime = 0; + u.u_cutime[0] = 0; + u.u_cutime[1] = 0; + u.u_utime = 0; + return; + } + u.u_ar0[R0] = p2->p_pid; + +out: + u.u_ar0[R7] =+ 2; +} + +/* + * break system call. + * -- bad planning: "break" is a dirty word in C. + */ +sbreak() +{ + register a, n, d; + int i; + + /* + * set n to new data size + * set d to new-old + * set n to new total size + */ + + n = (((u.u_arg[0]+63)>>6) & 01777); + if(!u.u_sep) + n =- nseg(u.u_tsize) * 128; + if(n < 0) + n = 0; + d = n - u.u_dsize; + n =+ USIZE+u.u_ssize; + if(estabur(u.u_tsize, u.u_dsize+d, u.u_ssize, u.u_sep)) + return; + u.u_dsize =+ d; + if(d > 0) + goto bigger; + a = u.u_procp->p_addr + n - u.u_ssize; + i = n; + n = u.u_ssize; + while(n--) { + copyseg(a-d, a); + a++; + } + expand(i); + return; + +bigger: + expand(n); + a = u.u_procp->p_addr + n; + n = u.u_ssize; + while(n--) { + a--; + copyseg(a-d, a); + } + while(d--) + clearseg(--a); +} diff --git a/sys/ken/sys2.c b/sys/ken/sys2.c new file mode 100644 index 0000000..6a5c381 --- /dev/null +++ b/sys/ken/sys2.c @@ -0,0 +1,289 @@ +# +#include "../param.h" +#include "../systm.h" +#include "../user.h" +#include "../reg.h" +#include "../file.h" +#include "../inode.h" + +/* + * read system call + */ +read() +{ + rdwr(FREAD); +} + +/* + * write system call + */ +write() +{ + rdwr(FWRITE); +} + +/* + * common code for read and write calls: + * check permissions, set base, count, and offset, + * and switch out to readi, writei, or pipe code. + */ +rdwr(mode) +{ + register *fp, m; + + m = mode; + fp = getf(u.u_ar0[R0]); + if(fp == NULL) + return; + if((fp->f_flag&m) == 0) { + u.u_error = EBADF; + return; + } + u.u_base = u.u_arg[0]; + u.u_count = u.u_arg[1]; + u.u_segflg = 0; + if(fp->f_flag&FPIPE) { + if(m==FREAD) + readp(fp); else + writep(fp); + } else { + u.u_offset[1] = fp->f_offset[1]; + u.u_offset[0] = fp->f_offset[0]; + if(m==FREAD) + readi(fp->f_inode); else + writei(fp->f_inode); + dpadd(fp->f_offset, u.u_arg[1]-u.u_count); + } + u.u_ar0[R0] = u.u_arg[1]-u.u_count; +} + +/* + * open system call + */ +open() +{ + register *ip; + extern uchar; + + ip = namei(&uchar, 0); + if(ip == NULL) + return; + u.u_arg[1]++; + open1(ip, u.u_arg[1], 0); +} + +/* + * creat system call + */ +creat() +{ + register *ip; + extern uchar; + + ip = namei(&uchar, 1); + if(ip == NULL) { + if(u.u_error) + return; + ip = maknode(u.u_arg[1]&07777&(~ISVTX)); + if (ip==NULL) + return; + open1(ip, FWRITE, 2); + } else + open1(ip, FWRITE, 1); +} + +/* + * common code for open and creat. + * Check permissions, allocate an open file structure, + * and call the device open routine if any. + */ +open1(ip, mode, trf) +int *ip; +{ + register struct file *fp; + register *rip, m; + int i; + + rip = ip; + m = mode; + if(trf != 2) { + if(m&FREAD) + access(rip, IREAD); + if(m&FWRITE) { + access(rip, IWRITE); + if((rip->i_mode&IFMT) == IFDIR) + u.u_error = EISDIR; + } + } + if(u.u_error) + goto out; + if(trf) + itrunc(rip); + prele(rip); + if ((fp = falloc()) == NULL) + goto out; + fp->f_flag = m&(FREAD|FWRITE); + fp->f_inode = rip; + i = u.u_ar0[R0]; + openi(rip, m&FWRITE); + if(u.u_error == 0) + return; + u.u_ofile[i] = NULL; + fp->f_count--; + +out: + iput(rip); +} + +/* + * close system call + */ +close() +{ + register *fp; + + fp = getf(u.u_ar0[R0]); + if(fp == NULL) + return; + u.u_ofile[u.u_ar0[R0]] = NULL; + closef(fp); +} + +/* + * seek system call + */ +seek() +{ + int n[2]; + register *fp, t; + + fp = getf(u.u_ar0[R0]); + if(fp == NULL) + return; + if(fp->f_flag&FPIPE) { + u.u_error = ESPIPE; + return; + } + t = u.u_arg[1]; + if(t > 2) { + n[1] = u.u_arg[0]<<9; + n[0] = u.u_arg[0]>>7; + if(t == 3) + n[0] =& 0777; + } else { + n[1] = u.u_arg[0]; + n[0] = 0; + if(t!=0 && n[1]<0) + n[0] = -1; + } + switch(t) { + + case 1: + case 4: + n[0] =+ fp->f_offset[0]; + dpadd(n, fp->f_offset[1]); + break; + + default: + n[0] =+ fp->f_inode->i_size0&0377; + dpadd(n, fp->f_inode->i_size1); + + case 0: + case 3: + ; + } + fp->f_offset[1] = n[1]; + fp->f_offset[0] = n[0]; +} + +/* + * link system call + */ +link() +{ + register *ip, *xp; + extern uchar; + + ip = namei(&uchar, 0); + if(ip == NULL) + return; + if(ip->i_nlink >= 127) { + u.u_error = EMLINK; + goto out; + } + if((ip->i_mode&IFMT)==IFDIR && !suser()) + goto out; + /* + * unlock to avoid possibly hanging the namei + */ + ip->i_flag =& ~ILOCK; + u.u_dirp = u.u_arg[1]; + xp = namei(&uchar, 1); + if(xp != NULL) { + u.u_error = EEXIST; + iput(xp); + } + if(u.u_error) + goto out; + if(u.u_pdir->i_dev != ip->i_dev) { + iput(u.u_pdir); + u.u_error = EXDEV; + goto out; + } + wdir(ip); + ip->i_nlink++; + ip->i_flag =| IUPD; + +out: + iput(ip); +} + +/* + * mknod system call + */ +mknod() +{ + register *ip; + extern uchar; + + if(suser()) { + ip = namei(&uchar, 1); + if(ip != NULL) { + u.u_error = EEXIST; + goto out; + } + } + if(u.u_error) + return; + ip = maknode(u.u_arg[1]); + if (ip==NULL) + return; + ip->i_addr[0] = u.u_arg[2]; + +out: + iput(ip); +} + +/* + * sleep system call + * not to be confused with the sleep internal routine. + */ +sslep() +{ + char *d[2]; + + spl7(); + d[0] = time[0]; + d[1] = time[1]; + dpadd(d, u.u_ar0[R0]); + + while(dpcmp(d[0], d[1], time[0], time[1]) > 0) { + if(dpcmp(tout[0], tout[1], time[0], time[1]) <= 0 || + dpcmp(tout[0], tout[1], d[0], d[1]) > 0) { + tout[0] = d[0]; + tout[1] = d[1]; + } + sleep(tout, PSLEP); + } + spl0(); +} diff --git a/sys/ken/sys3.c b/sys/ken/sys3.c new file mode 100644 index 0000000..26f1de6 --- /dev/null +++ b/sys/ken/sys3.c @@ -0,0 +1,194 @@ +# +/* + */ + +#include "../param.h" +#include "../systm.h" +#include "../reg.h" +#include "../buf.h" +#include "../filsys.h" +#include "../user.h" +#include "../inode.h" +#include "../file.h" +#include "../conf.h" + +/* + * the fstat system call. + */ +fstat() +{ + register *fp; + + fp = getf(u.u_ar0[R0]); + if(fp == NULL) + return; + stat1(fp->f_inode, u.u_arg[0]); +} + +/* + * the stat system call. + */ +stat() +{ + register ip; + extern uchar; + + ip = namei(&uchar, 0); + if(ip == NULL) + return; + stat1(ip, u.u_arg[1]); + iput(ip); +} + +/* + * The basic routine for fstat and stat: + * get the inode and pass appropriate parts back. + */ +stat1(ip, ub) +int *ip; +{ + register i, *bp, *cp; + + iupdat(ip, time); + bp = bread(ip->i_dev, ldiv(ip->i_number+31, 16)); + cp = bp->b_addr + 32*lrem(ip->i_number+31, 16) + 24; + ip = &(ip->i_dev); + for(i=0; i<14; i++) { + suword(ub, *ip++); + ub =+ 2; + } + for(i=0; i<4; i++) { + suword(ub, *cp++); + ub =+ 2; + } + brelse(bp); +} + +/* + * the dup system call. + */ +dup() +{ + register i, *fp; + + fp = getf(u.u_ar0[R0]); + if(fp == NULL) + return; + if ((i = ufalloc()) < 0) + return; + u.u_ofile[i] = fp; + fp->f_count++; +} + +/* + * the mount system call. + */ +smount() +{ + int d; + register *ip; + register struct mount *mp, *smp; + extern uchar; + + d = getmdev(); + if(u.u_error) + return; + u.u_dirp = u.u_arg[1]; + ip = namei(&uchar, 0); + if(ip == NULL) + return; + if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0) + goto out; + smp = NULL; + for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { + if(mp->m_bufp != NULL) { + if(d == mp->m_dev) + goto out; + } else + if(smp == NULL) + smp = mp; + } + if(smp == NULL) + goto out; + (*bdevsw[d.d_major].d_open)(d, !u.u_arg[2]); + if(u.u_error) + goto out; + mp = bread(d, 1); + if(u.u_error) { + brelse(mp); + goto out1; + } + smp->m_inodp = ip; + smp->m_dev = d; + smp->m_bufp = getblk(NODEV); + bcopy(mp->b_addr, smp->m_bufp->b_addr, 256); + smp = smp->m_bufp->b_addr; + smp->s_ilock = 0; + smp->s_flock = 0; + smp->s_ronly = u.u_arg[2] & 1; + brelse(mp); + ip->i_flag =| IMOUNT; + prele(ip); + return; + +out: + u.u_error = EBUSY; +out1: + iput(ip); +} + +/* + * the umount system call. + */ +sumount() +{ + int d; + register struct inode *ip; + register struct mount *mp; + + update(); + d = getmdev(); + if(u.u_error) + return; + for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) + if(mp->m_bufp!=NULL && d==mp->m_dev) + goto found; + u.u_error = EINVAL; + return; + +found: + for(ip = &inode[0]; ip < &inode[NINODE]; ip++) + if(ip->i_number!=0 && d==ip->i_dev) { + u.u_error = EBUSY; + return; + } + (*bdevsw[d.d_major].d_close)(d, 0); + ip = mp->m_inodp; + ip->i_flag =& ~IMOUNT; + iput(ip); + ip = mp->m_bufp; + mp->m_bufp = NULL; + brelse(ip); +} + +/* + * Common code for mount and umount. + * Check that the user's argument is a reasonable + * thing on which to mount, and return the device number if so. + */ +getmdev() +{ + register d, *ip; + extern uchar; + + ip = namei(&uchar, 0); + if(ip == NULL) + return; + if((ip->i_mode&IFMT) != IFBLK) + u.u_error = ENOTBLK; + d = ip->i_addr[0]; + if(ip->i_addr[0].d_major >= nblkdev) + u.u_error = ENXIO; + iput(ip); + return(d); +} diff --git a/sys/ken/sys4.c b/sys/ken/sys4.c new file mode 100644 index 0000000..e4ad8a2 --- /dev/null +++ b/sys/ken/sys4.c @@ -0,0 +1,259 @@ +# +/* + */ + +/* + * Everything in this file is a routine implementing a system call. + */ + +#include "../param.h" +#include "../user.h" +#include "../reg.h" +#include "../inode.h" +#include "../systm.h" +#include "../proc.h" + +getswit() +{ + + u.u_ar0[R0] = SW->integ; +} + +gtime() +{ + + u.u_ar0[R0] = time[0]; + u.u_ar0[R1] = time[1]; +} + +stime() +{ + + if(suser()) { + time[0] = u.u_ar0[R0]; + time[1] = u.u_ar0[R1]; + wakeup(tout); + } +} + +setuid() +{ + register uid; + + uid = u.u_ar0[R0].lobyte; + if(u.u_ruid == uid.lobyte || suser()) { + u.u_uid = uid; + u.u_procp->p_uid = uid; + u.u_ruid = uid; + } +} + +getuid() +{ + + u.u_ar0[R0].lobyte = u.u_ruid; + u.u_ar0[R0].hibyte = u.u_uid; +} + +setgid() +{ + register gid; + + gid = u.u_ar0[R0].lobyte; + if(u.u_rgid == gid.lobyte || suser()) { + u.u_gid = gid; + u.u_rgid = gid; + } +} + +getgid() +{ + + u.u_ar0[R0].lobyte = u.u_rgid; + u.u_ar0[R0].hibyte = u.u_gid; +} + +getpid() +{ + u.u_ar0[R0] = u.u_procp->p_pid; +} + +sync() +{ + + update(); +} + +nice() +{ + register n; + + n = u.u_ar0[R0]; + if(n > 20) + n = 20; + if(n < 0 && !suser()) + n = 0; + u.u_procp->p_nice = n; +} + +/* + * Unlink system call. + * panic: unlink -- "cannot happen" + */ +unlink() +{ + register *ip, *pp; + extern uchar; + + pp = namei(&uchar, 2); + if(pp == NULL) + return; + prele(pp); + ip = iget(pp->i_dev, u.u_dent.u_ino); + if(ip == NULL) + panic("unlink -- iget"); + if((ip->i_mode&IFMT)==IFDIR && !suser()) + goto out; + u.u_offset[1] =- DIRSIZ+2; + u.u_base = &u.u_dent; + u.u_count = DIRSIZ+2; + u.u_dent.u_ino = 0; + writei(pp); + ip->i_nlink--; + ip->i_flag =| IUPD; + +out: + iput(pp); + iput(ip); +} + +chdir() +{ + register *ip; + extern uchar; + + ip = namei(&uchar, 0); + if(ip == NULL) + return; + if((ip->i_mode&IFMT) != IFDIR) { + u.u_error = ENOTDIR; + bad: + iput(ip); + return; + } + if(access(ip, IEXEC)) + goto bad; + iput(u.u_cdir); + u.u_cdir = ip; + prele(ip); +} + +chmod() +{ + register *ip; + + if ((ip = owner()) == NULL) + return; + ip->i_mode =& ~07777; + if (u.u_uid) + u.u_arg[1] =& ~ISVTX; + ip->i_mode =| u.u_arg[1]&07777; + ip->i_flag =| IUPD; + iput(ip); +} + +chown() +{ + register *ip; + + if (!suser() || (ip = owner()) == NULL) + return; + ip->i_uid = u.u_arg[1].lobyte; + ip->i_gid = u.u_arg[1].hibyte; + ip->i_flag =| IUPD; + iput(ip); +} + +/* + * Change modified date of file: + * time to r0-r1; sys smdate; file + * This call has been withdrawn because it messes up + * incremental dumps (pseudo-old files aren't dumped). + * It works though and you can uncomment it if you like. + +smdate() +{ + register struct inode *ip; + register int *tp; + int tbuf[2]; + + if ((ip = owner()) == NULL) + return; + ip->i_flag =| IUPD; + tp = &tbuf[2]; + *--tp = u.u_ar0[R1]; + *--tp = u.u_ar0[R0]; + iupdat(ip, tp); + ip->i_flag =& ~IUPD; + iput(ip); +} +*/ + +ssig() +{ + register a; + + a = u.u_arg[0]; + if(a<=0 || a>=NSIG || a ==SIGKIL) { + u.u_error = EINVAL; + return; + } + u.u_ar0[R0] = u.u_signal[a]; + u.u_signal[a] = u.u_arg[1]; + if(u.u_procp->p_sig == a) + u.u_procp->p_sig = 0; +} + +kill() +{ + register struct proc *p, *q; + register a; + int f; + + f = 0; + a = u.u_ar0[R0]; + q = u.u_procp; + for(p = &proc[0]; p < &proc[NPROC]; p++) { + if(p == q) + continue; + if(a != 0 && p->p_pid != a) + continue; + if(a == 0 && (p->p_ttyp != q->p_ttyp || p <= &proc[1])) + continue; + if(u.u_uid != 0 && u.u_uid != p->p_uid) + continue; + f++; + psignal(p, u.u_arg[0]); + } + if(f == 0) + u.u_error = ESRCH; +} + +times() +{ + register *p; + + for(p = &u.u_utime; p < &u.u_utime+6;) { + suword(u.u_arg[0], *p++); + u.u_arg[0] =+ 2; + } +} + +profil() +{ + + u.u_prof[0] = u.u_arg[0] & ~1; /* base of sample buf */ + u.u_prof[1] = u.u_arg[1]; /* size of same */ + u.u_prof[2] = u.u_arg[2]; /* pc offset */ + u.u_prof[3] = (u.u_arg[3]>>1) & 077777; /* pc scale */ +} diff --git a/sys/ken/sysent.c b/sys/ken/sysent.c new file mode 100644 index 0000000..a44445a --- /dev/null +++ b/sys/ken/sysent.c @@ -0,0 +1,77 @@ +# +/* + */ + +/* + * This table is the switch used to transfer + * to the appropriate routine for processing a system call. + * Each row contains the number of arguments expected + * and a pointer to the routine. + */ +int sysent[] +{ + 0, &nullsys, /* 0 = indir */ + 0, &rexit, /* 1 = exit */ + 0, &fork, /* 2 = fork */ + 2, &read, /* 3 = read */ + 2, &write, /* 4 = write */ + 2, &open, /* 5 = open */ + 0, &close, /* 6 = close */ + 0, &wait, /* 7 = wait */ + 2, &creat, /* 8 = creat */ + 2, &link, /* 9 = link */ + 1, &unlink, /* 10 = unlink */ + 2, &exec, /* 11 = exec */ + 1, &chdir, /* 12 = chdir */ + 0, >ime, /* 13 = time */ + 3, &mknod, /* 14 = mknod */ + 2, &chmod, /* 15 = chmod */ + 2, &chown, /* 16 = chown */ + 1, &sbreak, /* 17 = break */ + 2, &stat, /* 18 = stat */ + 2, &seek, /* 19 = seek */ + 0, &getpid, /* 20 = getpid */ + 3, &smount, /* 21 = mount */ + 1, &sumount, /* 22 = umount */ + 0, &setuid, /* 23 = setuid */ + 0, &getuid, /* 24 = getuid */ + 0, &stime, /* 25 = stime */ + 3, &ptrace, /* 26 = ptrace */ + 0, &nosys, /* 27 = x */ + 1, &fstat, /* 28 = fstat */ + 0, &nosys, /* 29 = x */ + 1, &nullsys, /* 30 = smdate; inoperative */ + 1, &stty, /* 31 = stty */ + 1, >ty, /* 32 = gtty */ + 0, &nosys, /* 33 = x */ + 0, &nice, /* 34 = nice */ + 0, &sslep, /* 35 = sleep */ + 0, &sync, /* 36 = sync */ + 1, &kill, /* 37 = kill */ + 0, &getswit, /* 38 = switch */ + 0, &nosys, /* 39 = x */ + 0, &nosys, /* 40 = x */ + 0, &dup, /* 41 = dup */ + 0, &pipe, /* 42 = pipe */ + 1, ×, /* 43 = times */ + 4, &profil, /* 44 = prof */ + 0, &nosys, /* 45 = tiu */ + 0, &setgid, /* 46 = setgid */ + 0, &getgid, /* 47 = getgid */ + 2, &ssig, /* 48 = sig */ + 0, &nosys, /* 49 = x */ + 0, &nosys, /* 50 = x */ + 0, &nosys, /* 51 = x */ + 0, &nosys, /* 52 = x */ + 0, &nosys, /* 53 = x */ + 0, &nosys, /* 54 = x */ + 0, &nosys, /* 55 = x */ + 0, &nosys, /* 56 = x */ + 0, &nosys, /* 57 = x */ + 0, &nosys, /* 58 = x */ + 0, &nosys, /* 59 = x */ + 0, &nosys, /* 60 = x */ + 0, &nosys, /* 61 = x */ + 0, &nosys, /* 62 = x */ + 0, &nosys /* 63 = x */ +}; diff --git a/sys/ken/text.c b/sys/ken/text.c new file mode 100644 index 0000000..6c3363a --- /dev/null +++ b/sys/ken/text.c @@ -0,0 +1,156 @@ +# +/* + */ + +#include "../param.h" +#include "../systm.h" +#include "../user.h" +#include "../proc.h" +#include "../text.h" +#include "../inode.h" + +/* + * Swap out process p. + * The ff flag causes its core to be freed-- + * it may be off when called to create an image for a + * child process in newproc. + * Os is the old size of the data area of the process, + * and is supplied during core expansion swaps. + * + * panic: out of swap space + * panic: swap error -- IO error + */ +xswap(p, ff, os) +int *p; +{ + register *rp, a; + + rp = p; + if(os == 0) + os = rp->p_size; + a = malloc(swapmap, (rp->p_size+7)/8); + if(a == NULL) + panic("out of swap space"); + xccdec(rp->p_textp); + rp->p_flag =| SLOCK; + if(swap(a, rp->p_addr, os, 0)) + panic("swap error"); + if(ff) + mfree(coremap, os, rp->p_addr); + rp->p_addr = a; + rp->p_flag =& ~(SLOAD|SLOCK); + rp->p_time = 0; + if(runout) { + runout = 0; + wakeup(&runout); + } +} + +/* + * relinquish use of the shared text segment + * of a process. + */ +xfree() +{ + register *xp, *ip; + + if((xp=u.u_procp->p_textp) != NULL) { + u.u_procp->p_textp = NULL; + xccdec(xp); + if(--xp->x_count == 0) { + ip = xp->x_iptr; + if((ip->i_mode&ISVTX) == 0) { + xp->x_iptr = NULL; + mfree(swapmap, (xp->x_size+7)/8, xp->x_daddr); + ip->i_flag =& ~ITEXT; + iput(ip); + } + } + } +} + +/* + * Attach to a shared text segment. + * If there is no shared text, just return. + * If there is, hook up to it: + * if it is not currently being used, it has to be read + * in from the inode (ip) and established in the swap space. + * If it is being used, but is not currently in core, + * a swap has to be done to get it back. + * The full coroutine glory has to be invoked-- + * see slp.c-- because if the calling process + * is misplaced in core the text image might not fit. + * Quite possibly the code after "out:" could check to + * see if the text does fit and simply swap it in. + * + * panic: out of swap space + */ +xalloc(ip) +int *ip; +{ + register struct text *xp; + register *rp, ts; + + if(u.u_arg[1] == 0) + return; + rp = NULL; + for(xp = &text[0]; xp < &text[NTEXT]; xp++) + if(xp->x_iptr == NULL) { + if(rp == NULL) + rp = xp; + } else + if(xp->x_iptr == ip) { + xp->x_count++; + u.u_procp->p_textp = xp; + goto out; + } + if((xp=rp) == NULL) + panic("out of text"); + xp->x_count = 1; + xp->x_ccount = 0; + xp->x_iptr = ip; + ts = ((u.u_arg[1]+63)>>6) & 01777; + xp->x_size = ts; + if((xp->x_daddr = malloc(swapmap, (ts+7)/8)) == NULL) + panic("out of swap space"); + expand(USIZE+ts); + estabur(0, ts, 0, 0); + u.u_count = u.u_arg[1]; + u.u_offset[1] = 020; + u.u_base = 0; + readi(ip); + rp = u.u_procp; + rp->p_flag =| SLOCK; + swap(xp->x_daddr, rp->p_addr+USIZE, ts, 0); + rp->p_flag =& ~SLOCK; + rp->p_textp = xp; + rp = ip; + rp->i_flag =| ITEXT; + rp->i_count++; + expand(USIZE); + +out: + if(xp->x_ccount == 0) { + savu(u.u_rsav); + savu(u.u_ssav); + xswap(u.u_procp, 1, 0); + u.u_procp->p_flag =| SSWAP; + swtch(); + /* no return */ + } + xp->x_ccount++; +} + +/* + * Decrement the in-core usage count of a shared text segment. + * When it drops to zero, free the core space. + */ +xccdec(xp) +int *xp; +{ + register *rp; + + if((rp=xp)!=NULL && rp->x_ccount!=0) + if(--rp->x_ccount == 0) + mfree(coremap, rp->x_size, rp->x_caddr); +} diff --git a/sys/ken/trap.c b/sys/ken/trap.c new file mode 100644 index 0000000..6db137c --- /dev/null +++ b/sys/ken/trap.c @@ -0,0 +1,212 @@ +# +#include "../param.h" +#include "../systm.h" +#include "../user.h" +#include "../proc.h" +#include "../reg.h" +#include "../seg.h" + +#define EBIT 1 /* user error bit in PS: C-bit */ +#define UMODE 0170000 /* user-mode bits in PS word */ +#define SETD 0170011 /* SETD instruction */ +#define SYS 0104400 /* sys (trap) instruction */ +#define USER 020 /* user-mode flag added to dev */ + +/* + * structure of the system entry table (sysent.c) + */ +struct sysent { + int count; /* argument count */ + int (*call)(); /* name of handler */ +} sysent[64]; + +/* + * Offsets of the user's registers relative to + * the saved r0. See reg.h + */ +char regloc[9] +{ + R0, R1, R2, R3, R4, R5, R6, R7, RPS +}; + +/* + * Called from l40.s or l45.s when a processor trap occurs. + * The arguments are the words saved on the system stack + * by the hardware and software during the trap processing. + * Their order is dictated by the hardware and the details + * of C's calling sequence. They are peculiar in that + * this call is not 'by value' and changed user registers + * get copied back on return. + * dev is the kind of trap that occurred. + */ +trap(dev, sp, r1, nps, r0, pc, ps) +{ + register i, a; + register struct sysent *callp; + + savfp(); + if ((ps&UMODE) == UMODE) + dev =| USER; + u.u_ar0 = &r0; + switch(dev) { + + /* + * Trap not expected. + * Usually a kernel mode bus error. + * The numbers printed are used to + * find the hardware PS/PC as follows. + * (all numbers in octal 18 bits) + * address_of_saved_ps = + * (ka6*0100) + aps - 0140000; + * address_of_saved_pc = + * address_of_saved_ps - 2; + */ + default: + printf("ka6 = %o\n", *ka6); + printf("aps = %o\n", &ps); + printf("trap type %o\n", dev); + panic("trap"); + + case 0+USER: /* bus error */ + i = SIGBUS; + break; + + /* + * If illegal instructions are not + * being caught and the offending instruction + * is a SETD, the trap is ignored. + * This is because C produces a SETD at + * the beginning of every program which + * will trap on CPUs without 11/45 FPU. + */ + case 1+USER: /* illegal instruction */ + if(fuiword(pc-2) == SETD && u.u_signal[SIGINS] == 0) + goto out; + i = SIGINS; + break; + + case 2+USER: /* bpt or trace */ + i = SIGTRC; + break; + + case 3+USER: /* iot */ + i = SIGIOT; + break; + + case 5+USER: /* emt */ + i = SIGEMT; + break; + + case 6+USER: /* sys call */ + u.u_error = 0; + ps =& ~EBIT; + callp = &sysent[fuiword(pc-2)&077]; + if (callp == sysent) { /* indirect */ + a = fuiword(pc); + pc =+ 2; + i = fuword(a); + if ((i & ~077) != SYS) + i = 077; /* illegal */ + callp = &sysent[i&077]; + for(i=0; icount; i++) + u.u_arg[i] = fuword(a =+ 2); + } else { + for(i=0; icount; i++) { + u.u_arg[i] = fuiword(pc); + pc =+ 2; + } + } + u.u_dirp = u.u_arg[0]; + trap1(callp->call); + if(u.u_intflg) + u.u_error = EINTR; + if(u.u_error < 100) { + if(u.u_error) { + ps =| EBIT; + r0 = u.u_error; + } + goto out; + } + i = SIGSYS; + break; + + /* + * Since the floating exception is an + * imprecise trap, a user generated + * trap may actually come from kernel + * mode. In this case, a signal is sent + * to the current process to be picked + * up later. + */ + case 8: /* floating exception */ + psignal(u.u_procp, SIGFPT); + return; + + case 8+USER: + i = SIGFPT; + break; + + /* + * If the user SP is below the stack segment, + * grow the stack automatically. + * This relies on the ability of the hardware + * to restart a half executed instruction. + * On the 11/40 this is not the case and + * the routine backup/l40.s may fail. + * The classic example is on the instruction + * cmp -(sp),-(sp) + */ + case 9+USER: /* segmentation exception */ + a = sp; + if(backup(u.u_ar0) == 0) + if(grow(a)) + goto out; + i = SIGSEG; + break; + } + psignal(u.u_procp, i); + +out: + if(issig()) + psig(); + setpri(u.u_procp); +} + +/* + * Call the system-entry routine f (out of the + * sysent table). This is a subroutine for trap, and + * not in-line, because if a signal occurs + * during processing, an (abnormal) return is simulated from + * the last caller to savu(qsav); if this took place + * inside of trap, it wouldn't have a chance to clean up. + * + * If this occurs, the return takes place without + * clearing u_intflg; if it's still set, trap + * marks an error which means that a system + * call (like read on a typewriter) got interrupted + * by a signal. + */ +trap1(f) +int (*f)(); +{ + + u.u_intflg = 1; + savu(u.u_qsav); + (*f)(); + u.u_intflg = 0; +} + +/* + * nonexistent system call-- set fatal error code. + */ +nosys() +{ + u.u_error = 100; +} + +/* + * Ignored system call + */ +nullsys() +{ +} diff --git a/sys/lib1 b/sys/lib1 new file mode 100644 index 0000000..759b400 Binary files /dev/null and b/sys/lib1 differ diff --git a/sys/lib2 b/sys/lib2 new file mode 100644 index 0000000..b4a320c Binary files /dev/null and b/sys/lib2 differ diff --git a/sys/param.h b/sys/param.h new file mode 100644 index 0000000..c422492 --- /dev/null +++ b/sys/param.h @@ -0,0 +1,91 @@ +/* + * tunable variables + */ + +#define NBUF 15 /* size of buffer cache */ +#define NINODE 100 /* number of in core inodes */ +#define NFILE 100 /* number of in core file structures */ +#define NMOUNT 5 /* number of mountable file systems */ +#define NEXEC 3 /* number of simultaneous exec's */ +#define MAXMEM (64*32) /* max core per process - first # is Kw */ +#define SSIZE 20 /* initial stack size (*64 bytes) */ +#define SINCR 20 /* increment of stack (*64 bytes) */ +#define NOFILE 15 /* max open files per process */ +#define CANBSIZ 256 /* max size of typewriter line */ +#define CMAPSIZ 100 /* size of core allocation area */ +#define SMAPSIZ 100 /* size of swap allocation area */ +#define NCALL 20 /* max simultaneous time callouts */ +#define NPROC 50 /* max number of processes */ +#define NTEXT 40 /* max number of pure texts */ +#define NCLIST 100 /* max total clist size */ +#define HZ 60 /* Ticks/second of the clock */ + +/* + * priorities + * probably should not be + * altered too much + */ + +#define PSWP -100 +#define PINOD -90 +#define PRIBIO -50 +#define PPIPE 1 +#define PWAIT 40 +#define PSLEP 90 +#define PUSER 100 + +/* + * signals + * dont change + */ + +#define NSIG 20 +#define SIGHUP 1 /* hangup */ +#define SIGINT 2 /* interrupt (rubout) */ +#define SIGQIT 3 /* quit (FS) */ +#define SIGINS 4 /* illegal instruction */ +#define SIGTRC 5 /* trace or breakpoint */ +#define SIGIOT 6 /* iot */ +#define SIGEMT 7 /* emt */ +#define SIGFPT 8 /* floating exception */ +#define SIGKIL 9 /* kill */ +#define SIGBUS 10 /* bus error */ +#define SIGSEG 11 /* segmentation violation */ +#define SIGSYS 12 /* sys */ +#define SIGPIPE 13 /* end of pipe */ + +/* + * fundamental constants + * cannot be changed + */ + +#define USIZE 16 /* size of user block (*64) */ +#define NULL 0 +#define NODEV (-1) +#define ROOTINO 1 /* i number of all roots */ +#define DIRSIZ 14 /* max characters per directory */ + +/* + * structure to access an + * integer in bytes + */ +struct +{ + char lobyte; + char hibyte; +}; + +/* + * structure to access an integer + */ +struct +{ + int integ; +}; + +/* + * Certain processor registers + */ +#define PS 0177776 +#define KL 0177560 +#define SW 0177570 diff --git a/sys/proc.h b/sys/proc.h new file mode 100644 index 0000000..34a1d3b --- /dev/null +++ b/sys/proc.h @@ -0,0 +1,42 @@ +/* + * One structure allocated per active + * process. It contains all data needed + * about the process while the + * process may be swapped out. + * Other per process data (user.h) + * is swapped with the process. + */ +struct proc +{ + char p_stat; + char p_flag; + char p_pri; /* priority, negative is high */ + char p_sig; /* signal number sent to this process */ + char p_uid; /* user id, used to direct tty signals */ + char p_time; /* resident time for scheduling */ + char p_cpu; /* cpu usage for scheduling */ + char p_nice; /* nice for scheduling */ + int p_ttyp; /* controlling tty */ + int p_pid; /* unique process id */ + int p_ppid; /* process id of parent */ + int p_addr; /* address of swappable image */ + int p_size; /* size of swappable image (*64 bytes) */ + int p_wchan; /* event process is awaiting */ + int *p_textp; /* pointer to text structure */ +} proc[NPROC]; + +/* stat codes */ +#define SSLEEP 1 /* sleeping on high priority */ +#define SWAIT 2 /* sleeping on low priority */ +#define SRUN 3 /* running */ +#define SIDL 4 /* intermediate state in process creation */ +#define SZOMB 5 /* intermediate state in process termination */ +#define SSTOP 6 /* process being traced */ + +/* flag codes */ +#define SLOAD 01 /* in core */ +#define SSYS 02 /* scheduling process */ +#define SLOCK 04 /* process cannot be swapped */ +#define SSWAP 010 /* process is being swapped out */ +#define STRC 020 /* process is being traced */ +#define SWTED 040 /* another tracing flag */ diff --git a/sys/reg.h b/sys/reg.h new file mode 100644 index 0000000..71f1b5f --- /dev/null +++ b/sys/reg.h @@ -0,0 +1,16 @@ +/* + * Location of the users' stored + * registers relative to R0. + * Usage is u.u_ar0[XX]. + */ +#define R0 (0) +#define R1 (-2) +#define R2 (-9) +#define R3 (-8) +#define R4 (-7) +#define R5 (-6) +#define R6 (-3) +#define R7 (1) +#define RPS (2) + +#define TBIT 020 /* PS trace bit */ diff --git a/sys/run b/sys/run new file mode 100644 index 0000000..4112985 --- /dev/null +++ b/sys/run @@ -0,0 +1,73 @@ +chdir ken +cc -c -O *.c +ar r ../lib1 +rm *.o + +chdir ../dmr +cc -c -O *.c +ar r ../lib2 +rm *.o + +chdir ../conf +as m40.s +mv a.out m40.o +: as m45.s +: mv a.out m45.o +: cc sysfix.c +: mv a.out sysfix +cc mkconf.c +mv a.out mkconf + +mkconf +rk +tm +tc +done + +cc -c c.c +as l.s +ld -x a.out m40.o c.o ../lib1 ../lib2 +: as data.s l.s +: ld -x -r -d a.out m45.o c.o ../lib1 ../lib2 +: nm -ug +: sysfix a.out x +: mv x a.out +cmp a.out /rkunix +cp a.out /rkunix + +mkconf +rp +tm +tc +done + +cc -c c.c +as l.s +ld -x a.out m40.o c.o ../lib1 ../lib2 +: as data.s l.s +: ld -x -r -d a.out m45.o c.o ../lib1 ../lib2 +: nm -ug +: sysfix a.out x +: mv x a.out +cmp a.out /rpunix +cp a.out /rpunix + +mkconf +hp +tm +tc +done + +cc -c c.c +as l.s +ld -x a.out m40.o c.o ../lib1 ../lib2 +: as data.s l.s +: ld -x -r -d a.out m45.o c.o ../lib1 ../lib2 +: nm -ug +: sysfix a.out x +: mv x a.out +cmp a.out /hpunix +cp a.out /hpunix + +rm mkconf c.c l.s a.out *.o +: rm sysfix diff --git a/sys/seg.h b/sys/seg.h new file mode 100644 index 0000000..6844bef --- /dev/null +++ b/sys/seg.h @@ -0,0 +1,26 @@ +/* + * KT-11 addresses and bits. + */ + +#define UISD 0177600 /* first user I-space descriptor register */ +#define UISA 0177640 /* first user I-space address register */ +#define UDSA 0177660 /* first user D-space address register */ +#define RO 02 /* access abilities */ +#define WO 04 +#define RW 06 +#define ED 010 /* extend direction */ + +/* + * structure used to address + * a sequence of integers. + */ +struct +{ + int r[]; +}; +int *ka6; /* 11/40 KISA6; 11/45 KDSA6 */ + +/* + * address to access 11/70 UNIBUS map + */ +#define UBMAP 0170200 diff --git a/sys/systm.h b/sys/systm.h new file mode 100644 index 0000000..08b71d7 --- /dev/null +++ b/sys/systm.h @@ -0,0 +1,54 @@ +/* + * Random set of variables + * used by more than one + * routine. + */ +char canonb[CANBSIZ]; /* buffer for erase and kill (#@) */ +int coremap[CMAPSIZ]; /* space for core allocation */ +int swapmap[SMAPSIZ]; /* space for swap allocation */ +int *rootdir; /* pointer to inode of root directory */ +int cputype; /* type of cpu =40, 45, or 70 */ +int execnt; /* number of processes in exec */ +int lbolt; /* time of day in 60th not in time */ +int time[2]; /* time in sec from 1970 */ +int tout[2]; /* time of day of next sleep */ +/* + * The callout structure is for + * a routine arranging + * to be called by the clock interrupt + * (clock.c) with a specified argument, + * in a specified amount of time. + * Used, for example, to time tab + * delays on teletypes. + */ +struct callo +{ + int c_time; /* incremental time */ + int c_arg; /* argument to routine */ + int (*c_func)(); /* routine */ +} callout[NCALL]; +/* + * Mount structure. + * One allocated on every mount. + * Used to find the super block. + */ +struct mount +{ + int m_dev; /* device mounted */ + int *m_bufp; /* pointer to superblock */ + int *m_inodp; /* pointer to mounted on inode */ +} mount[NMOUNT]; +int mpid; /* generic for unique process id's */ +char runin; /* scheduling flag */ +char runout; /* scheduling flag */ +char runrun; /* scheduling flag */ +char curpri; /* more scheduling */ +int maxmem; /* actual max memory per process */ +int *lks; /* pointer to clock device */ +int rootdev; /* dev of root see conf.c */ +int swapdev; /* dev of swap see conf.c */ +int swplo; /* block number of swap space */ +int nswap; /* size of swap space */ +int updlock; /* lock for sync */ +int rablock; /* block to be read ahead */ +char regloc[]; /* locs. of saved user registers (trap.c) */ diff --git a/sys/text.h b/sys/text.h new file mode 100644 index 0000000..f6ff234 --- /dev/null +++ b/sys/text.h @@ -0,0 +1,15 @@ +/* + * Text structure. + * One allocated per pure + * procedure on swap device. + * Manipulated by text.c + */ +struct text +{ + int x_daddr; /* disk address of segment */ + int x_caddr; /* core address, if loaded */ + int x_size; /* size (*64) */ + int *x_iptr; /* inode of prototype */ + char x_count; /* reference count */ + char x_ccount; /* number of loaded references */ +} text[NTEXT]; diff --git a/sys/tty.h b/sys/tty.h new file mode 100644 index 0000000..7e29eac --- /dev/null +++ b/sys/tty.h @@ -0,0 +1,84 @@ +/* + * A clist structure is the head + * of a linked list queue of characters. + * The characters are stored in 4-word + * blocks containing a link and 6 characters. + * The routines getc and putc (m45.s or m40.s) + * manipulate these structures. + */ +struct clist +{ + int c_cc; /* character count */ + int c_cf; /* pointer to first block */ + int c_cl; /* pointer to last block */ +}; + +/* + * A tty structure is needed for + * each UNIX character device that + * is used for normal terminal IO. + * The routines in tty.c handle the + * common code associated with + * these structures. + * The definition and device dependent + * code is in each driver. (kl.c dc.c dh.c) + */ +struct tty +{ + struct clist t_rawq; /* input chars right off device */ + struct clist t_canq; /* input chars after erase and kill */ + struct clist t_outq; /* output list to device */ + int t_flags; /* mode, settable by stty call */ + int *t_addr; /* device address (register or startup fcn) */ + char t_delct; /* number of delimiters in raw q */ + char t_col; /* printing column of device */ + char t_erase; /* erase character */ + char t_kill; /* kill character */ + char t_state; /* internal state, not visible externally */ + char t_char; /* character temporary */ + int t_speeds; /* output+input line speed */ + int t_dev; /* device name */ +}; + +char partab[]; /* ASCII table: parity, character class */ + +#define TTIPRI 10 +#define TTOPRI 20 + +#define CERASE '#' /* default special characters */ +#define CEOT 004 +#define CKILL '@' +#define CQUIT 034 /* FS, cntl shift L */ +#define CINTR 0177 /* DEL */ + +/* limits */ +#define TTHIWAT 50 +#define TTLOWAT 30 +#define TTYHOG 256 + +/* modes */ +#define HUPCL 01 +#define XTABS 02 +#define LCASE 04 +#define ECHO 010 +#define CRMOD 020 +#define RAW 040 +#define ODDP 0100 +#define EVENP 0200 +#define NLDELAY 001400 +#define TBDELAY 006000 +#define CRDELAY 030000 +#define VTDELAY 040000 + +/* Hardware bits */ +#define DONE 0200 +#define IENABLE 0100 + +/* Internal state bits */ +#define TIMEOUT 01 /* Delay timeout in progress */ +#define WOPEN 02 /* Waiting for open to complete */ +#define ISOPEN 04 /* Device is open */ +#define SSTART 010 /* Has special start routine at addr */ +#define CARR_ON 020 /* Software copy of carrier-present */ +#define BUSY 040 /* Output in progress */ +#define ASLEEP 0100 /* Wakeup when output done */ diff --git a/sys/user.h b/sys/user.h new file mode 100644 index 0000000..6c5f352 --- /dev/null +++ b/sys/user.h @@ -0,0 +1,93 @@ +/* + * The user structure. + * One allocated per process. + * Contains all per process data + * that doesn't need to be referenced + * while the process is swapped. + * The user block is USIZE*64 bytes + * long; resides at virtual kernel + * loc 140000; contains the system + * stack per user; is cross referenced + * with the proc structure for the + * same process. + */ +struct user +{ + int u_rsav[2]; /* save r5,r6 when exchanging stacks */ + int u_fsav[25]; /* save fp registers */ + /* rsav and fsav must be first in structure */ + char u_segflg; /* flag for IO; user or kernel space */ + char u_error; /* return error code */ + char u_uid; /* effective user id */ + char u_gid; /* effective group id */ + char u_ruid; /* real user id */ + char u_rgid; /* real group id */ + int u_procp; /* pointer to proc structure */ + char *u_base; /* base address for IO */ + char *u_count; /* bytes remaining for IO */ + char *u_offset[2]; /* offset in file for IO */ + int *u_cdir; /* pointer to inode of current directory */ + char u_dbuf[DIRSIZ]; /* current pathname component */ + char *u_dirp; /* current pointer to inode */ + struct { /* current directory entry */ + int u_ino; + char u_name[DIRSIZ]; + } u_dent; + int *u_pdir; /* inode of parent directory of dirp */ + int u_uisa[16]; /* prototype of segmentation addresses */ + int u_uisd[16]; /* prototype of segmentation descriptors */ + int u_ofile[NOFILE]; /* pointers to file structures of open files */ + int u_arg[5]; /* arguments to current system call */ + int u_tsize; /* text size (*64) */ + int u_dsize; /* data size (*64) */ + int u_ssize; /* stack size (*64) */ + int u_sep; /* flag for I and D separation */ + int u_qsav[2]; /* label variable for quits and interrupts */ + int u_ssav[2]; /* label variable for swapping */ + int u_signal[NSIG]; /* disposition of signals */ + int u_utime; /* this process user time */ + int u_stime; /* this process system time */ + int u_cutime[2]; /* sum of childs' utimes */ + int u_cstime[2]; /* sum of childs' stimes */ + int *u_ar0; /* address of users saved R0 */ + int u_prof[4]; /* profile arguments */ + char u_intflg; /* catch intr from sys */ + /* kernel stack per user + * extends from u + USIZE*64 + * backward not to reach here + */ +} u; + +/* u_error codes */ +#define EFAULT 106 +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define ENOTBLK 15 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define ETXTBSY 26 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32