// FtpPListImp1.bcpl -- Property list implementation routines
// Copyright Xerox Corporation 1979, 1981, 1982
// Last modified May 13, 1982  1:17 PM by Boggs

get "FtpProt.decl"

external
[
// outgoing procedures
GenStringProp; ScanStringProp; InitStringProp; FreeStringProp
GenNumberProp; ScanNumberProp; InitNumberProp
GenKeywordProp; ScanKeywordProp; InitKeywordProp

// incoming procedures
PropError; Nin
Free; MoveBlock
ExtractSubstring; PutTemplate; Puts
EnumerateKeywordTable; LookupKeyword

// incoming statics
sysZone; CtxRunning
]

structure String [ length byte; char↑1,1 byte ]

//-----------------------------------------------------------------------------------------
let GenStringProp(prop, nil, name, pList) be
//-----------------------------------------------------------------------------------------
[
let QuotedWss(stream, string) be
   for i = 1 to string>>String.length do
      [
      let char = string>>String.char↑i
      if char eq $) % char eq $( % char eq QuoteChar then
         Puts(stream, QuoteChar)
      Puts(stream, char)
      ]
let string = pList!(prop>>Prop.pOffset)
if string ne 0 then
   PutTemplate(CtxRunning>>FtpCtx.dbls, "($S $P)", name, QuotedWss, string)
]

//-----------------------------------------------------------------------------------------
and ScanStringProp(prop, nil, name, v) = valof
//-----------------------------------------------------------------------------------------
[
if (v!0)!(prop>>Prop.pOffset) ne 0 then
   Free(sysZone, (v!0)!(prop>>Prop.pOffset))
(v!0)!(prop>>Prop.pOffset) = ExtractSubstring(v!1)
resultis true
]

//-----------------------------------------------------------------------------------------
and InitStringProp(prop, nil, nil, v) be
//-----------------------------------------------------------------------------------------
if (v!1)!(prop>>Prop.pOffset) ne 0 then
   (v!0)!(prop>>Prop.pOffset) = ExtractSubstring((v!1)!(prop>>Prop.pOffset))

//-----------------------------------------------------------------------------------------
and FreeStringProp(prop, nil, nil, pList) be
//-----------------------------------------------------------------------------------------
   if pList!(prop>>Prop.pOffset) ne 0 then
       Free(sysZone, pList!(prop>>Prop.pOffset))

//-----------------------------------------------------------------------------------------
and GenNumberProp(prop, nil, name, pList) be
//-----------------------------------------------------------------------------------------
[
let lvNumber = pList+(prop>>Prop.pOffset)
test prop>>Prop.pExtra  //true if double precision
   ifnot if lvNumber!0 ne 0 then
      PutTemplate(CtxRunning>>FtpCtx.dbls, "($S $UD)", name, lvNumber!0)
   ifso if lvNumber!0 ne 0 % lvNumber!1 ne 0 then
      PutTemplate(CtxRunning>>FtpCtx.dbls, "($S $EUD)", name, lvNumber)
]

//-----------------------------------------------------------------------------------------
and ScanNumberProp(prop, nil, name, v) =
//-----------------------------------------------------------------------------------------
   Nin(v!1, (v!0)+prop>>Prop.pOffset, prop>>Prop.pExtra)?
    true, PropError(prop, name)

//-----------------------------------------------------------------------------------------
and InitNumberProp(prop, nil, nil, v) be
//-----------------------------------------------------------------------------------------
   MoveBlock((v!0)+(prop>>Prop.pOffset), (v!1)+(prop>>Prop.pOffset),
    prop>>Prop.pExtra? 2, 1)

//-----------------------------------------------------------------------------------------
and GenKeywordProp(prop, nil, name, pList) be
//-----------------------------------------------------------------------------------------
[
let v = vec 1; v!0 = name; v!1 = pList!(prop>>Prop.pOffset)
let Gen(kte, nil, keyword, v) be if kte!0 eq v!1 then
   PutTemplate(CtxRunning>>FtpCtx.dbls, "($S $S)", v!0, keyword)
if v!1 ne 0 then EnumerateKeywordTable(prop>>Prop.pExtra, Gen, v)
]

//-----------------------------------------------------------------------------------------
and ScanKeywordProp(prop, nil, name, v) = valof
//-----------------------------------------------------------------------------------------
[
let kte = LookupKeyword(prop>>Prop.pExtra, v!1)
test kte ne 0
   ifso
      [
      (v!0)!(prop>>Prop.pOffset) = kte!0
      resultis true
      ]
   ifnot resultis PropError(prop, name)
]

//-----------------------------------------------------------------------------------------
and InitKeywordProp(prop, nil, nil, v) be
//-----------------------------------------------------------------------------------------
   (v!0)!(prop>>Prop.pOffset) = (v!1)!(prop>>Prop.pOffset)