// March 31, 1978 11:19 AM *** RESIDENT *** // Utility routines // Compile with FLOAT/M to get sTypeFloat // Compile with SQRT/M to get SquareRoot get "streams.d" get "altoFileSys.d" // outgoing procedures: external [ confirm getLine typeForm sTypeForm SquareRoot openRead openWrite abortMessage FPerror FatalError capitalize equal ] // incoming procedures: external [ Wss // SYSTEM Wos Wns Gets Puts OpenFile Closes Zero getBlock // free storage routines putBlock giveUp FLD; FLDI; FST; FTR // FLOAT FML; FDV; FAD; FSB FSN; FCM; FNEG; FLDV ] // incoming statics: external [ keys // SYSTEM dsp ] // local definitions: manifest [ getFloat= not newname FLOAT getSqrt= not newname SQRT ] //**************************************************************** // input/output procedures //**************************************************************** let openRead(message, itemType, fileNameAd, fileFp; numargs n) = valof [openread switchon n into [ case 1: itemType=wordItem case 2: fileNameAd=0 case 3: fileFp=0 default: endcase ] if fileFp ne 0 then Zero(fileFp, lFP) [ typeForm(0, message) let fileName=getLine() unless fileName then resultis abortMessage() let file=OpenFile(fileName, ksTypeReadOnly, itemType, 0, fileFp) if file then [ test fileNameAd ne 0 ifso @fileNameAd=fileName ifnot putBlock(fileName) resultis file ] typeForm(0, "No such file!*N") putBlock(fileName) ] repeat ]openread and openWrite(message, itemType, fileNameAd, fileFp; numargs n) = valof [openwrite let file, fileName=nil, nil switchon n into [ case 1: itemType=wordItem case 2: fileNameAd=0 case 3: fileFp=0 default: endcase ] [ typeForm(0, message) fileName=getLine() unless fileName then resultis abortMessage() if fileFp ne 0 then Zero(fileFp, lFP) file=OpenFile(fileName, ksTypeWriteOnly, itemType, verLatest, fileFp) test file ifso test confirm("Overwrite ? ") ifso break ifnot [ Closes(file); putBlock(fileName) ] ifnot [ if fileFp ne 0 then Zero(fileFp, lFP) file=OpenFile(fileName, ksTypeWriteOnly, itemType, verNew, fileFp) break ] ] repeat test fileNameAd ne 0 ifso @fileNameAd=fileName ifnot putBlock(fileName) resultis file ]openwrite and abortMessage() = valof [ typeForm(0, "Abort*N") resultis 0 ] and FatalError(message, error; numargs n) be [ typeForm(0, "SORRY: UNRECOVERABLE ERROR. Type any character to finish.", 0, "*NPlease contact your local software expert.*N", 0, message) if n eq 2 then typeForm(10, error) Gets(keys) finish ] and FPerror(error) = FatalError("Floating point error ", error) and capitalize(char) = ((char ge $a) & (char le $z)) ? (char - #40), char and equal(string1, string2) = valof [ let count=string1>>STRING.length if count ne string2>>STRING.length then resultis false for i=1 to count do if capitalize(string1>>STRING.char↑i) ne capitalize(string2>>STRING.char↑i) resultis false resultis true ] and confirm(message; numargs n) = valof [confirm if n & message then typeForm(0, message, 0, " [ Yes No ] ") [ switchon Gets(keys) into [ case $N: case $n: typeForm(0, "No*N") resultis false case $Y: case $y: case $*N: typeForm(0, "Yes*N") resultis true ] repeat ]confirm //**************************************************************** // square root (optional) //**************************************************************** and SquareRoot(a) be [ // a is FP pointer compileif getSqrt then [ // FP accumulators manifest [ r=0; t=1; q=2 ] let rSave=vec 2; let tSave=vec 2; let qSave=vec 2 FST(r, rSave); FST(t, tSave); FST(q, qSave) let two= table [ #40500; 0 ] let prec= table [ #43516; #20000 ] FLD(r, a) if FSN(r) eq 0 return if FSN(r) eq -1 then [ FNEG(r); FST(r, a) ] FLDI(r, 1); FLD(q, prec) while FCM(q, prec) ne 1 do [ // t←(r+a/r)/2 FLD(t, a); FDV(t, r); FAD(t, r); FDV(t, two) // q←|r/(r-t)| if FCM(r, t) eq 0 break FLD(q, r); FSB(r, t); FDV(q, r) if FSN(q) eq -1 then FNEG(q) // r←t FLD(r, t) ] // result in a FST(r, a) FLD(r, rSave); FLD(t, tSave); FLD(q, qSave) return ] FatalError("Procedure SquareRoot not there!") ] //*************************************************************** // keyboard input (with DISPLAY output) //*************************************************************** and getLine(stream; numargs n) = valof [getLine //string input terminated by carriage-return or escape //returns string or 0 if n eq 0 then stream=dsp manifest [ s=20 ] let bsize, ncmax=s, s/2 let b=getBlock(bsize) unless b resultis giveUp("[getLine]") b!0=0 let nc, lc=0, 0 [loop let c=Gets(keys) switchon c into [ case #33: case $*N: // escape or carriage return => return string or 0 test nc ifso [ Puts(stream, $*N) b>>STRING.length=nc resultis b ] ifnot [ putBlock(b) resultis 0 ] case #10: // back space => delete last character if nc ne 0 then [ Puts(stream, $\) Puts(stream, b>>STRING.char↑nc) nc=nc-1 endcase ] case #177: // delete => delete line Wss(stream, " XXX ") nc=0 endcase default: Puts(stream, c) // pack new character into string nc=nc+1 if nc eq ncmax then [ bsize=bsize+s ncmax=ncmax+s/2 let d=b b=getBlock(bsize) unless b resultis giveUp("[getLine]", d) for i=0 to bsize-s-1 do b!i=d!i putBlock(d) ] b>>STRING.char↑nc=c ] ]loop repeat ]getLine //*************************************************************** // general stream output //*************************************************************** and typeForm(f1, d1, f2, d2, f3, d3, f4, d4, nil, nil, nil, nil, nil, nil, nil, nil; numargs n) be [ let p=lv f1 for i=0 to n-2 by 2 do sTypeF(dsp, p!i, p!(i+1)) ] and sTypeForm(s, f1, d1, f2, d2, f3, d3, f4, d4, nil, nil, nil, nil, nil, nil; numargs n) be [ let p=lv f1 for i=0 to n-3 by 2 do sTypeF(s, p!i, p!(i+1)) ] and sTypeF(stream, f, data) be [TypeF switchon f into [ // floating point case -2: sTypeFloat(stream, data); endcase // unsigned octal case -1: Wos(stream, data); endcase //string case 0: Wss(stream, data); endcase //character case 1: Puts(stream, data); endcase //integer (f is radix) default: Wns(stream, data, 0, f) ] ]TypeF and sTypeFloat(stream, lvnum) be [sTypeFloat compileif getFloat then [ FLD(1, lvnum) let p=FSN(1) if p eq 0 then [ Puts(stream, $0); return ] if p eq -1 then [ FNEG(1); Puts(stream, $-) ] FLDV(2, table [ 0; 1; #100000; 4 ]); //fuz1 = 1+2e-9 FML(2, 1) ; //n←fuz1*Number FLDI(3, 1); FLDI(4, 10) FLD(5, 2) //number let p=0 while FCM(5, 4) eq 1 do [ FDV(5, 4); p=p+1 ] while FCM(5, 3) eq -1 do [ FML(5, 4); p=p-1 ] // ac5 has a number between 1 and 10, and p has power FLD(6, table [ #031325; #163073 ]) //fuz2 = 5e-9 FML(6, 2) //s←fuz2 * n let q=p test p gr 7 % p ls -3 then p=0 or q=0 test p ls 0 ifso [ Puts(stream, $0); Puts(stream, $.) for i=p to -2 do Puts(stream, $0) for i=1 to -p do FDV(6, 4) //s=s e p ] ifnot for i=1 to p do FML(6, 4) // now print (s suppresses trailing zeroes) for i=1 to 9 do [ let ipart=FTR(5) Puts(stream, $0+ipart) p=p-1 FLDI(7, ipart); FSB(5, 7); FML(5, 4) if p ls 0 then [ if p eq -1 then Puts(stream, $.) FML(6, 4); //s←s*10 if FCM(5, 6) eq -1 then break ] ] if q then [ Puts(stream, $E); Wns(stream, q) ] return ] Wss(stream, " ### ") ]sTypeFloat