-- ^ making the context struct declaration
mkContext :: String -> -- ^ context name
             M.Map Ident LabeledBlock ->  -- ^ labeled blocks
             [AST.CDeclaration N.NodeInfo] ->  -- ^ formal arguments
             [AST.CDeclaration N.NodeInfo] ->  -- ^ local variable declarations
             [AST.CDeclarationSpecifier N.NodeInfo] ->  -- ^ return Type
             [AST.CDerivedDeclarator N.NodeInfo] -> -- ^ the pointer or array postfix
             S.Set Ident -> S.Set Ident -> 
             AST.CDeclaration N.NodeInfo
mkContext name labeledBlocks formal_arg_decls local_var_decls returnType ptrArrs local_decl_vars fargs = 
  let structName  = iid name
      ctxtAlias   = AST.CDeclr (Just (internalIdent (map toLower name))) [] Nothing [] N.undefNode
      attrs       = []
      
      isReturnVoid   = isVoidDeclSpec returnType
      
      funcResult | isReturnVoid = [] 
                 | otherwise    = [AST.CDecl returnType [(Just (AST.CDeclr (Just $ iid "func_result") ptrArrs Nothing [] N.undefNode), Nothing, Nothing)] N.undefNode]
      decls'        = -- formal_arg_decls ++ 
        -- note: we remove local decl duplicate, maybe we should let different label block to have different type decl in the ctxt, see test/scoped_dup_var.c
                      concatMap (\d -> renameDeclWithLabeledBlocks d labeledBlocks local_decl_vars fargs) (nubBy declLHSEq $ map (cff_trans_declaration . dropConstTyQual . dropStorageQual) (formal_arg_decls ++ local_var_decls)) ++ funcResult
      tyDef         = AST.CStorageSpec (AST.CTypedef N.undefNode)
      structDef     =
        AST.CTypeSpec (AST.CSUType
                       (AST.CStruct AST.CStructTag (Just structName) (Just decls') attrs N.undefNode) N.undefNode) 
  in AST.CDecl [tyDef, structDef] [(Just ctxtAlias, Nothing, Nothing)] N.undefNode
mkContext :: String -> -- ^ context name
             M.Map Ident LabeledBlock ->  -- ^ labeled blocks
             [AST.CDeclaration N.NodeInfo] ->  -- ^ formal arguments
             [AST.CDeclaration N.NodeInfo] ->  -- ^ local variable declarations
             [AST.CDeclarationSpecifier N.NodeInfo] ->  -- ^ return Type
             [AST.CDerivedDeclarator N.NodeInfo] -> -- ^ the pointer or array postfix
             S.Set Ident -> S.Set Ident -> 
             AST.CDeclaration N.NodeInfo
mkContext name labeledBlocks formal_arg_decls local_var_decls returnType ptrArrs local_decl_vars fargs = 
  let structName  = iid name
      ctxtAlias   = AST.CDeclr (Just (internalIdent (map toLower name))) [] Nothing [] N.undefNode
      attrs       = []
      
      isReturnVoid   = isVoidDeclSpec returnType
      
      funcResult | isReturnVoid = [] 
                 | otherwise    = [AST.CDecl returnType [(Just (AST.CDeclr (Just $ iid "func_result") ptrArrs Nothing [] N.undefNode), Nothing, Nothing)] N.undefNode]
      decls'        = -- formal_arg_decls ++ 
        -- note: we remove local decl duplicate, maybe we should let different label block to have different type decl in the ctxt, see test/scoped_dup_var.c
                      concatMap (\d -> renameDeclWithLabeledBlocks d labeledBlocks local_decl_vars fargs) (nubBy declLHSEq $ map (cff_trans_declaration . dropConstTyQual . dropStorageQual) (formal_arg_decls ++ local_var_decls)) ++ funcResult
      tyDef         = AST.CStorageSpec (AST.CTypedef N.undefNode)
      structDef     =
        AST.CTypeSpec (AST.CSUType
                       (AST.CStruct AST.CStructTag (Just structName) (Just decls') attrs N.undefNode) N.undefNode) 
  in AST.CDecl [tyDef, structDef] [(Just ctxtAlias, Nothing, Nothing)] N.undefNode
mkContext name labeledBlocks formal_arg_decls local_var_decls returnType ptrArrs local_decl_vars fargs = 
  let structName  = iid name
      ctxtAlias   = AST.CDeclr (Just (internalIdent (map toLower name))) [] Nothing [] N.undefNode
      attrs       = []
      
      isReturnVoid   = isVoidDeclSpec returnType
      
      funcResult | isReturnVoid = [] 
                 | otherwise    = [AST.CDecl returnType [(Just (AST.CDeclr (Just $ iid "func_result") ptrArrs Nothing [] N.undefNode), Nothing, Nothing)] N.undefNode]
      decls'        = -- formal_arg_decls ++ 
        -- note: we remove local decl duplicate, maybe we should let different label block to have different type decl in the ctxt, see test/scoped_dup_var.c
                      concatMap (\d -> renameDeclWithLabeledBlocks d labeledBlocks local_decl_vars fargs) (nubBy declLHSEq $ map (cff_trans_declaration . dropConstTyQual . dropStorageQual) (formal_arg_decls ++ local_var_decls)) ++ funcResult
      tyDef         = AST.CStorageSpec (AST.CTypedef N.undefNode)
      structDef     =
        AST.CTypeSpec (AST.CSUType
                       (AST.CStruct AST.CStructTag (Just structName) (Just decls') attrs N.undefNode) N.undefNode) 
  in AST.CDecl [tyDef, structDef] [(Just ctxtAlias, Nothing, Nothing)] N.undefNode