-- Copyright: Mario Schweigler (C) 2005-2006
-- Institution: Computing Laboratory, University of Kent, Canterbury, UK
-- Description: pony internal code file 3

-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-- MA 02110-1301, USA.

--{{{  Compiler declarations
#INCLUDE "ponylib.inc"
#INCLUDE "ponyint.inc"
#USE "ponyintaux.tce"
#USE "ponyint1.tce"
#USE "ponyint2.tce"
--}}}

--{{{  Processes

--{{{  PROC pony.int.nct.handler
-- NCT-handler
-- Parameters: own.nct.id           | VAL: own NCT-ID
--             initial.cli.claimed  | VAL: client-end initially claimed?
--             initial.svr.claimed  | VAL: server-end initially claimed?
--             initial.claimed.node | VAL: node of initially claimed ends
--             nct.handle.svr       | server-end of NCT-handle
--             link.mgr.handle      | link-manager-handle (client-end)
--             output.msgs          | VAL: output messages?
--             int.msg.handle       | internal message-handle (client-end)
PROC pony.int.nct.handler (VAL INT own.nct.id,
                           VAL BOOL initial.cli.claimed, initial.svr.claimed,
                           VAL INT initial.claimed.node,
                           PONY.INT.NCTHANDLE? nct.handle.svr,
                           SHARED PONY.INT.LINKMGRHANDLE! link.mgr.handle,
                           VAL BOOL output.msgs,
                           SHARED PONY.INT.MSGHANDLE! int.msg.handle)
  --{{{  Constants
  -- Pending-state
  VAL INT PENDINGSTATE.NONE IS 0:
  VAL INT PENDINGSTATE.SVR IS 1:
  VAL INT PENDINGSTATE.CLI IS 2:
  --}}}
  --{{{  Variables
  -- Array of nodes claiming client-end
  INITIAL MOBILE []INT cli.claim.array IS MOBILE [500]INT:
  -- Index of the first element
  --   (if buffer empty, it equals `cli.end.ptr')
  INITIAL INT cli.start.ptr IS 0:
  -- Index of next element to be added
  --   ((cli.end.ptr + (SIZE cli.claim.array)) - cli.start.ptr) \ (SIZE cli.claim.array)
  --   is the number of elements stored in the buffer
  INITIAL INT cli.end.ptr IS 0:
  -- Same for server-end
  INITIAL MOBILE []INT svr.claim.array IS MOBILE [500]INT:
  INITIAL INT svr.start.ptr IS 0:
  INITIAL INT svr.end.ptr IS 0:
  -- Pending-state
  INITIAL INT pending.state IS PENDINGSTATE.NONE:
  --}}}
  --{{{  Link-handles
  SHARED PONY.INT.LINKHANDLE! cli.link.handle:
  SHARED PONY.INT.LINKHANDLE! svr.link.handle:
  --}}}
  SEQ
    --{{{  Initialise variables and link-handles
    IF
      initial.cli.claimed
        SEQ
          -- First element of client-claim-array
          cli.claim.array[0] := initial.claimed.node
          cli.end.ptr := 1
          -- Get link-handle to client-end node from link-manager
          CLAIM link.mgr.handle
            SEQ
              --{{{  OUT message
              IF
                output.msgs
                  CLAIM int.msg.handle
                    SEQ
                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                      int.msg.handle[to.handler] ! msg.str; ": OUT linkmgrh: get.link.handle; "
                      int.msg.handle[to.handler] ! msg.int; initial.claimed.node
                      int.msg.handle[to.handler] ! msg.end; FALSE
                TRUE
                  SKIP
              --}}}
              -- Carrying: node-ID
              link.mgr.handle[to.mgr] ! get.link.handle; initial.claimed.node
              -- Get reply
              -- Carrying: link-handle
              link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; cli.link.handle
              --{{{  IN message
              IF
                output.msgs
                  CLAIM int.msg.handle
                    SEQ
                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                      int.msg.handle[to.handler] ! msg.str; ": IN linkmgrh: get.link.handle.confirm; [cli-end]"
                      int.msg.handle[to.handler] ! msg.end; FALSE
                TRUE
                  SKIP
              --}}}
      TRUE
        SKIP
    IF
      initial.svr.claimed
        SEQ
          -- First element of server-claim-array
          svr.claim.array[0] := initial.claimed.node
          svr.end.ptr := 1
          -- Get link-handle to server-end node from link-manager
          CLAIM link.mgr.handle
            SEQ
              --{{{  OUT message
              IF
                output.msgs
                  CLAIM int.msg.handle
                    SEQ
                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                      int.msg.handle[to.handler] ! msg.str; ": OUT linkmgrh: get.link.handle; "
                      int.msg.handle[to.handler] ! msg.int; initial.claimed.node
                      int.msg.handle[to.handler] ! msg.end; FALSE
                TRUE
                  SKIP
              --}}}
              -- Carrying: node-ID
              link.mgr.handle[to.mgr] ! get.link.handle; initial.claimed.node
              -- Get reply
              -- Carrying: link-handle
              link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; svr.link.handle
              --{{{  IN message
              IF
                output.msgs
                  CLAIM int.msg.handle
                    SEQ
                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                      int.msg.handle[to.handler] ! msg.str; ": IN linkmgrh: get.link.handle.confirm; [cli-end]"
                      int.msg.handle[to.handler] ! msg.end; FALSE
                TRUE
                  SKIP
              --}}}
      TRUE
        SKIP
    --}}}
    INITIAL BOOL running IS TRUE:
    WHILE running
      nct.handle.svr[to.handler] ? CASE
        --{{{  Claim client-end
        INT node.id:
        -- Carrying: node-ID of the CTB-handler making the request
        claim.cli; node.id
          SEQ
            --{{{  IN message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                    int.msg.handle[to.handler] ! msg.str; ": IN ncth: claim.cli; "
                    int.msg.handle[to.handler] ! msg.int; node.id
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            --{{{  Double buffer size if buffer full
            --       (full means there are ((SIZE cli.claim.array) - 1) elements)
            IF
              (((cli.end.ptr + (SIZE cli.claim.array)) - cli.start.ptr) \ (SIZE cli.claim.array)) = ((SIZE cli.claim.array) - 1)
                -- New array double the size of the current one
                INITIAL MOBILE []INT new.cli.claim.array IS MOBILE [((SIZE cli.claim.array) * 2)]INT:
                SEQ
                  -- Copy elements into new array
                  IF
                    cli.start.ptr = 0
                      [new.cli.claim.array FOR cli.end.ptr] := [cli.claim.array FOR cli.end.ptr]
                    TRUE
                      SEQ
                        [new.cli.claim.array FOR ((SIZE cli.claim.array) - cli.start.ptr)] :=
                          [cli.claim.array FROM cli.start.ptr FOR ((SIZE cli.claim.array) - cli.start.ptr)]
                        [new.cli.claim.array FROM ((SIZE cli.claim.array) - cli.start.ptr) FOR cli.end.ptr] :=
                          [cli.claim.array FOR cli.end.ptr]
                  -- Adapt pointers
                  cli.start.ptr := 0
                  cli.end.ptr := (SIZE cli.claim.array) - 1
                  -- Use new array
                  cli.claim.array := new.cli.claim.array
              TRUE
                SKIP
            --}}}
            -- Update buffer element
            cli.claim.array[cli.end.ptr] := node.id
            -- Move end-pointer
            cli.end.ptr := (cli.end.ptr + 1) \ (SIZE cli.claim.array)
            IF
              -- There was no client-end in queue before
              (((cli.end.ptr + (SIZE cli.claim.array)) - cli.start.ptr) \ (SIZE cli.claim.array)) = 1
                IF
                  --{{{  Currently no server-end in queue
                  svr.start.ptr = svr.end.ptr
                    SEQ
                      -- Get link-handle to client-end node from link-manager
                      CLAIM link.mgr.handle
                        SEQ
                          --{{{  OUT message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": OUT linkmgrh: get.link.handle; "
                                  int.msg.handle[to.handler] ! msg.int; node.id
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                          -- Carrying: node-ID
                          link.mgr.handle[to.mgr] ! get.link.handle; node.id
                          -- Get reply
                          -- Carrying: link-handle
                          link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; cli.link.handle
                          --{{{  IN message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": IN linkmgrh: get.link.handle.confirm; [cli-end]"
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                      -- Send claim-confirmation to client-end CTB-handler (via link-handle)
                      CLAIM cli.link.handle
                        SEQ
                          --{{{  OUT message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                  int.msg.handle[to.handler] ! msg.int; node.id
                                  int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reclient.claim.confirm.nootherend; "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                          -- Carrying: NCT-ID of the recipient CTB-handler
                          cli.link.handle[to.handler] ! forctbhandler.reclient.claim.confirm.nootherend; own.nct.id
                  --}}}
                  --{{{  There is a server-end in queue
                  TRUE
                    SEQ
                      -- Send new-other-end to server-end CTB-handler (via link-handle)
                      CLAIM svr.link.handle
                        SEQ
                          --{{{  OUT message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                  int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                                  int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reserver.new.other.end; "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; "; "
                                  int.msg.handle[to.handler] ! msg.int; node.id
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                          -- Carrying: NCT-ID of the recipient CTB-handler;
                          --           node-ID of the other end's node
                          svr.link.handle[to.handler] ! forctbhandler.reserver.new.other.end;
                                                        own.nct.id; node.id
                      -- Update pending-state
                      pending.state := PENDINGSTATE.SVR
                  --}}}
              TRUE
                SKIP
        --}}}
        --{{{  Claim server-end
        INT node.id:
        -- Carrying: node-ID of the CTB-handler making the request
        claim.svr; node.id
          SEQ
            --{{{  IN message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                    int.msg.handle[to.handler] ! msg.str; ": IN ncth: claim.svr; "
                    int.msg.handle[to.handler] ! msg.int; node.id
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            --{{{  Double buffer size if buffer full
            --       (full means there are ((SIZE svr.claim.array) - 1) elements)
            IF
              (((svr.end.ptr + (SIZE svr.claim.array)) - svr.start.ptr) \ (SIZE svr.claim.array)) = ((SIZE svr.claim.array) - 1)
                -- New array double the size of the current one
                INITIAL MOBILE []INT new.svr.claim.array IS MOBILE [((SIZE svr.claim.array) * 2)]INT:
                SEQ
                  -- Copy elements into new array
                  IF
                    svr.start.ptr = 0
                      [new.svr.claim.array FOR svr.end.ptr] := [svr.claim.array FOR svr.end.ptr]
                    TRUE
                      SEQ
                        [new.svr.claim.array FOR ((SIZE svr.claim.array) - svr.start.ptr)] :=
                          [svr.claim.array FROM svr.start.ptr FOR ((SIZE svr.claim.array) - svr.start.ptr)]
                        [new.svr.claim.array FROM ((SIZE svr.claim.array) - svr.start.ptr) FOR svr.end.ptr] :=
                          [svr.claim.array FOR svr.end.ptr]
                  -- Adapt pointers
                  svr.start.ptr := 0
                  svr.end.ptr := (SIZE svr.claim.array) - 1
                  -- Use new array
                  svr.claim.array := new.svr.claim.array
              TRUE
                SKIP
            --}}}
            -- Update buffer element
            svr.claim.array[svr.end.ptr] := node.id
            -- Move end-pointer
            svr.end.ptr := (svr.end.ptr + 1) \ (SIZE svr.claim.array)
            IF
              -- There was no server-end in queue before
              (((svr.end.ptr + (SIZE svr.claim.array)) - svr.start.ptr) \ (SIZE svr.claim.array)) = 1
                IF
                  --{{{  Currently no client-end in queue
                  cli.start.ptr = cli.end.ptr
                    SEQ
                      -- Get link-handle to server-end node from link-manager
                      CLAIM link.mgr.handle
                        SEQ
                          --{{{  OUT message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": OUT linkmgrh: get.link.handle; "
                                  int.msg.handle[to.handler] ! msg.int; node.id
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                          -- Carrying: node-ID
                          link.mgr.handle[to.mgr] ! get.link.handle; node.id
                          -- Get reply
                          -- Carrying: link-handle
                          link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; svr.link.handle
                          --{{{  IN message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": IN linkmgrh: get.link.handle.confirm; [cli-end]"
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                      -- Send claim-confirmation to server-end CTB-handler (via link-handle)
                      CLAIM svr.link.handle
                        SEQ
                          --{{{  OUT message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                  int.msg.handle[to.handler] ! msg.int; node.id
                                  int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reserver.claim.confirm.nootherend; "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                          -- Carrying: NCT-ID of the recipient CTB-handler
                          svr.link.handle[to.handler] ! forctbhandler.reserver.claim.confirm.nootherend; own.nct.id
                  --}}}
                  --{{{  There is a client-end in queue
                  TRUE
                    SEQ
                      -- Send new-other-end to client-end CTB-handler (via link-handle)
                      CLAIM cli.link.handle
                        SEQ
                          --{{{  OUT message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                  int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                                  int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reclient.new.other.end; "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; "; "
                                  int.msg.handle[to.handler] ! msg.int; node.id
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                          -- Carrying: NCT-ID of the recipient CTB-handler;
                          --           node-ID of the other end's node
                          cli.link.handle[to.handler] ! forctbhandler.reclient.new.other.end;
                                                        own.nct.id; node.id
                      -- Update pending-state
                      pending.state := PENDINGSTATE.CLI
                  --}}}
              TRUE
                SKIP
        --}}}
        --{{{  Confirm new-other-end
        new.other.end.confirm
          SEQ
            --{{{  IN message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                    int.msg.handle[to.handler] ! msg.str; ": IN ncth: new.other.end.confirm"
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            IF
              --{{{  Both ends are on different nodes
              cli.claim.array[cli.start.ptr] <> svr.claim.array[svr.start.ptr]
                IF
                  --{{{  Message is from client-end node
                  pending.state = PENDINGSTATE.CLI
                    SEQ
                      -- Get link-handle to server-end node from link-manager
                      CLAIM link.mgr.handle
                        SEQ
                          --{{{  OUT message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": OUT linkmgrh: get.link.handle; "
                                  int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                          -- Carrying: node-ID
                          link.mgr.handle[to.mgr] ! get.link.handle; svr.claim.array[svr.start.ptr]
                          -- Get reply
                          -- Carrying: link-handle
                          link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; svr.link.handle
                          --{{{  IN message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": IN linkmgrh: get.link.handle.confirm; [cli-end]"
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                      -- Send claim-confirmation to server-end CTB-handler (via link-handle)
                      CLAIM svr.link.handle
                        SEQ
                          --{{{  OUT message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                  int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                                  int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reserver.claim.confirm.otherendclaimed; "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; "; "
                                  int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                          -- Carrying: NCT-ID of the recipient CTB-handler;
                          --           node-ID of the other end's node
                          svr.link.handle[to.handler] ! forctbhandler.reserver.claim.confirm.otherendclaimed;
                                                        own.nct.id; cli.claim.array[cli.start.ptr]
                  --}}}
                  --{{{  Message is from server-end node
                  TRUE
                    SEQ
                      -- Get link-handle to client-end node from link-manager
                      CLAIM link.mgr.handle
                        SEQ
                          --{{{  OUT message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": OUT linkmgrh: get.link.handle; "
                                  int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                          -- Carrying: node-ID
                          link.mgr.handle[to.mgr] ! get.link.handle; cli.claim.array[cli.start.ptr]
                          -- Get reply
                          -- Carrying: link-handle
                          link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; cli.link.handle
                          --{{{  IN message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": IN linkmgrh: get.link.handle.confirm; [cli-end]"
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                      -- Send claim-confirmation to client-end CTB-handler (via link-handle)
                      CLAIM cli.link.handle
                        SEQ
                          --{{{  OUT message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                  int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                                  int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reclient.claim.confirm.otherendclaimed; "
                                  int.msg.handle[to.handler] ! msg.int; own.nct.id
                                  int.msg.handle[to.handler] ! msg.str; "; "
                                  int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                          -- Carrying: NCT-ID of the recipient CTB-handler;
                          --           node-ID of the other end's node
                          cli.link.handle[to.handler] ! forctbhandler.reclient.claim.confirm.otherendclaimed;
                                                        own.nct.id; svr.claim.array[svr.start.ptr]
                  --}}}
              --}}}
              --{{{  Both ends on the same node (i.e. internal session)
              TRUE
                IF
                  -- Message is from client-end node
                  pending.state = PENDINGSTATE.CLI
                    svr.link.handle := cli.link.handle
                  -- Message is from server-end node
                  TRUE
                    cli.link.handle := svr.link.handle
              --}}}
            -- Update pending-state
            pending.state := PENDINGSTATE.NONE
        --}}}
        --{{{  Release client-end
        release.cli
          SEQ
            --{{{  IN message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                    int.msg.handle[to.handler] ! msg.str; ": IN ncth: release.cli"
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            --{{{  Send dummy `new-other-end' to client-end CTB-handler (via link-handle) if no reply is pending
            --       (otherwise the client-end node got a new-other-end message before)
            IF
              pending.state = PENDINGSTATE.NONE
                CLAIM cli.link.handle
                  SEQ
                    --{{{  OUT message
                    IF
                      output.msgs
                        CLAIM int.msg.handle
                          SEQ
                            int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                            int.msg.handle[to.handler] ! msg.int; own.nct.id
                            int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                            int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                            int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reclient.new.other.end; "
                            int.msg.handle[to.handler] ! msg.int; own.nct.id
                            int.msg.handle[to.handler] ! msg.str; "; -1"
                            int.msg.handle[to.handler] ! msg.end; FALSE
                      TRUE
                        SKIP
                    --}}}
                    -- Carrying: NCT-ID of the recipient CTB-handler;
                    --           node-ID of the other end's node
                    cli.link.handle[to.handler] ! forctbhandler.reclient.new.other.end; own.nct.id; -1
              TRUE
                SKIP
            --}}}
            -- Move start-pointer
            cli.start.ptr := (cli.start.ptr + 1) \ (SIZE cli.claim.array)
            IF
              --{{{  No reply pending
              pending.state = PENDINGSTATE.NONE
                IF
                  -- There is another node in client-end queue
                  cli.start.ptr <> cli.end.ptr
                    IF
                      --{{{  Currently no server-end in queue (i.e. there was no session)
                      svr.start.ptr = svr.end.ptr
                        SEQ
                          -- Get link-handle to client-end node from link-manager
                          CLAIM link.mgr.handle
                            SEQ
                              --{{{  OUT message
                              IF
                                output.msgs
                                  CLAIM int.msg.handle
                                    SEQ
                                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.str; ": OUT linkmgrh: get.link.handle; "
                                      int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                                      int.msg.handle[to.handler] ! msg.end; FALSE
                                TRUE
                                  SKIP
                              --}}}
                              -- Carrying: node-ID
                              link.mgr.handle[to.mgr] ! get.link.handle; cli.claim.array[cli.start.ptr]
                              -- Get reply
                              -- Carrying: link-handle
                              link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; cli.link.handle
                              --{{{  IN message
                              IF
                                output.msgs
                                  CLAIM int.msg.handle
                                    SEQ
                                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.str; ": IN linkmgrh: get.link.handle.confirm; [cli-end]"
                                      int.msg.handle[to.handler] ! msg.end; FALSE
                                TRUE
                                  SKIP
                              --}}}
                          -- Send claim-confirmation to client-end CTB-handler (via link-handle)
                          CLAIM cli.link.handle
                            SEQ
                              --{{{  OUT message
                              IF
                                output.msgs
                                  CLAIM int.msg.handle
                                    SEQ
                                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                      int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                                      int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reclient.claim.confirm.nootherend; "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.end; FALSE
                                TRUE
                                  SKIP
                              --}}}
                              -- Carrying: NCT-ID of the recipient CTB-handler
                              cli.link.handle[to.handler] ! forctbhandler.reclient.claim.confirm.nootherend; own.nct.id
                      --}}}
                      --{{{  There is a server-end in queue (i.e. there was a session)
                      TRUE
                        SEQ
                          -- Send new-other-end to server-end CTB-handler (via link-handle)
                          CLAIM svr.link.handle
                            SEQ
                              --{{{  OUT message
                              IF
                                output.msgs
                                  CLAIM int.msg.handle
                                    SEQ
                                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                      int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                                      int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reserver.new.other.end; "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.str; "; "
                                      int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                                      int.msg.handle[to.handler] ! msg.end; FALSE
                                TRUE
                                  SKIP
                              --}}}
                              -- Carrying: NCT-ID of the recipient CTB-handler;
                              --           node-ID of the other end's node
                              svr.link.handle[to.handler] ! forctbhandler.reserver.new.other.end;
                                                            own.nct.id; cli.claim.array[cli.start.ptr]
                          -- Update pending-state
                          pending.state := PENDINGSTATE.SVR
                      --}}}
                  TRUE
                    SKIP
              --}}}
              --{{{  Client-end reply pending
              --       (i.e. client-end node got a new-other-end message before)
              TRUE
                SEQ
                  -- Get link-handle to server-end node from link-manager
                  CLAIM link.mgr.handle
                    SEQ
                      --{{{  OUT message
                      IF
                        output.msgs
                          CLAIM int.msg.handle
                            SEQ
                              int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                              int.msg.handle[to.handler] ! msg.int; own.nct.id
                              int.msg.handle[to.handler] ! msg.str; ": OUT linkmgrh: get.link.handle; "
                              int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                              int.msg.handle[to.handler] ! msg.end; FALSE
                        TRUE
                          SKIP
                      --}}}
                      -- Carrying: node-ID
                      link.mgr.handle[to.mgr] ! get.link.handle; svr.claim.array[svr.start.ptr]
                      -- Get reply
                      -- Carrying: link-handle
                      link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; svr.link.handle
                      --{{{  IN message
                      IF
                        output.msgs
                          CLAIM int.msg.handle
                            SEQ
                              int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                              int.msg.handle[to.handler] ! msg.int; own.nct.id
                              int.msg.handle[to.handler] ! msg.str; ": IN linkmgrh: get.link.handle.confirm; [cli-end]"
                              int.msg.handle[to.handler] ! msg.end; FALSE
                        TRUE
                          SKIP
                      --}}}
                  -- Send claim-confirmation to server-end CTB-handler (via link-handle)
                  CLAIM svr.link.handle
                    SEQ
                      --{{{  OUT message
                      IF
                        output.msgs
                          CLAIM int.msg.handle
                            SEQ
                              int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                              int.msg.handle[to.handler] ! msg.int; own.nct.id
                              int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                              int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                              int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reserver.claim.confirm.nootherend; "
                              int.msg.handle[to.handler] ! msg.int; own.nct.id
                              int.msg.handle[to.handler] ! msg.end; FALSE
                        TRUE
                          SKIP
                      --}}}
                      -- Carrying: NCT-ID of the recipient CTB-handler
                      svr.link.handle[to.handler] ! forctbhandler.reserver.claim.confirm.nootherend; own.nct.id
                  IF
                    -- There is another node in client-end queue
                    cli.start.ptr <> cli.end.ptr
                      SEQ
                        -- Send new-other-end to server-end CTB-handler (via link-handle)
                        CLAIM svr.link.handle
                          SEQ
                            --{{{  OUT message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                                    int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                    int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                                    int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reserver.new.other.end; "
                                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                                    int.msg.handle[to.handler] ! msg.str; "; "
                                    int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                            -- Carrying: NCT-ID of the recipient CTB-handler;
                            --           node-ID of the other end's node
                            svr.link.handle[to.handler] ! forctbhandler.reserver.new.other.end;
                                                          own.nct.id; cli.claim.array[cli.start.ptr]
                        -- Update pending-state
                        pending.state := PENDINGSTATE.SVR
                    TRUE
                      -- Update pending-state
                      pending.state := PENDINGSTATE.NONE
              --}}}
        --}}}
        --{{{  Release server-end
        release.svr
          SEQ
            --{{{  IN message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                    int.msg.handle[to.handler] ! msg.str; ": IN ncth: release.svr"
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            --{{{  Send dummy `new-other-end' to server-end CTB-handler (via link-handle) if no reply is pending
            --       (otherwise the server-end node got a new-other-end message before)
            IF
              pending.state = PENDINGSTATE.NONE
                CLAIM svr.link.handle
                  SEQ
                    --{{{  OUT message
                    IF
                      output.msgs
                        CLAIM int.msg.handle
                          SEQ
                            int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                            int.msg.handle[to.handler] ! msg.int; own.nct.id
                            int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                            int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                            int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reserver.new.other.end; "
                            int.msg.handle[to.handler] ! msg.int; own.nct.id
                            int.msg.handle[to.handler] ! msg.str; "; -1"
                            int.msg.handle[to.handler] ! msg.end; FALSE
                      TRUE
                        SKIP
                    --}}}
                    -- Carrying: NCT-ID of the recipient CTB-handler;
                    --           node-ID of the other end's node
                    svr.link.handle[to.handler] ! forctbhandler.reserver.new.other.end; own.nct.id; -1
              TRUE
                SKIP
            --}}}
            -- Move start-pointer
            svr.start.ptr := (svr.start.ptr + 1) \ (SIZE svr.claim.array)
            IF
              --{{{  No reply pending
              pending.state = PENDINGSTATE.NONE
                IF
                  -- There is another node in server-end queue
                  svr.start.ptr <> svr.end.ptr
                    IF
                      --{{{  Currently no client-end in queue (i.e. there was no session)
                      cli.start.ptr = cli.end.ptr
                        SEQ
                          -- Get link-handle to server-end node from link-manager
                          CLAIM link.mgr.handle
                            SEQ
                              --{{{  OUT message
                              IF
                                output.msgs
                                  CLAIM int.msg.handle
                                    SEQ
                                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.str; ": OUT linkmgrh: get.link.handle; "
                                      int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                                      int.msg.handle[to.handler] ! msg.end; FALSE
                                TRUE
                                  SKIP
                              --}}}
                              -- Carrying: node-ID
                              link.mgr.handle[to.mgr] ! get.link.handle; svr.claim.array[svr.start.ptr]
                              -- Get reply
                              -- Carrying: link-handle
                              link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; svr.link.handle
                              --{{{  IN message
                              IF
                                output.msgs
                                  CLAIM int.msg.handle
                                    SEQ
                                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.str; ": IN linkmgrh: get.link.handle.confirm; [cli-end]"
                                      int.msg.handle[to.handler] ! msg.end; FALSE
                                TRUE
                                  SKIP
                              --}}}
                          -- Send claim-confirmation to server-end CTB-handler (via link-handle)
                          CLAIM svr.link.handle
                            SEQ
                              --{{{  OUT message
                              IF
                                output.msgs
                                  CLAIM int.msg.handle
                                    SEQ
                                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                      int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                                      int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reserver.claim.confirm.nootherend; "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.end; FALSE
                                TRUE
                                  SKIP
                              --}}}
                              -- Carrying: NCT-ID of the recipient CTB-handler
                              svr.link.handle[to.handler] ! forctbhandler.reserver.claim.confirm.nootherend; own.nct.id
                      --}}}
                      --{{{  There is a client-end in queue (i.e. there was a session)
                      TRUE
                        SEQ
                          -- Send new-other-end to client-end CTB-handler (via link-handle)
                          CLAIM cli.link.handle
                            SEQ
                              --{{{  OUT message
                              IF
                                output.msgs
                                  CLAIM int.msg.handle
                                    SEQ
                                      int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                      int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                                      int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reclient.new.other.end; "
                                      int.msg.handle[to.handler] ! msg.int; own.nct.id
                                      int.msg.handle[to.handler] ! msg.str; "; "
                                      int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                                      int.msg.handle[to.handler] ! msg.end; FALSE
                                TRUE
                                  SKIP
                              --}}}
                              -- Carrying: NCT-ID of the recipient CTB-handler;
                              --           node-ID of the other end's node
                              cli.link.handle[to.handler] ! forctbhandler.reclient.new.other.end;
                                                            own.nct.id; svr.claim.array[svr.start.ptr]
                          -- Update pending-state
                          pending.state := PENDINGSTATE.CLI
                      --}}}
                  TRUE
                    SKIP
              --}}}
              --{{{  Server-end reply pending
              --       (i.e. server-end node got a new-other-end message before)
              TRUE
                SEQ
                  -- Get link-handle to client-end node from link-manager
                  CLAIM link.mgr.handle
                    SEQ
                      --{{{  OUT message
                      IF
                        output.msgs
                          CLAIM int.msg.handle
                            SEQ
                              int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                              int.msg.handle[to.handler] ! msg.int; own.nct.id
                              int.msg.handle[to.handler] ! msg.str; ": OUT linkmgrh: get.link.handle; "
                              int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                              int.msg.handle[to.handler] ! msg.end; FALSE
                        TRUE
                          SKIP
                      --}}}
                      -- Carrying: node-ID
                      link.mgr.handle[to.mgr] ! get.link.handle; cli.claim.array[cli.start.ptr]
                      -- Get reply
                      -- Carrying: link-handle
                      link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; cli.link.handle
                      --{{{  IN message
                      IF
                        output.msgs
                          CLAIM int.msg.handle
                            SEQ
                              int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                              int.msg.handle[to.handler] ! msg.int; own.nct.id
                              int.msg.handle[to.handler] ! msg.str; ": IN linkmgrh: get.link.handle.confirm; [cli-end]"
                              int.msg.handle[to.handler] ! msg.end; FALSE
                        TRUE
                          SKIP
                      --}}}
                  -- Send claim-confirmation to client-end CTB-handler (via link-handle)
                  CLAIM cli.link.handle
                    SEQ
                      --{{{  OUT message
                      IF
                        output.msgs
                          CLAIM int.msg.handle
                            SEQ
                              int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                              int.msg.handle[to.handler] ! msg.int; own.nct.id
                              int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                              int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                              int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reclient.claim.confirm.nootherend; "
                              int.msg.handle[to.handler] ! msg.int; own.nct.id
                              int.msg.handle[to.handler] ! msg.end; FALSE
                        TRUE
                          SKIP
                      --}}}
                      -- Carrying: NCT-ID of the recipient CTB-handler
                      cli.link.handle[to.handler] ! forctbhandler.reclient.claim.confirm.nootherend; own.nct.id
                  IF
                    -- There is another node in server-end queue
                    svr.start.ptr <> svr.end.ptr
                      SEQ
                        -- Send new-other-end to client-end CTB-handler (via link-handle)
                        CLAIM cli.link.handle
                          SEQ
                            --{{{  OUT message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                                    int.msg.handle[to.handler] ! msg.str; ": OUT linkh "
                                    int.msg.handle[to.handler] ! msg.int; cli.claim.array[cli.start.ptr]
                                    int.msg.handle[to.handler] ! msg.str; ": forctbhandler.reclient.new.other.end; "
                                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                                    int.msg.handle[to.handler] ! msg.str; "; "
                                    int.msg.handle[to.handler] ! msg.int; svr.claim.array[svr.start.ptr]
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                            -- Carrying: NCT-ID of the recipient CTB-handler;
                            --           node-ID of the other end's node
                            cli.link.handle[to.handler] ! forctbhandler.reclient.new.other.end;
                                                          own.nct.id; svr.claim.array[svr.start.ptr]
                        -- Update pending-state
                        pending.state := PENDINGSTATE.CLI
                    TRUE
                      -- Update pending-state
                      pending.state := PENDINGSTATE.NONE
              --}}}
        --}}}
        --{{{  End-over-itself operation completed
        INT node.id:
        -- Carrying: node-ID of the CTB-handler making the request
        eoi.done; node.id
          SEQ
            --{{{  IN message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                    int.msg.handle[to.handler] ! msg.str; ": IN ncth: eoi.done; "
                    int.msg.handle[to.handler] ! msg.int; node.id
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            IF
              cli.claim.array[cli.start.ptr] = node.id
                SEQ
                  svr.claim.array[svr.start.ptr] := node.id
                  svr.link.handle := cli.link.handle
              TRUE
                SEQ
                  cli.claim.array[cli.start.ptr] := node.id
                  cli.link.handle := svr.link.handle
        --}}}
        --{{{  Shutdown
        shutdown
          SEQ
            --{{{  IN message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                    int.msg.handle[to.handler] ! msg.str; ": IN ncth: shutdown"
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            -- Leave main loop
            running := FALSE
            -- Send reply
            --{{{  OUT message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "nct.hdlr "
                    int.msg.handle[to.handler] ! msg.int; own.nct.id
                    int.msg.handle[to.handler] ! msg.str; ": OUT ncth: shutdown.confirm"
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            nct.handle.svr[from.handler] ! shutdown.confirm
        --}}}
:
--}}}
--{{{  PROC pony.int.nct.mgr
-- NCT-manager
-- Parameters: nct.mgr.handle.svr  | server-end of NCT-manager-handle
--             link.mgr.handle     | link-manager-handle (client-end)
--             output.msgs         | VAL: output messages?
--             int.msg.handle      | internal message-handle (client-end)
PROC pony.int.nct.mgr (PONY.INT.NCTMGRHANDLE? nct.mgr.handle.svr,
                       SHARED PONY.INT.LINKMGRHANDLE! link.mgr.handle,
                       VAL BOOL output.msgs,
                       SHARED PONY.INT.MSGHANDLE! int.msg.handle)
  --{{{  DATA TYPE NCT.DATA
  DATA TYPE NCT.DATA
    RECORD
      INT cli.state, svr.state, type.hash:
  :
  --}}}
  --{{{  Constants
  -- End-states
  VAL INT ENDSTATE.UNKNOWN IS 0:
  VAL INT ENDSTATE.UNSHARED.NOTYETALLOC IS 1:
  VAL INT ENDSTATE.UNSHARED.ALLOC IS 2:
  VAL INT ENDSTATE.SHARED IS 3:
  --}}}
  --{{{  Arrays and variables
  -- NCT-handle-array
  INITIAL MOBILE []SHARED PONY.INT.NCTHANDLE! nct.handle.array IS MOBILE [500]SHARED PONY.INT.NCTHANDLE!:
  -- NCT-name-array
  INITIAL MOBILE []MOBILE []BYTE nct.name.array IS MOBILE [500]MOBILE []BYTE:
  -- NCT-data-array
  INITIAL MOBILE []NCT.DATA nct.data.array IS MOBILE [500]NCT.DATA:
  -- Number of allocated NCTs
  INITIAL INT num.ncts IS 0:
  --}}}
  INITIAL BOOL running IS TRUE:
  WHILE running
    nct.mgr.handle.svr[to.mgr] ? CASE
      --{{{  Get NCT-handle for a given NCT-ID
      INT nct.id:
      -- Carrying: NCT-ID
      get.nct.handle; nct.id
        SEQ
          --{{{  IN message
          IF
            output.msgs
              CLAIM int.msg.handle
                SEQ
                  int.msg.handle[to.handler] ! msg.str; "nct.mgr: IN nctmgrh: get.nct.handle; "
                  int.msg.handle[to.handler] ! msg.int; nct.id
                  int.msg.handle[to.handler] ! msg.end; FALSE
            TRUE
              SKIP
          --}}}
          -- Return handle
          --{{{  OUT message
          IF
            output.msgs
              CLAIM int.msg.handle
                SEQ
                  int.msg.handle[to.handler] ! msg.str; "nct.mgr: OUT nctmgrh: get.nct.handle.confirm; [cli-end]"
                  int.msg.handle[to.handler] ! msg.end; FALSE
            TRUE
              SKIP
          --}}}
          -- Carrying: NCT-handle
          nct.mgr.handle.svr[from.mgr] ! get.nct.handle.confirm; nct.handle.array[nct.id]
      --}}}
      --{{{  Explicit allocation
      INT request.node.id, dir.type, share.type.alloc, share.type.opposite, type.hash:
      MOBILE[] BYTE nct.name:
      -- Carrying: node-ID of the kernel making the request;
      --           direction-type of the end to be allocated
      --             (0 = client-end, 1 = server-end);
      --           share-type of the end to be allocated
      --             (1 = unshared, 2 = shared);
      --           share-type of the opposite end
      --             (0 = unknown, 1 = unshared, 2 = shared);
      --           type-hash of the NCT to be allocated;
      --           name of the NCT
      alloc; request.node.id; dir.type;
             share.type.alloc; share.type.opposite;
             type.hash; nct.name
        INITIAL BOOL name.found IS FALSE:
        INITIAL INT alloc.nct.id.or.error IS num.ncts:
        PONY.INT.NCTHANDLE? nct.handle.svr:
        SHARED PONY.INT.LINKHANDLE! link.handle:
        SEQ
          --{{{  IN message
          IF
            output.msgs
              CLAIM int.msg.handle
                SEQ
                  int.msg.handle[to.handler] ! msg.str; "nct.mgr: IN nctmgrh: alloc; "
                  int.msg.handle[to.handler] ! msg.int; request.node.id
                  int.msg.handle[to.handler] ! msg.str; "; "
                  int.msg.handle[to.handler] ! msg.int; dir.type
                  int.msg.handle[to.handler] ! msg.str; "; "
                  int.msg.handle[to.handler] ! msg.int; share.type.alloc
                  int.msg.handle[to.handler] ! msg.str; "; "
                  int.msg.handle[to.handler] ! msg.int; share.type.opposite
                  int.msg.handle[to.handler] ! msg.str; "; "
                  int.msg.handle[to.handler] ! msg.hex; type.hash
                  int.msg.handle[to.handler] ! msg.str; "; *""
                  int.msg.handle[to.handler] ! msg.str; CLONE nct.name
                  int.msg.handle[to.handler] ! msg.str; "*""
                  int.msg.handle[to.handler] ! msg.end; FALSE
            TRUE
              SKIP
          --}}}
          --{{{  Try to find name in database
          INITIAL INT i IS 0:
          WHILE (NOT name.found) AND (i < num.ncts)
            SEQ
              IF
                pony.int.equal.str(nct.name, nct.name.array[i])
                  SEQ
                    name.found := TRUE
                    alloc.nct.id.or.error := i
                TRUE
                  SKIP
              i := i + 1
          --}}}
          IF
            --{{{  NCT-name found
            name.found
              INT new.cli.state, new.svr.state:
              SEQ
                IF
                  --{{{  Type-hash mismatch
                  nct.data.array[alloc.nct.id.or.error][type.hash] <> type.hash
                    alloc.nct.id.or.error := PONYC.RESULT.ALLOC.CHANTYPEMISMATCH
                  --}}}
                  --{{{  Type-hash fits, client-end to be allocated
                  dir.type = PONYC.INT.DIRTYPE.CLI
                    SEQ
                      --{{{  Check end to be allocated
                      CASE nct.data.array[alloc.nct.id.or.error][cli.state]
                        ENDSTATE.UNKNOWN
                          CASE share.type.alloc
                            PONYC.SHARETYPE.UNSHARED
                              new.cli.state := ENDSTATE.UNSHARED.ALLOC
                            ELSE
                              new.cli.state := ENDSTATE.SHARED
                        ENDSTATE.UNSHARED.NOTYETALLOC
                          CASE share.type.alloc
                            PONYC.SHARETYPE.UNSHARED
                              new.cli.state := ENDSTATE.UNSHARED.ALLOC
                            ELSE
                              alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                        ENDSTATE.UNSHARED.ALLOC
                          CASE share.type.alloc
                            PONYC.SHARETYPE.UNSHARED
                              alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XCOUNTMISMATCH
                            ELSE
                              alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                        ENDSTATE.SHARED
                          CASE share.type.alloc
                            PONYC.SHARETYPE.UNSHARED
                              alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                            ELSE
                              new.cli.state := ENDSTATE.SHARED
                      --}}}
                      IF
                        -- There was no error
                        alloc.nct.id.or.error >= 0
                          --{{{  Check opposite end
                          CASE nct.data.array[alloc.nct.id.or.error][svr.state]
                            ENDSTATE.UNKNOWN
                              CASE share.type.opposite
                                PONYC.SHARETYPE.UNKNOWN
                                  new.svr.state := ENDSTATE.UNKNOWN
                                PONYC.SHARETYPE.UNSHARED
                                  new.svr.state := ENDSTATE.UNSHARED.NOTYETALLOC
                                ELSE
                                  new.svr.state := ENDSTATE.SHARED
                            ENDSTATE.UNSHARED.NOTYETALLOC
                              CASE share.type.opposite
                                PONYC.SHARETYPE.UNKNOWN
                                  new.svr.state := ENDSTATE.UNSHARED.NOTYETALLOC
                                PONYC.SHARETYPE.UNSHARED
                                  new.svr.state := ENDSTATE.UNSHARED.NOTYETALLOC
                                ELSE
                                  alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                            ENDSTATE.UNSHARED.ALLOC
                              CASE share.type.opposite
                                PONYC.SHARETYPE.UNKNOWN
                                  new.svr.state := ENDSTATE.UNSHARED.ALLOC
                                PONYC.SHARETYPE.UNSHARED
                                  new.svr.state := ENDSTATE.UNSHARED.ALLOC
                                ELSE
                                  alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                            ENDSTATE.SHARED
                              CASE share.type.opposite
                                PONYC.SHARETYPE.UNKNOWN
                                  new.svr.state := ENDSTATE.SHARED
                                PONYC.SHARETYPE.UNSHARED
                                  alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                                ELSE
                                  new.svr.state := ENDSTATE.SHARED
                          --}}}
                        TRUE
                          SKIP
                  --}}}
                  --{{{  Type-hash fits, server-end to be allocated
                  TRUE
                    SEQ
                      --{{{  Check end to be allocated
                      CASE nct.data.array[alloc.nct.id.or.error][svr.state]
                        ENDSTATE.UNKNOWN
                          CASE share.type.alloc
                            PONYC.SHARETYPE.UNSHARED
                              new.svr.state := ENDSTATE.UNSHARED.ALLOC
                            ELSE
                              new.svr.state := ENDSTATE.SHARED
                        ENDSTATE.UNSHARED.NOTYETALLOC
                          CASE share.type.alloc
                            PONYC.SHARETYPE.UNSHARED
                              new.svr.state := ENDSTATE.UNSHARED.ALLOC
                            ELSE
                              alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                        ENDSTATE.UNSHARED.ALLOC
                          CASE share.type.alloc
                            PONYC.SHARETYPE.UNSHARED
                              alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XCOUNTMISMATCH
                            ELSE
                              alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                        ENDSTATE.SHARED
                          CASE share.type.alloc
                            PONYC.SHARETYPE.UNSHARED
                              alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                            ELSE
                              new.svr.state := ENDSTATE.SHARED
                      --}}}
                      IF
                        -- There was no error
                        alloc.nct.id.or.error >= 0
                          --{{{  Check opposite end
                          CASE nct.data.array[alloc.nct.id.or.error][cli.state]
                            ENDSTATE.UNKNOWN
                              CASE share.type.opposite
                                PONYC.SHARETYPE.UNKNOWN
                                  new.cli.state := ENDSTATE.UNKNOWN
                                PONYC.SHARETYPE.UNSHARED
                                  new.cli.state := ENDSTATE.UNSHARED.NOTYETALLOC
                                ELSE
                                  new.cli.state := ENDSTATE.SHARED
                            ENDSTATE.UNSHARED.NOTYETALLOC
                              CASE share.type.opposite
                                PONYC.SHARETYPE.UNKNOWN
                                  new.cli.state := ENDSTATE.UNSHARED.NOTYETALLOC
                                PONYC.SHARETYPE.UNSHARED
                                  new.cli.state := ENDSTATE.UNSHARED.NOTYETALLOC
                                ELSE
                                  alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                            ENDSTATE.UNSHARED.ALLOC
                              CASE share.type.opposite
                                PONYC.SHARETYPE.UNKNOWN
                                  new.cli.state := ENDSTATE.UNSHARED.ALLOC
                                PONYC.SHARETYPE.UNSHARED
                                  new.cli.state := ENDSTATE.UNSHARED.ALLOC
                                ELSE
                                  alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                            ENDSTATE.SHARED
                              CASE share.type.opposite
                                PONYC.SHARETYPE.UNKNOWN
                                  new.cli.state := ENDSTATE.SHARED
                                PONYC.SHARETYPE.UNSHARED
                                  alloc.nct.id.or.error := PONYC.RESULT.ALLOC.X2XTYPEMISMATCH
                                ELSE
                                  new.cli.state := ENDSTATE.SHARED
                          --}}}
                        TRUE
                          SKIP
                  --}}}
                IF
                  -- There was no error
                  alloc.nct.id.or.error >= 0
                    SEQ
                      -- Update client-end-state and server-end-state
                      nct.data.array[alloc.nct.id.or.error][cli.state] := new.cli.state
                      nct.data.array[alloc.nct.id.or.error][svr.state] := new.svr.state
                  TRUE
                    SKIP
            --}}}
            --{{{  NCT-name is new
            TRUE
              SEQ
                --{{{  Double size of arrays if necessary
                IF
                  num.ncts = (SIZE nct.handle.array)
                    -- New arrays
                    INITIAL MOBILE []SHARED PONY.INT.NCTHANDLE! new.nct.handle.array IS MOBILE [2 * num.ncts]SHARED PONY.INT.NCTHANDLE!:
                    INITIAL MOBILE []MOBILE []BYTE new.nct.name.array IS MOBILE [2 * num.ncts]MOBILE []BYTE:
                    INITIAL MOBILE []NCT.DATA new.nct.data.array IS MOBILE [2 * num.ncts]NCT.DATA:
                    SEQ
                      -- Set existing elements in new arrays
                      SEQ i = 0 FOR num.ncts
                        SEQ
                          new.nct.handle.array[i] := nct.handle.array[i]
                          new.nct.name.array[i] := nct.name.array[i]
                      [new.nct.data.array FOR num.ncts] := nct.data.array
                      -- Use new arrays
                      nct.handle.array := new.nct.handle.array
                      nct.name.array := new.nct.name.array
                      nct.data.array := new.nct.data.array
                  TRUE
                    SKIP
                --}}}
                -- Initialise new NCT-handle
                nct.handle.array[num.ncts], nct.handle.svr := MOBILE PONY.INT.NCTHANDLE
                -- Update NCT-name-array
                nct.name.array[num.ncts] := nct.name
                --{{{  Update NCT-data-array
                IF
                  dir.type = PONYC.INT.DIRTYPE.CLI
                    SEQ
                      CASE share.type.alloc
                        PONYC.SHARETYPE.UNSHARED
                          nct.data.array[num.ncts][cli.state] := ENDSTATE.UNSHARED.ALLOC
                        ELSE
                          nct.data.array[num.ncts][cli.state] := ENDSTATE.SHARED
                      CASE share.type.opposite
                        PONYC.SHARETYPE.UNKNOWN
                          nct.data.array[num.ncts][svr.state] := ENDSTATE.UNKNOWN
                        PONYC.SHARETYPE.UNSHARED
                          nct.data.array[num.ncts][svr.state] := ENDSTATE.UNSHARED.NOTYETALLOC
                        ELSE
                          nct.data.array[num.ncts][svr.state] := ENDSTATE.SHARED
                  TRUE
                    SEQ
                      CASE share.type.alloc
                        PONYC.SHARETYPE.UNSHARED
                          nct.data.array[num.ncts][svr.state] := ENDSTATE.UNSHARED.ALLOC
                        ELSE
                          nct.data.array[num.ncts][svr.state] := ENDSTATE.SHARED
                      CASE share.type.opposite
                        PONYC.SHARETYPE.UNKNOWN
                          nct.data.array[num.ncts][cli.state] := ENDSTATE.UNKNOWN
                        PONYC.SHARETYPE.UNSHARED
                          nct.data.array[num.ncts][cli.state] := ENDSTATE.UNSHARED.NOTYETALLOC
                        ELSE
                          nct.data.array[num.ncts][cli.state] := ENDSTATE.SHARED
                nct.data.array[num.ncts][type.hash] := type.hash
                --}}}
                -- Fork off new NCT-handler
                --{{{  FORK message
                IF
                  output.msgs
                    CLAIM int.msg.handle
                      SEQ
                        int.msg.handle[to.handler] ! msg.str; "nct.mgr: FORK nct.hdlr ("
                        int.msg.handle[to.handler] ! msg.int; num.ncts
                        int.msg.handle[to.handler] ! msg.str; ", FALSE, FALSE, -1, [svr-end], [cli-end], "
                        int.msg.handle[to.handler] ! msg.bool; output.msgs
                        int.msg.handle[to.handler] ! msg.str; ", [cli-end])"
                        int.msg.handle[to.handler] ! msg.end; FALSE
                  TRUE
                    SKIP
                --}}}
                FORK pony.int.nct.handler (num.ncts,
                                           FALSE, FALSE, -1,
                                           nct.handle.svr, link.mgr.handle,
                                           output.msgs, int.msg.handle)
                -- Increase `num.ncts'
                num.ncts := num.ncts + 1
            --}}}
          -- Get link-handle from link-manager
          CLAIM link.mgr.handle
            SEQ
              --{{{  OUT message
              IF
                output.msgs
                  CLAIM int.msg.handle
                    SEQ
                      int.msg.handle[to.handler] ! msg.str; "nct.mgr: OUT linkmgrh: get.link.handle; "
                      int.msg.handle[to.handler] ! msg.int; request.node.id
                      int.msg.handle[to.handler] ! msg.end; FALSE
                TRUE
                  SKIP
              --}}}
              -- Carrying: node-ID
              link.mgr.handle[to.mgr] ! get.link.handle; request.node.id
              -- Get reply
              -- Carrying: link-handle
              link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; link.handle
              --{{{  IN message
              IF
                output.msgs
                  CLAIM int.msg.handle
                    SEQ
                      int.msg.handle[to.handler] ! msg.str; "nct.mgr: IN linkmgrh: get.link.handle.confirm; [cli-end]"
                      int.msg.handle[to.handler] ! msg.end; FALSE
                TRUE
                  SKIP
              --}}}
          -- Send reply to requesting main kernel (via link-handle)
          CLAIM link.handle
            IF
              --{{{  There was an error
              alloc.nct.id.or.error < 0
                SEQ
                  --{{{  OUT message
                  IF
                    output.msgs
                      CLAIM int.msg.handle
                        SEQ
                          int.msg.handle[to.handler] ! msg.str; "nct.mgr: OUT linkh "
                          int.msg.handle[to.handler] ! msg.int; request.node.id
                          int.msg.handle[to.handler] ! msg.str; ": formainkernel.alloc.error; "
                          int.msg.handle[to.handler] ! msg.int; alloc.nct.id.or.error
                          int.msg.handle[to.handler] ! msg.end; FALSE
                    TRUE
                      SKIP
                  --}}}
                  -- Carrying: result
                  link.handle[to.handler] ! formainkernel.alloc.error;
                                            alloc.nct.id.or.error
              --}}}
              --{{{  No error
              TRUE
                SEQ
                  --{{{  OUT message
                  IF
                    output.msgs
                      CLAIM int.msg.handle
                        SEQ
                          int.msg.handle[to.handler] ! msg.str; "nct.mgr: OUT linkh "
                          int.msg.handle[to.handler] ! msg.int; request.node.id
                          int.msg.handle[to.handler] ! msg.str; ": formainkernel.alloc.confirm; "
                          int.msg.handle[to.handler] ! msg.int; alloc.nct.id.or.error
                          int.msg.handle[to.handler] ! msg.end; FALSE
                    TRUE
                      SKIP
                  --}}}
                  -- Carrying: NCT-ID of the newly allocated end
                  link.handle[to.handler] ! formainkernel.alloc.confirm;
                                            alloc.nct.id.or.error
              --}}}
      --}}}
      --{{{  Make CTB networked
      INT request.node.id, request.nct.id, request.chan.id:
      BOOL initial.cli.claimed, initial.svr.claimed:
      -- Carrying: node-ID of the decode-handler making the request;
      --           NCT-ID of the decode-handler making the request;
      --           channel-ID of the decode-handler making the request;
      --           client-end initially claimed?;
      --           server-end initially claimed?
      make.ctb.networked; request.node.id; request.nct.id; request.chan.id;
                          initial.cli.claimed; initial.svr.claimed
        PONY.INT.NCTHANDLE? nct.handle.svr:
        SHARED PONY.INT.LINKHANDLE! link.handle:
        SEQ
          --{{{  IN message
          IF
            output.msgs
              CLAIM int.msg.handle
                SEQ
                  int.msg.handle[to.handler] ! msg.str; "nct.mgr: IN nctmgrh: make.ctb.networked; "
                  int.msg.handle[to.handler] ! msg.int; request.node.id
                  int.msg.handle[to.handler] ! msg.str; "; "
                  int.msg.handle[to.handler] ! msg.int; request.nct.id
                  int.msg.handle[to.handler] ! msg.str; "; "
                  int.msg.handle[to.handler] ! msg.int; request.chan.id
                  int.msg.handle[to.handler] ! msg.str; "; "
                  int.msg.handle[to.handler] ! msg.bool; initial.cli.claimed
                  int.msg.handle[to.handler] ! msg.str; "; "
                  int.msg.handle[to.handler] ! msg.bool; initial.svr.claimed
                  int.msg.handle[to.handler] ! msg.end; FALSE
            TRUE
              SKIP
          --}}}
          --{{{  Double size of arrays if necessary
          IF
            num.ncts = (SIZE nct.handle.array)
              -- New arrays
              INITIAL MOBILE []SHARED PONY.INT.NCTHANDLE! new.nct.handle.array IS MOBILE [2 * num.ncts]SHARED PONY.INT.NCTHANDLE!:
              INITIAL MOBILE []MOBILE []BYTE new.nct.name.array IS MOBILE [2 * num.ncts]MOBILE []BYTE:
              INITIAL MOBILE []NCT.DATA new.nct.data.array IS MOBILE [2 * num.ncts]NCT.DATA:
              SEQ
                -- Set existing elements in new arrays
                SEQ i = 0 FOR num.ncts
                  SEQ
                    new.nct.handle.array[i] := nct.handle.array[i]
                    new.nct.name.array[i] := nct.name.array[i]
                [new.nct.data.array FOR num.ncts] := nct.data.array
                -- Use new arrays
                nct.handle.array := new.nct.handle.array
                nct.name.array := new.nct.name.array
                nct.data.array := new.nct.data.array
            TRUE
              SKIP
          --}}}
          -- Initialise new NCT-handle
          nct.handle.array[num.ncts], nct.handle.svr := MOBILE PONY.INT.NCTHANDLE
          -- Update NCT-name-array
          nct.name.array[num.ncts] := ""
          -- Get link-handle from link-manager
          CLAIM link.mgr.handle
            SEQ
              --{{{  OUT message
              IF
                output.msgs
                  CLAIM int.msg.handle
                    SEQ
                      int.msg.handle[to.handler] ! msg.str; "nct.mgr: OUT linkmgrh: get.link.handle; "
                      int.msg.handle[to.handler] ! msg.int; request.node.id
                      int.msg.handle[to.handler] ! msg.end; FALSE
                TRUE
                  SKIP
              --}}}
              -- Carrying: node-ID
              link.mgr.handle[to.mgr] ! get.link.handle; request.node.id
              -- Get reply
              -- Carrying: link-handle
              link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; link.handle
              --{{{  IN message
              IF
                output.msgs
                  CLAIM int.msg.handle
                    SEQ
                      int.msg.handle[to.handler] ! msg.str; "nct.mgr: IN linkmgrh: get.link.handle.confirm; [cli-end]"
                      int.msg.handle[to.handler] ! msg.end; FALSE
                TRUE
                  SKIP
              --}}}
          -- Send reply to requesting decode-handler (via link-handle)
          CLAIM link.handle
            SEQ
              --{{{  OUT message
              IF
                output.msgs
                  CLAIM int.msg.handle
                    SEQ
                      int.msg.handle[to.handler] ! msg.str; "nct.mgr: OUT linkh "
                      int.msg.handle[to.handler] ! msg.int; request.node.id
                      int.msg.handle[to.handler] ! msg.str; ": fordechandler.make.ctb.networked.confirm; "
                      int.msg.handle[to.handler] ! msg.int; request.nct.id
                      int.msg.handle[to.handler] ! msg.str; "; "
                      int.msg.handle[to.handler] ! msg.int; request.chan.id
                      int.msg.handle[to.handler] ! msg.str; "; "
                      int.msg.handle[to.handler] ! msg.int; num.ncts
                      int.msg.handle[to.handler] ! msg.end; FALSE
                TRUE
                  SKIP
              --}}}
              -- Carrying: NCT-ID of the recipient decode-handler;
              --           channel-ID of the recipient decode-handler;
              --           NCT-ID of the newly allocated end
              link.handle[to.handler] ! fordechandler.make.ctb.networked.confirm;
                                        request.nct.id; request.chan.id; num.ncts
          -- Fork off new NCT-handler
          --{{{  FORK message
          IF
            output.msgs
              CLAIM int.msg.handle
                SEQ
                  int.msg.handle[to.handler] ! msg.str; "nct.mgr: FORK nct.hdlr ("
                  int.msg.handle[to.handler] ! msg.int; num.ncts
                  int.msg.handle[to.handler] ! msg.str; ", "
                  int.msg.handle[to.handler] ! msg.bool; initial.cli.claimed
                  int.msg.handle[to.handler] ! msg.str; ", "
                  int.msg.handle[to.handler] ! msg.bool; initial.svr.claimed
                  int.msg.handle[to.handler] ! msg.str; ", "
                  int.msg.handle[to.handler] ! msg.int; request.node.id
                  int.msg.handle[to.handler] ! msg.str; ", [svr-end], [cli-end], "
                  int.msg.handle[to.handler] ! msg.bool; output.msgs
                  int.msg.handle[to.handler] ! msg.str; ", [cli-end])"
                  int.msg.handle[to.handler] ! msg.end; FALSE
            TRUE
              SKIP
          --}}}
          FORK pony.int.nct.handler (num.ncts,
                                     initial.cli.claimed, initial.svr.claimed,
                                     request.node.id,
                                     nct.handle.svr, link.mgr.handle,
                                     output.msgs, int.msg.handle)
          -- Increase `num.ncts'
          num.ncts := num.ncts + 1
      --}}}
      --{{{  Shutdown
      shutdown
        SEQ
          --{{{  IN message
          IF
            output.msgs
              CLAIM int.msg.handle
                SEQ
                  int.msg.handle[to.handler] ! msg.str; "nct.mgr: IN nctmgrh: shutdown"
                  int.msg.handle[to.handler] ! msg.end; FALSE
            TRUE
              SKIP
          --}}}
          -- Shut down NCT-handlers
          SEQ i = 0 FOR num.ncts
            CLAIM nct.handle.array[i]
              SEQ
                --{{{  OUT message
                IF
                  output.msgs
                    CLAIM int.msg.handle
                      SEQ
                        int.msg.handle[to.handler] ! msg.str; "nct.mgr: OUT ncth "
                        int.msg.handle[to.handler] ! msg.int; i
                        int.msg.handle[to.handler] ! msg.str; ": shutdown"
                        int.msg.handle[to.handler] ! msg.end; FALSE
                  TRUE
                    SKIP
                --}}}
                nct.handle.array[i][to.handler] ! shutdown
                -- Get reply
                nct.handle.array[i][from.handler] ? CASE shutdown.confirm
                --{{{  IN message
                IF
                  output.msgs
                    CLAIM int.msg.handle
                      SEQ
                        int.msg.handle[to.handler] ! msg.str; "nct.mgr: IN ncth "
                        int.msg.handle[to.handler] ! msg.int; i
                        int.msg.handle[to.handler] ! msg.str; ": shutdown.confirm"
                        int.msg.handle[to.handler] ! msg.end; FALSE
                  TRUE
                    SKIP
                --}}}
          -- Leave main loop
          running := FALSE
          -- Send reply
          --{{{  OUT message
          IF
            output.msgs
              CLAIM int.msg.handle
                SEQ
                  int.msg.handle[to.handler] ! msg.str; "nct.mgr: OUT nctmgrh: shutdown.confirm"
                  int.msg.handle[to.handler] ! msg.end; FALSE
            TRUE
              SKIP
          --}}}
          nct.mgr.handle.svr[from.mgr] ! shutdown.confirm
      --}}}
:
--}}}

----------------------------------------------------------------------

--{{{  PROC pony.int.main.kernel
-- Main kernel
-- Parameters: own.node.id             | VAL: own node-ID
--             net.handle.svr          | server-end of network-handle
--             link.mgr.handle         | link-manager-handle (client-end)
--             ctb.mgr.handle          | CTB-manager-handle (client-end)
--             ctb.mgr.handle.svr      | server-end of CTB-manager-handle
--             nct.mgr.handle          | NCT-manager-handle (client-end)
--             nct.mgr.handle.svr      | server-end of NCT-manager-handle
--             kernel.reply.handle     | kernel-reply-handle (client-end)
--             kernel.reply.handle.svr | server-end of kernel-reply-handle
--             output.errs             | VAL: output errors?
--             initial.err.point       | VAL: initial error-point?
--             err.handle.svr          | server-end of error-handle
--             int.err.handle          | internal error-handle (client-end)
--             int.err.handle.svr      | server-end of internal error-handle
--             msg.type                | VAL: message-type
--             msg.handle.svr          | server-end of message-handle
--             int.msg.handle          | internal message-handle (client-end)
--             int.msg.handle.svr      | server-end of internal message-handle
PROC pony.int.main.kernel (VAL INT own.node.id,
                           PONY.NETHANDLE? net.handle.svr,
                           SHARED PONY.INT.LINKMGRHANDLE! link.mgr.handle,
                           SHARED PONY.INT.CTBMGRHANDLE! ctb.mgr.handle,
                           PONY.INT.CTBMGRHANDLE? ctb.mgr.handle.svr,
                           SHARED PONY.INT.NCTMGRHANDLE! nct.mgr.handle,
                           PONY.INT.NCTMGRHANDLE? nct.mgr.handle.svr,
                           SHARED PONY.INT.KERNELREPLYHANDLE! kernel.reply.handle,
                           PONY.INT.KERNELREPLYHANDLE? kernel.reply.handle.svr,
                           VAL BOOL output.errs, initial.err.point,
                           PONY.ERRHANDLE? err.handle.svr,
                           SHARED PONY.INT.ERRHANDLE! int.err.handle,
                           PONY.INT.ERRHANDLE? int.err.handle.svr,
                           VAL INT msg.type,
                           PONY.MSGHANDLE? msg.handle.svr,
                           SHARED PONY.INT.MSGHANDLE! int.msg.handle,
                           PONY.INT.MSGHANDLE? int.msg.handle.svr)
  VAL BOOL output.msgs IS ((msg.type = PONYC.MSGTYPE.STATUS) OR (msg.type = PONYC.MSGTYPE.STATUSERR)):
  SHARED PONY.INT.LINKHANDLE! master.link.handle:
  SEQ
    --{{{  Fork off message-handler
    IF
      msg.type <> (-1)
        FORK pony.int.msg.handler (own.node.id, msg.type,
                                   msg.handle.svr, int.msg.handle.svr)
      TRUE
        SKIP
    --}}}
    --{{{  Fork off error-handler
    IF
      output.errs
        SEQ
          --{{{  FORK message
          IF
            output.msgs
              CLAIM int.msg.handle
                SEQ
                  int.msg.handle[to.handler] ! msg.str; "main.kernel: FORK err.hdlr ("
                  int.msg.handle[to.handler] ! msg.bool; initial.err.point
                  int.msg.handle[to.handler] ! msg.str; ", [svr-end], [svr-end], [cli-end], "
                  int.msg.handle[to.handler] ! msg.int; msg.type
                  int.msg.handle[to.handler] ! msg.str; ", [cli-end])"
                  int.msg.handle[to.handler] ! msg.end; FALSE
            TRUE
              SKIP
          --}}}
          FORK pony.int.err.handler (initial.err.point,
                                     err.handle.svr, int.err.handle.svr,
                                     ctb.mgr.handle,
                                     msg.type, int.msg.handle)
      TRUE
        SKIP
    --}}}
    --{{{  Get master-link-handle from link-manager
    CLAIM link.mgr.handle
      SEQ
        --{{{  OUT message
        IF
          output.msgs
            CLAIM int.msg.handle
              SEQ
                int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT linkmgrh: get.link.handle; 0"
                int.msg.handle[to.handler] ! msg.end; FALSE
          TRUE
            SKIP
        --}}}
        -- Carrying: node-ID
        link.mgr.handle[to.mgr] ! get.link.handle; 0
        -- Get reply
        -- Carrying: link-handle
        link.mgr.handle[from.mgr] ? CASE get.link.handle.confirm; master.link.handle
        --{{{  IN message
        IF
          output.msgs
            CLAIM int.msg.handle
              SEQ
                int.msg.handle[to.handler] ! msg.str; "main.kernel: IN linkmgrh: get.link.handle.confirm; [cli-end]"
                int.msg.handle[to.handler] ! msg.end; FALSE
          TRUE
            SKIP
        --}}}
    --}}}
    --{{{  Fork off CTB-manager and NCT-manager
    --{{{  FORK message
    IF
      output.msgs
        CLAIM int.msg.handle
          SEQ
            int.msg.handle[to.handler] ! msg.str; "main.kernel: FORK ctb.mgr ("
            int.msg.handle[to.handler] ! msg.int; own.node.id
            int.msg.handle[to.handler] ! msg.str; ", [svr-end], [cli-end], [cli-end], [cli-end], [cli-end], "
            int.msg.handle[to.handler] ! msg.bool; output.msgs
            int.msg.handle[to.handler] ! msg.str; ", [cli-end])"
            int.msg.handle[to.handler] ! msg.end; FALSE
      TRUE
        SKIP
    --}}}
    FORK pony.int.ctb.mgr (own.node.id, ctb.mgr.handle.svr,
                           ctb.mgr.handle,
                           link.mgr.handle, master.link.handle,
                           kernel.reply.handle,
                           output.msgs, int.msg.handle)
    IF
      own.node.id = 0
        SEQ
          --{{{  FORK message
          IF
            output.msgs
              CLAIM int.msg.handle
                SEQ
                  int.msg.handle[to.handler] ! msg.str; "main.kernel: FORK nct.mgr ([svr-end], [cli-end], "
                  int.msg.handle[to.handler] ! msg.bool; output.msgs
                  int.msg.handle[to.handler] ! msg.str; ", [cli-end])"
                  int.msg.handle[to.handler] ! msg.end; FALSE
            TRUE
              SKIP
          --}}}
          FORK pony.int.nct.mgr (nct.mgr.handle.svr, link.mgr.handle,
                                 output.msgs, int.msg.handle)
      TRUE
        SKIP
    --}}}
    INITIAL BOOL running IS TRUE:
    WHILE running
      net.handle.svr[to.kernel] ? CASE
        --{{{  Explicit allocation
        INT dir.type, share.type.alloc, share.type.opposite,
            num.chans, num.readers.in.svr, type.hash:
        MOBILE[] BYTE nct.name:
        -- Carrying: direction-type of the end to be allocated
        --             (0 = client-end, 1 = server-end);
        --           share-type of the end to be allocated
        --             (1 = unshared, 2 = shared);
        --           share-type of the opposite end
        --             (0 = unknown, 1 = unshared, 2 = shared);
        --           number of channel-words;
        --           number of reading-ends in server-end;
        --           type-hash of the NCT to be allocated;
        --           name of the NCT
        alloc;  dir.type; share.type.alloc; share.type.opposite;
                num.chans; num.readers.in.svr; type.hash; nct.name
          SEQ
            --{{{  IN message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "main.kernel: IN neth: alloc; "
                    int.msg.handle[to.handler] ! msg.int; dir.type
                    int.msg.handle[to.handler] ! msg.str; "; "
                    int.msg.handle[to.handler] ! msg.int; share.type.alloc
                    int.msg.handle[to.handler] ! msg.str; "; "
                    int.msg.handle[to.handler] ! msg.int; share.type.opposite
                    int.msg.handle[to.handler] ! msg.str; "; "
                    int.msg.handle[to.handler] ! msg.int; num.chans
                    int.msg.handle[to.handler] ! msg.str; "; "
                    int.msg.handle[to.handler] ! msg.int; num.readers.in.svr
                    int.msg.handle[to.handler] ! msg.str; "; "
                    int.msg.handle[to.handler] ! msg.hex; type.hash
                    int.msg.handle[to.handler] ! msg.str; "; *""
                    int.msg.handle[to.handler] ! msg.str; CLONE nct.name
                    int.msg.handle[to.handler] ! msg.str; "*""
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            -- Send request to NCT-manager (via master-link-handle)
            CLAIM master.link.handle
              SEQ
                --{{{  OUT message
                IF
                  output.msgs
                    CLAIM int.msg.handle
                      SEQ
                        int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT linkh 0: fornctmgr.alloc; "
                        int.msg.handle[to.handler] ! msg.int; dir.type
                        int.msg.handle[to.handler] ! msg.str; "; "
                        int.msg.handle[to.handler] ! msg.int; share.type.alloc
                        int.msg.handle[to.handler] ! msg.str; "; "
                        int.msg.handle[to.handler] ! msg.int; share.type.opposite
                        int.msg.handle[to.handler] ! msg.str; "; "
                        int.msg.handle[to.handler] ! msg.hex; type.hash
                        int.msg.handle[to.handler] ! msg.str; "; *""
                        int.msg.handle[to.handler] ! msg.str; CLONE nct.name
                        int.msg.handle[to.handler] ! msg.str; "*""
                        int.msg.handle[to.handler] ! msg.end; FALSE
                  TRUE
                    SKIP
                --}}}
                -- Carrying: direction-type of the end to be allocated
                --             (0 = client-end, 1 = server-end);
                --           share-type of the end to be allocated
                --             (1 = unshared, 2 = shared);
                --           share-type of the opposite end
                --             (0 = unknown, 1 = unshared, 2 = shared);
                --           type-hash of the NCT to be allocated;
                --           name of the NCT
                master.link.handle[to.handler] ! fornctmgr.alloc;
                                                 dir.type; share.type.alloc; share.type.opposite;
                                                 type.hash; nct.name
            -- Wait for reply (via kernel-reply-handle)
            kernel.reply.handle.svr[to.kernel] ? CASE
              --{{{  Error
              INT result:
              -- Carrying: result
              alloc.error; result
                SEQ
                  --{{{  IN message
                  IF
                    output.msgs
                      CLAIM int.msg.handle
                        SEQ
                          int.msg.handle[to.handler] ! msg.str; "main.kernel: IN kernelreplyh: alloc.error; "
                          int.msg.handle[to.handler] ! msg.int; result
                          int.msg.handle[to.handler] ! msg.end; FALSE
                    TRUE
                      SKIP
                  --}}}
                  -- Pass error on to allocation process
                  --{{{  OUT message
                  IF
                    output.msgs
                      CLAIM int.msg.handle
                        SEQ
                          int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT neth: alloc.error; "
                          int.msg.handle[to.handler] ! msg.int; result
                          int.msg.handle[to.handler] ! msg.end; FALSE
                    TRUE
                      SKIP
                  --}}}
                  net.handle.svr[from.kernel] ! alloc.error; result
              --}}}
              --{{{  No error
              INT nct.id:
              -- Carrying: NCT-ID of the newly allocated end
              alloc.confirm; nct.id
                SHARED PONY.INT.CTBCLAIMHANDLE! ctb.claim.handle:
                SEQ
                  --{{{  IN message
                  IF
                    output.msgs
                      CLAIM int.msg.handle
                        SEQ
                          int.msg.handle[to.handler] ! msg.str; "main.kernel: IN kernelreplyh: alloc.confirm; "
                          int.msg.handle[to.handler] ! msg.int; nct.id
                          int.msg.handle[to.handler] ! msg.end; FALSE
                    TRUE
                      SKIP
                  --}}}
                  -- Send request to CTB-manager
                  CLAIM ctb.mgr.handle
                    SEQ
                      --{{{  OUT message
                      IF
                        output.msgs
                          CLAIM int.msg.handle
                            SEQ
                              int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT ctbmgrh: alloc.ct.end; "
                              int.msg.handle[to.handler] ! msg.int; nct.id
                              int.msg.handle[to.handler] ! msg.end; FALSE
                        TRUE
                          SKIP
                      --}}}
                      -- Carrying: NCT-ID
                      ctb.mgr.handle[to.mgr] ! alloc.ct.end; nct.id
                      -- Wait for reply
                      ctb.mgr.handle[from.mgr] ? CASE
                        --{{{  Increase reference-count of CTB
                        INT ctb.ptr:
                        -- Carrying: CTB-pointer
                        clone.ctb; ctb.ptr
                          SEQ
                            --{{{  IN message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "main.kernel: IN ctbmgrh: clone.ctb; "
                                    int.msg.handle[to.handler] ! msg.hex; ctb.ptr
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                            -- Pass message on to allocation process
                            --{{{  OUT message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT neth: clone.ctb; "
                                    int.msg.handle[to.handler] ! msg.hex; ctb.ptr
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                            -- Carrying: CTB-pointer
                            net.handle.svr[from.kernel] ! clone.ctb; ctb.ptr
                        --}}}
                        --{{{  Allocate new CTB
                        alloc.new.ctb
                          INT ctb.ptr:
                          PONY.NETHOOKHANDLE! net.hook.handle:
                          MOBILE []PONY.DECODEHANDLE! dec.handle.array:
                          MOBILE []PONY.ENCODEHANDLE! enc.handle.array:
                          SEQ
                            --{{{  IN message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "main.kernel: IN ctbmgrh: alloc.new.ctb"
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                            -- Pass channel-counts on to CTB-manager
                            --{{{  OUT message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT ctbmgrh: alloc.new.ctb.confirm.chancounts; "
                                    int.msg.handle[to.handler] ! msg.int; num.chans
                                    int.msg.handle[to.handler] ! msg.str; "; "
                                    int.msg.handle[to.handler] ! msg.int; num.readers.in.svr
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                            -- Carrying: number of channel-words in CTB;
                            --           number of reading-ends in server-end
                            ctb.mgr.handle[to.mgr] ! alloc.new.ctb.confirm.chancounts;
                                                     num.chans; num.readers.in.svr
                            -- Wait for reply
                            -- Carrying: network-hook-handle;
                            --           array of decode-handles;
                            --           array of encode-handles
                            ctb.mgr.handle[from.mgr] ? CASE alloc.new.ctb.confirm;
                                                            net.hook.handle;
                                                            dec.handle.array; enc.handle.array
                            --{{{  IN message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "main.kernel: IN ctbmgrh: alloc.new.ctb.confirm; [cli-end]; [array ("
                                    int.msg.handle[to.handler] ! msg.int; SIZE dec.handle.array
                                    int.msg.handle[to.handler] ! msg.str; ")]; [array ("
                                    int.msg.handle[to.handler] ! msg.int; SIZE enc.handle.array
                                    int.msg.handle[to.handler] ! msg.str; ")]"
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                            -- Pass message on to allocation process
                            --{{{  OUT message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT neth: alloc.new.ctb; "
                                    int.msg.handle[to.handler] ! msg.int; nct.id
                                    int.msg.handle[to.handler] ! msg.str; "; [cli-end]; [array ("
                                    int.msg.handle[to.handler] ! msg.int; SIZE dec.handle.array
                                    int.msg.handle[to.handler] ! msg.str; ")]; [array ("
                                    int.msg.handle[to.handler] ! msg.int; SIZE enc.handle.array
                                    int.msg.handle[to.handler] ! msg.str; ")]"
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                            -- Carrying: NCT-ID;
                            --           network-hook-handle;
                            --           array of decode-handles;
                            --           array of encode-handles
                            net.handle.svr[from.kernel] ! alloc.new.ctb; nct.id;
                                                          net.hook.handle;
                                                          dec.handle.array; enc.handle.array
                            -- Wait for reply
                            -- Carrying: CTB-pointer
                            net.handle.svr[to.kernel] ? CASE alloc.new.ctb.confirm; ctb.ptr
                            --{{{  IN message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "main.kernel: IN neth: alloc.new.ctb.confirm; "
                                    int.msg.handle[to.handler] ! msg.hex; ctb.ptr
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                            -- Pass CTB-pointer on to CTB-manager
                            --{{{  OUT message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT ctbmgrh: alloc.new.ctb.confirm.ctbptr; "
                                    int.msg.handle[to.handler] ! msg.hex; ctb.ptr
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                            -- Carrying: CTB-pointer
                            ctb.mgr.handle[to.mgr] ! alloc.new.ctb.confirm.ctbptr; ctb.ptr
                        --}}}
                      --{{{  Get CTB-claim-handle if end is unshared
                      IF
                        share.type.alloc = PONYC.SHARETYPE.UNSHARED
                          SEQ
                            --{{{  OUT message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT ctbmgrh: get.ctb.claim.handle; "
                                    int.msg.handle[to.handler] ! msg.int; nct.id
                                    int.msg.handle[to.handler] ! msg.str; "; "
                                    int.msg.handle[to.handler] ! msg.int; dir.type
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                            -- Carrying: NCT-ID;
                            --           direction-type of the end to be claimed/released
                            --             (0 = client-end, 1 = server-end)
                            ctb.mgr.handle[to.mgr] ! get.ctb.claim.handle; nct.id; dir.type
                            -- Get reply
                            -- Carrying: CTB-claim-handle
                            ctb.mgr.handle[from.mgr] ? CASE get.ctb.claim.handle.confirm;
                                                            ctb.claim.handle
                            --{{{  IN message
                            IF
                              output.msgs
                                CLAIM int.msg.handle
                                  SEQ
                                    int.msg.handle[to.handler] ! msg.str; "main.kernel: IN ctbmgrh: get.ctb.claim.handle.confirm; [cli-end]"
                                    int.msg.handle[to.handler] ! msg.end; FALSE
                              TRUE
                                SKIP
                            --}}}
                        TRUE
                          SKIP
                      --}}}
                  --{{{  Claim end if unshared
                  IF
                    share.type.alloc = PONYC.SHARETYPE.UNSHARED
                      CLAIM ctb.claim.handle
                        SEQ
                          --{{{  OUT message
                          IF
                            output.msgs
                              CLAIM int.msg.handle
                                SEQ
                                  int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT ctbclaimh "
                                  int.msg.handle[to.handler] ! msg.int; nct.id
                                  int.msg.handle[to.handler] ! msg.str; "/"
                                  int.msg.handle[to.handler] ! msg.int; dir.type
                                  int.msg.handle[to.handler] ! msg.str; ": claim"
                                  int.msg.handle[to.handler] ! msg.end; FALSE
                            TRUE
                              SKIP
                          --}}}
                          ctb.claim.handle[to.handler] ! claim
                    TRUE
                      SKIP
                  --}}}
              --}}}
        --}}}
        --{{{  Shutdown
        shutdown
          MOBILE []INT final.ctb.ptr.array:
          SEQ
            --{{{  IN message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "main.kernel: IN neth: shutdown"
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            -- Leave main loop
            running := FALSE
            --{{{  Shut down CTB-manager
            CLAIM ctb.mgr.handle
              SEQ
                --{{{  OUT message
                IF
                  output.msgs
                    CLAIM int.msg.handle
                      SEQ
                        int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT ctbmgrh: shutdown"
                        int.msg.handle[to.handler] ! msg.end; FALSE
                  TRUE
                    SKIP
                --}}}
                ctb.mgr.handle[to.mgr] ! shutdown
            -- Get reply
            -- Carrying: array of formerly networked CTB-pointers
            kernel.reply.handle.svr[to.kernel] ? CASE fromctbmgr.shutdown.confirm;
                                                      final.ctb.ptr.array
            --{{{  IN message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "main.kernel: IN kernelreplyh: fromctbmgr.shutdown.confirm; [array ("
                    int.msg.handle[to.handler] ! msg.int; SIZE final.ctb.ptr.array
                    int.msg.handle[to.handler] ! msg.str; ")]"
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            --}}}
            --{{{  Shut down link-manager
            CLAIM link.mgr.handle
              SEQ
                --{{{  OUT message
                IF
                  output.msgs
                    CLAIM int.msg.handle
                      SEQ
                        int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT linkmgrh: shutdown"
                        int.msg.handle[to.handler] ! msg.end; FALSE
                  TRUE
                    SKIP
                --}}}
                link.mgr.handle[to.mgr] ! shutdown
            -- Get reply
            kernel.reply.handle.svr[to.kernel] ? CASE fromlinkmgr.shutdown.confirm
            --{{{  IN message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "main.kernel: IN kernelreplyh: fromlinkmgr.shutdown.confirm"
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            --}}}
            --{{{  Shut down NCT-manager
            IF
              own.node.id = 0
                CLAIM nct.mgr.handle
                  SEQ
                    --{{{  OUT message
                    IF
                      output.msgs
                        CLAIM int.msg.handle
                          SEQ
                            int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT nctmgrh: shutdown"
                            int.msg.handle[to.handler] ! msg.end; FALSE
                      TRUE
                        SKIP
                    --}}}
                    nct.mgr.handle[to.mgr] ! shutdown
                    -- Get reply
                    nct.mgr.handle[from.mgr] ? CASE shutdown.confirm
                    --{{{  IN message
                    IF
                      output.msgs
                        CLAIM int.msg.handle
                          SEQ
                            int.msg.handle[to.handler] ! msg.str; "main.kernel: IN nctmgrh: shutdown.confirm"
                            int.msg.handle[to.handler] ! msg.end; FALSE
                      TRUE
                        SKIP
                    --}}}
              TRUE
                SKIP
            --}}}
            --{{{  Send reply to shutdown process
            --{{{  OUT message
            IF
              output.msgs
                CLAIM int.msg.handle
                  SEQ
                    int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT neth: shutdown.confirm; [array ("
                    int.msg.handle[to.handler] ! msg.int; SIZE final.ctb.ptr.array
                    int.msg.handle[to.handler] ! msg.str; ")]"
                    int.msg.handle[to.handler] ! msg.end; FALSE
              TRUE
                SKIP
            --}}}
            net.handle.svr[from.kernel] ! shutdown.confirm;
                                          final.ctb.ptr.array
            --}}}
            --{{{  Shut down error-handler and message-handler
            IF
              output.errs
                -- Send internal shutdown signal to error-handler
                CLAIM int.err.handle
                  SEQ
                    --{{{  OUT message
                    IF
                      output.msgs
                        CLAIM int.msg.handle
                          SEQ
                            int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT int.errh: shutdown"
                            int.msg.handle[to.handler] ! msg.end; FALSE
                      TRUE
                        SKIP
                    --}}}
                    int.err.handle[to.handler] ! shutdown
              msg.type <> (-1)
                --{{{  SHUTDOWN message
                CLAIM int.msg.handle
                  SEQ
                    IF
                      output.msgs
                        SEQ
                          int.msg.handle[to.handler] ! msg.str; "main.kernel: OUT int.msgh: shutdown"
                          int.msg.handle[to.handler] ! msg.end; FALSE
                      TRUE
                        SKIP
                    int.msg.handle[to.handler] ! shutdown
                --}}}
              TRUE
                SKIP
            --}}}
        --}}}
:
--}}}

--}}}

--{{{  Network-type-specific code

--{{{  Compiler declarations for all supported network-types
#USE "ponyinttcpipstartup.tce"
--}}}
--{{{  PROC pony.int.startup.linkmgr
-- Call the network-type-specific startup process
-- Parameters: net.type            | VAL: network-type
--                                   `PONYC.NETTYPE.TCPIP' | TCP/IP
--             ans.name            | VAL: name of the ANS
--             app.name            | VAL: name of the application
--             node.name           | VAL: name of the node
--             node.type           | VAL: node-type
--                                   `PONYC.NODETYPE.MASTER      | master
--                                   `PONYC.NODETYPE.MASTERRESET | master/reset
--                                   `PONYC.NODETYPE.SLAVE       | slave
--                                   `PONYC.NODETYPE.SLAVEWAIT   | slave/wait
--             ctb.mgr.handle      | CTB-manager-handle (client-end)
--             nct.mgr.handle      | NCT-manager-handle (client-end)
--             kernel.reply.handle | kernel-reply-handle (client-end)
--             output.errs         | VAL: output errors?
--             int.err.handle      | internal error-handle (client-end)
--             msg.type            | VAL: message-type
--             int.msg.handle      | internal message-handle (client-end)
--             own.node.id         | RESULT: own node-ID
--             link.mgr.handle     | RESULT: link-manager-handle
--             result              | RESULT: result
PROC pony.int.startup.linkmgr (VAL INT net.type,
                               VAL []BYTE ans.name, app.name, node.name,
                               VAL INT node.type,
                               SHARED PONY.INT.CTBMGRHANDLE! ctb.mgr.handle,
                               SHARED PONY.INT.NCTMGRHANDLE! nct.mgr.handle,
                               SHARED PONY.INT.KERNELREPLYHANDLE! kernel.reply.handle,
                               VAL BOOL output.errs,
                               SHARED PONY.INT.ERRHANDLE! int.err.handle,
                               VAL INT msg.type,
                               SHARED PONY.INT.MSGHANDLE! int.msg.handle,
                               RESULT INT own.node.id,
                               RESULT SHARED PONY.INT.LINKMGRHANDLE! link.mgr.handle,
                               RESULT INT result)
  CASE net.type
    --{{{  TCP/IP
    PONYC.NETTYPE.TCPIP
      pony.int.startup.linkmgr.tcpip (ans.name, app.name,
                                      node.name, node.type,
                                      ctb.mgr.handle, nct.mgr.handle,
                                      kernel.reply.handle,
                                      output.errs, int.err.handle,
                                      msg.type, int.msg.handle,
                                      own.node.id, link.mgr.handle, result)
    --}}}
    --{{{  Unsupported network-type
    ELSE
      result := PONYC.RESULT.STARTUP.ILLEGALNETTYPE
    --}}}
:
--}}}

--}}}

