// UtilStr.bcpl -- miscellaneous utility and string procedures // 19 October 1976 by B.L. Parsley // 8 March 1977 by B.L. Parsley // commented out (//FLOAT) all references to FloatStr package get "UtilStr.D" // outgoing procedures external [ // string procedutes CopyString // (sourceStr, destStr) -> destStr AppendChar // (char, destStr) -> destStr AppendString // (sourceStr, destStr) -> destStr AppendNum // (number, destStr, [radix/10]) -> destStr MakeString // (destStr, radix,value, [radix,value, ...]) -> destStr ImbedChar // (char, destStr, [index/destStr>>SL+1]) -> destStr ExtractString // (sStr, dStr, bIndex, [eIndex/sStr>>SL+1]) -> destStr SearchChar // (str, char, [index/0]) -> index/0 SearchString // (str1, str2, [index/0, [sw/false]]) -> index/0 StringEqual // (str1, str2, [sw/false]) -> true/false StringToValue // (sourceStr, [radix/10, [pointer]]) -> value StrToValErr // (str, char, radix) ValueToString // (value, destStr, [radix/10]) -> destStr ] // incoming procedures external [ MoveBlock Allocate Wss CallSwat ] // Procedures let CopyString (sourceStr, destStr) = valof [ MoveBlock (destStr, sourceStr, (sourceStr>>SL rshift 1) + 1) resultis destStr ] and AppendChar (char, destStr) = valof [ let strL = destStr>>SL + 1 destStr>>CH↑strL = char destStr>>SL = strL resultis destStr ] and AppendString (sourceStr, destStr) = valof [ let strLS, strLD = sourceStr>>SL, destStr>>SL for i = 1 to strLS do destStr>>CH↑(strLD + i) = sourceStr>>CH↑i destStr>>SL = strLD + strLS resultis destStr ] and AppendNum (number, destStr, radix; numargs na) = valof [ let str = vec lSTRING resultis AppendString (ValueToString (number, str, (na eq 3 ? radix, 10)), destStr) ] and MakeString (destStr, radix0,val0, nil,nil, nil,nil, nil,nil, nil,nil, nil,nil, nil,nil, nil,nil, nil,nil, nil,nil; numargs na) be [ let arg = lv radix0 let str = vec lSTRING destStr!0 = 0 for i = 0 to na - 2 by 2 do AppendString (ValueToString (arg!(i+1), str, arg!i), destStr) ] and ImbedChar (char, destStr, index; numargs na) = valof [ let strL = destStr>>SL if na ls 3 do index = strL + 1 for i = strL to index by -1 do destStr>>CH↑(i + 1) = destStr>>CH↑i destStr>>CH↑index = char destStr>>SL = strL + 1 resultis destStr ] and ExtractString (sourceStr, destStr, bIndex, eIndex; numargs na) = valof [ let length = sourceStr>>SL - bIndex if na eq 4 do [ let x = eIndex - bIndex - 1; if x ls length do length = x ] for i = 1 to length do destStr>>CH↑i = sourceStr>>CH↑(bIndex + i) destStr>>SL = length gr 0 ? length, 0 resultis destStr ] and SearchChar (str, char, index; numargs na) = valof [ for idx = (na eq 3 ? index + 1, 1) to str>>SL do if str>>CH↑idx eq char do resultis idx resultis 0 ] and SearchString (str1, str2, index, sw; numargs na) = valof [ if na ls 4 do sw = false let str1L, str2L = str1>>SL, str2>>SL for idx = (na ge 3 ? index, 0) to str1L - str2L do [ let strEq = true for j = 1 to str2L do [ let c1, c2 = str1>>CH↑(idx + j), str2>>CH↑j unless sw do [ if $a le c1 & c1 le $z do c1 = c1 - #40 if $a le c2 & c2 le $z do c2 = c2 - #40 ] if c1 ne c2 do [ strEq = false; break ] ] if strEq do resultis idx + str2L ] resultis 0 ] and StringEqual (str1, str2, sw; numargs na) = valof [ let sl = str1>>SL if sl ne str2>>SL do resultis false if na ls 3 do sw = false for i = 1 to sl do [ let c1, c2 = str1>>CH↑i, str2>>CH↑i unless sw do [ if $a le c1 & c1 le $z do c1 = c1 - #40 if $a le c2 & c2 le $z do c2 = c2 - #40 ] if c1 ne c2 do resultis false ] resultis true ] and StringToValue (sourceStr, radix, pointer; numargs na) = valof [ if na ls 2 do radix = 10 let strL = sourceStr>>SL let str1c = (strL eq 0 ? (na eq 3 ? pointer, 0), sourceStr>>CH↑1) switchon radix into [ case radixFileName: for i = 1 to strL do [ let c = sourceStr>>CH↑i unless ($a le c & c le $z) % ($A le c & c le $Z) % ($0 le c & c le $9) % c eq $. % c eq $! % c eq $$ % c eq $+ % c eq $- do StrToValErr (sourceStr, c, radix) ] // no endcase case radixString: [ MoveBlock (pointer, sourceStr, (sourceStr>>SL rshift 1) + 1); resultis pointer ] case radixSwitch: resultis str1c eq $Y % str1c eq $y % str1c eq $T % str1c eq $t case radixCharStr: resultis str1c case radixCharCode: [ if str1c eq $** do [ sourceStr>>CH↑1 = $0; resultis StringToValue (sourceStr, 8) ] resultis str1c ] //FLOAT case radixFloatS: //FLOAT case radixFloat: //FLOAT [ //FLOAT if StrToFPNum eq 0 do CallSwat ("StrToFPNum not loaded") //FLOAT resultis StrToFPNum (sourceStr, pointer) //FLOAT ] default: [ let n = strL eq 0 ? str1c, 0 if str1c eq $- do sourceStr>>CH↑1 = $0 for i = 1 to strL do [ let x = sourceStr>>CH↑i - $0 unless (0 le x & x le radix - 1) do StrToValErr (sourceStr, x + $0, radix) n = n*radix + x ] resultis str1c eq $- ? -n, n ] ] ] and StrToValErr (str, char, radix) be CallSwat ("StringToValue error in: ", str) and ValueToString (value, destStr, radix; numargs na) = valof [ if na ls 3 do radix = 10 destStr!0 = 0 switchon radix into [ case radixFloatS: case radixFileName: case radixString: resultis CopyString (value, destStr) case radixSwitch: resultis AppendChar ((value ? $Y, $N), destStr) case radixCharStr: resultis AppendChar (value, destStr) case radixCharCode: [ if value le cntrlZ do [ AppendChar ($↑, destStr); value = value + #100 ] resultis AppendChar (value, destStr) ] //FLOAT case radixFloat: //FLOAT [ //FLOAT if FPNumToStr eq 0 do CallSwat ("FPNumToStr not loaded") //FLOAT resultis FPNumToStr (value, destStr) //FLOAT ] case 2: [ for col = 1 to 16 do AppendChar ($0 + (value rshift (16 - col))<<ODD, destStr) endcase ] case 8: [ let zero = true for i = 0 to 16/3 do [ let v = (value rshift 3*(16/3 - i)) & #7 if v eq 0 & zero loop AppendChar ($0 + v, destStr) zero = false ] if zero do destStr!0 = 1b8 + $0 endcase ] case 16: [ for col = 1 to 4 do [ let v = (value rshift 4*(4 - col)) & #17 AppendChar ((v le 9 ? ($0 + v), ($A + (v - 10))), destStr) ] endcase ] default: [ let min = value ls 0 if min do value = -value [ ImbedChar ((value rem radix) + $0, destStr, 1) value = value/radix ] repeatuntil value eq 0 if min do ImbedChar ($-, destStr, 1) ] ] resultis destStr ]