// Copyright Xerox Corporation 1979
get "streams.d"
// Outgoing procedures
external [ SetupReadParam; ReadParam; EvalParam;
ReadString; AddItem; Swat ]
// Outgoing statics
external [
ReadParamStream
]
static [
ReadParamStream
]
// Incoming procedures
external [ Ws; Wss; Gets; Puts; dsp; keys; MoveBlock; OpenFile;
Endofs; CallSwat; DefaultArgs ]
external [
fpComCm //FP for file "Com.Cm"
]
static [ stringVec; swVec ]
structure STRING[
length byte
char ↑1,255 byte
]
structure [ oddblank bit 15; odd bit ]
structure [ left byte; right byte ]
let SetupReadParam(aStringVec, aSwVec, aS, tempSwVec; numargs na) be [
let comName=vec 256
DefaultArgs(lv na)
ReadParamStream=(aS ne 0 ? aS,
OpenFile("Com.Cm", ksTypeReadOnly, charItem, 0, fpComCm))
stringVec=aStringVec; swVec=aSwVec
ReadParam(0, 0, (stringVec ne 0 ? stringVec, comName),
tempSwVec)
]
and ReadParam(type, prompt, resultVec, aSwVec, returnOnNull;
numargs na)=valof [
DefaultArgs(lv na)
let name=vec 256; let sw=vec 128; let c=nil
name!0=0; sw!0=0
let skipBlanks=true
while true do [
c=GetComChar(skipBlanks)
skipBlanks=false
if c eq $/ % c eq $*S % c eq $*N then break
AddItem(name, c)
]
if c eq $/ then while true do [
c=GetComChar(false); if c eq $/ then loop
if c eq $*S % c eq $*N then break
if c eq $! then [ CallSwat("Debug break. "); loop ]
AddItem(sw, c)
]
if resultVec eq 0 & stringVec ne 0 then resultVec=stringVec
if resultVec ne 0 then MoveBlock(resultVec, name, name!0+1)
if aSwVec eq 0 & swVec ne 0 then aSwVec=swVec
if aSwVec ne 0 then MoveBlock(aSwVec, sw, sw!0+1)
if prompt eq -1 then [ returnOnNull=true; prompt=0 ]
if returnOnNull & name!0 eq 0 resultis -1
resultis EvalParam(name, type, prompt, resultVec)
]
and EvalParam(name, type, prompt, resultVec; numargs na)=valof [
// two-character types
manifest [ ic=$I * #400 + $C; iw=$I * #400 + $W;
oc=$O * #400 + $C; ow=$O * #400 + $W;
ef=$E *#400 +$F
]
structure SS[ length byte; c1 byte; c2 byte; blank byte ]
let packedName=vec 128
let v=nil; let ft=nil; let radix=8
DefaultArgs(lv na, 2)
if na ls 4 then resultVec=name
if type gr 256 then [
test type>>SS.length eq 1
ifso type=type>>SS.c1
ifnot type=type>>SS.c1 * #400 + type>>SS.c2
]
if prompt eq 0 then prompt="Try again: "
if name!0 eq 0 then goto GetNewName
Retry: PackString(packedName, name)
switchon type into [
case ic:
case $I: ft=0
LOpenFile: v=0
if name!0 then v=OpenFile(packedName,
(table [ ksTypeReadOnly;
ksTypeReadOnly;
ksTypeWriteOnly;
ksTypeWriteOnly;
ksTypeReadWrite;
ksTypeReadWrite ] )!ft,
((ft eq 0%ft eq 2)? charItem,wordItem))
if v ne 0 then [
if resultVec ne 0 then goto RetPackedName
endcase
]
Ws("*NCouldn't open "); Ws(packedName)
goto GetNewName
case iw: ft=1; goto LOpenFile
case oc:
case $O: ft=2; goto LOpenFile
case ow: ft=3; goto LOpenFile
case $F: ft=4; goto LOpenFile
case ef: ft=5; goto LOpenFile
case $B: radix=8
GetNumber: [gn let e=name!0; let b=1
switchon name!e into [
case $d:
case $D: radix=10; e=e-1; endcase
case $o:
case $O:
case $b:
case $B: radix=8; e=e-1; endcase
default: endcase
]
if name!b eq $# then [ radix=8; b=b+1 ]
v=0
for i=b to e do [
let d=name!i-$0
if d ls 0 % d ge radix then [
Ws("*N"); Ws(packedName)
Ws(" isn't a proper ")
Ws((radix eq 8 ? "octal", "decimal"))
Ws(" number")
goto GetNewName
]
v=v*radix+d
]
]gn
endcase
case $D: radix=10; goto GetNumber
case $P: v=resultVec
RetPackedName: test resultVec ne 0
ifso MoveBlock(resultVec, packedName, (name!0 rshift 1)+1)
ifnot
NoResultVec: CallSwat("No place to put the packed string")
endcase
case 0: v=resultVec
test resultVec ne 0
ifso MoveBlock(resultVec, name, name!0+1)
ifnot goto NoResultVec
endcase
default: CallSwat("Undefined type")
]
resultis v
GetNewName: Ws("*N"); Ws(prompt)
ReadString(name, "/*S*N", keys, true, prompt)
Puts(dsp, $*N); goto Retry
]
and ReadString(result, breaks, inStream, editFlag, prompt;
numargs na)=valof [
DefaultArgs(lv na, 1, "*N", keys, false, "")
if inStream eq keys & (editFlag eq false
% editFlag eq true) then editFlag=dsp
// avoid using stsize or stdec
let lb=breaks>>STRING.length
let bv=vec 256
for i=1 to lb do [
let j=i rshift 1
bv!i=(i<<odd ? breaks!j<<right, breaks!j<<left)
]
[ result!0=0
while true do [
let c=Gets(inStream)
for i=1 to lb do if bv!i eq c then resultis c
if editFlag then switchon c into [
Del: case #177: Wss(editFlag, "XXX*N")
Wss(editFlag, prompt); break
case $H-#100: case $A-#100:
if result!0 eq 0 then goto Del
Puts(editFlag, $\)
Puts(editFlag, result!(result!0))
result!0=result!0-1; loop
]
AddItem(result, c)
if editFlag then Puts(editFlag, c)
]
loop
] repeat
]
and GetComChar(skipBlanks)=valof [
while true do [
let c=Endofs(ReadParamStream) ? $*N,
Gets(ReadParamStream)
if c eq $*S & skipBlanks then loop
resultis c
]
]
and AddItem(vector, value) be [
vector!0=vector!0+1
vector!(vector!0)=value
]
and PackString(dest, source) be [
dest>>STRING.length=source!0
l6: for i=1 to source!0 do [
let j=i rshift 1
l7: test i<<odd ifso dest!j<<right=source!i
ifnot [ dest!j=0; dest!j<<left=source!i]
]
]