// FtpPlistImp2.bcpl -- More property list implementation routines // Copyright Xerox Corporation, 1981, 1982, 1983 // Last modified August 10, 1983 5:38 PM by Boggs get "FtpProt.decl" get "Time.d" external [ // outgoing procedures GenDateProp; ScanDateProp GenBitProp; ScanBitProp ParseDate; WritePTV; PropError; Nin // incoming procedures FTPM; Zero; MoveBlock; PutTemplate; MulPlus32x16 EnumerateKeywordTable; LookupKeyword WRITEUDT; UNPACKDT; PACKDT; FINDMONTH // incoming statics pListKT; CtxRunning ] structure String [ length byte; char↑1,2 byte ] //----------------------------------------------------------------------------------------- let GenDateProp(prop, nil, name, pl) be //----------------------------------------------------------------------------------------- [ let ptv = pl + prop>>Prop.pOffset if ptv>>Time.h ne 0 then PutTemplate(CtxRunning>>FtpCtx.dbls, "($S $P)", name, WritePTV, ptv) ] //----------------------------------------------------------------------------------------- and ScanDateProp(prop, nil, name, v) = //----------------------------------------------------------------------------------------- ParseDate(v!1, (v!0)+prop>>Prop.pOffset)? true, PropError(prop, name) //----------------------------------------------------------------------------------------- and GenBitProp(prop, nil, name, pl) be //----------------------------------------------------------------------------------------- [ if pl>>PL.DPRP eq 0 return let GenBit(prop, nil, name, i) be if prop>>Prop.pDPRP eq 1b15 rshift i then PutTemplate(CtxRunning>>FtpCtx.dbls, "(Desired-property $S)", name) for i = 0 to 15 if (pl>>PL.DPRP & 1b15 rshift i) ne 0 then EnumerateKeywordTable(pListKT, GenBit, i) ] //----------------------------------------------------------------------------------------- and ScanBitProp(prop, nil, name, v) = valof //----------------------------------------------------------------------------------------- [ let kte = LookupKeyword(pListKT, v!1) test kte ne 0 ifso [ (v!0)!(prop>>Prop.pOffset) = (v!0)!(prop>>Prop.pOffset) % kte>>Prop.pDPRP resultis true ] ifnot resultis PropError(prop, name) ] //----------------------------------------------------------------------------------------- and ParseDate(string, ptv) = valof //----------------------------------------------------------------------------------------- // Parses the string-format date in string into an Alto-format date in ptv. // Returns true if successful, false if not. // "day-month-year hour:minute:second [zone]" // zone:={{A|E|C|M|P|Y|H}{S|D}T}|GMT|{{+|-}hh[:mm]} [ let utv = vec lenUTV; Zero(utv, lenUTV) let temp, index = vec 10, 1 utv>>UTV.day = GetNumber(string, lv index) GetToken(string, temp, lv index) utv>>UTV.month = FINDMONTH(temp) utv>>UTV.year = GetNumber(string, lv index) +1900 utv>>UTV.hour = GetNumber(string, lv index) utv>>UTV.minute = GetNumber(string, lv index) utv>>UTV.second = GetNumber(string, lv index) while index le string>>String.length do [ //scan for + or - let char = string>>String.char↑index if AlphaNumeric(char) break index = index +1 if char eq $- % char eq $+ then utv>>UTV.zone.sign = char eq $- ] GetToken(string, temp, lv index) let zone = temp>>String.length ne 0 if zone then [ let char = temp>>String.char↑1 test char ge $0 & char le $9 ifso [ let hour = nil; Nin(temp, lv hour); utv>>UTV.zone.hour = hour utv>>UTV.zone.minute = GetNumber(string, lv index) ] ifnot [ utv>>UTV.zone.hour = selecton char & 137b into [ case $A: 4 // Atlantic case $E: 5 // Eastern case $C: 6 // Central case $M: 7 // Mountain case $P: 8 // Pacific case $Y: 9 // Youkon case $H: 10 // Hawaiian default: 0 // also GMT ] char = temp>>String.char↑2 utv>>UTV.daylight = char eq $D % char eq $d ] ] resultis PACKDT(utv, ptv, zone) eq 0 ] //----------------------------------------------------------------------------------------- and GetToken(string, lvDest, lvIndex) be //----------------------------------------------------------------------------------------- [ while @lvIndex le string>>String.length do // strip leading punctuation [ if AlphaNumeric(string>>String.char↑(@lvIndex)) break @lvIndex = @lvIndex +1 ] let length = 0 // accumulate token while @lvIndex le string>>String.length & length ls 19 do [ lvDest>>String.char↑(length+1) = string>>String.char↑(@lvIndex) length = length +1 @lvIndex = @lvIndex +1 unless AlphaNumeric(string>>String.char↑(@lvIndex)) break ] lvDest>>String.length = length ] //----------------------------------------------------------------------------------------- and AlphaNumeric(char) = (char ge $0 & char le $9) % (char ge $A & char le $Z) % (char ge $a & char le $z) //----------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------- and GetNumber(string, lvIndex) = valof //----------------------------------------------------------------------------------------- [ let temp = vec 10 GetToken(string, temp, lvIndex) let number = 0 Nin(temp, lv number) resultis number ] //----------------------------------------------------------------------------------------- and WritePTV(stream, ptv) be //----------------------------------------------------------------------------------------- [ let utv = vec lenUTV if ptv!0 ne 0 then [ UNPACKDT(ptv, utv) WRITEUDT(stream, utv, true) ] ] //----------------------------------------------------------------------------------------- and PropError(prop, name) = valof //----------------------------------------------------------------------------------------- [ FTPM(markNo, prop>>Prop.pErrSubCode, "Malformed $S", false, name) resultis false ] //----------------------------------------------------------------------------------------- and Nin(string, lvDest, double; numargs na) = valof //----------------------------------------------------------------------------------------- [ if na ls 3 then double = false let start = 1 for i = 1 to string>>String.length do if string>>String.char↑i ne $*S then [ start = i; break ] let number = vec 1; Zero(number, 2) for i = start to string>>String.length do [ let char = string>>String.char↑i if char ls $0 % char gr $9 then resultis false MulPlus32x16(char-$0, 10, number) ] test double ifnot lvDest!0 = number!1 ifso MoveBlock(lvDest, number, 2) resultis true ]