cp-freeze-thaw.c   [plain text]


/* APPLE LOCAL PFE */
/* Freeze/thaw C++-specific trees and other data.
   Copyright (C) 2001  Free Software Foundation, Inc.
   Contributed by Ira L. Ruben (ira@apple.com)

This file is part of GNU CC.

GNU CC 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, or (at your option)
any later version.

GNU CC 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 GNU CC; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */

#include "config.h"

#ifdef PFE

#include "system.h"
#include "tree.h"
#include "toplev.h"
#include "c-common.h"
#include "hashtab.h"
#include "varray.h"
#include <string.h>

#include "cp/cp-tree.h"

#include "pfe.h"
#include "pfe-header.h"
#include "cp-freeze-thaw.h"

/*-------------------------------------------------------------------*/

/* Initialize language specific compiler state.  */
void
cxx_pfe_lang_init (lang)
  int lang;
{
  if (pfe_operation == PFE_DUMP)
    pfe_set_lang ((enum pfe_lang) lang == PFE_LANG_UNKNOWN ?
		  PFE_LANG_CXX : lang);
  else if (pfe_operation == PFE_LOAD)
    pfe_check_lang ((enum pfe_lang) lang == PFE_LANG_UNKNOWN ?
		    PFE_LANG_CXX : lang);
  
  /* Initialize the language specific compiler state */
  if (pfe_operation == PFE_DUMP)
    pfe_compiler_state_ptr->lang_specific  = (struct pfe_lang_compiler_state *)
      pfe_calloc (1, sizeof (struct pfe_lang_compiler_state));
}

/* Freeze/thaw language specific compiler state.  */
void 
cxx_freeze_thaw_compiler_state (pp)
     struct pfe_lang_compiler_state **pp;
{
  struct pfe_lang_compiler_state *hdr;
  int i;
 
  /* This is only called once from pfe_freeze_thaw_compiler_state()
     and only when *p is not NULL.  We cannot use PFE_FREEZE_THAW_PTR
     to freeze/thaw the pointer since we will always get NULL when
     thawing when PFE_NO_THAW_LOAD is 1.  Since we know *p is not NULL
     and since we know were only called once we don't need to use
     PFE_FREEZE_THAW_PTR anyhow.  */
     
  hdr = (struct pfe_lang_compiler_state *)pfe_freeze_thaw_ptr_fp (pp);
  
  PFE_GLOBAL_TO_HDR_IF_FREEZING (global_namespace);
  PFE_FREEZE_THAW_WALK (hdr->global_namespace);
  PFE_HDR_TO_GLOBAL_IF_THAWING (global_namespace);

  PFE_FREEZE_THAW_GLOBAL_TREE_ARRAY (cp_global_trees, CPTI_MAX);

  pfe_freeze_thaw_decl2_globals (hdr);

  /* cp/decl2.c */
  PFE_GLOBAL_TO_HDR_IF_FREEZING (static_ctors);
  PFE_FREEZE_THAW_WALK (hdr->static_ctors);
  PFE_HDR_TO_GLOBAL_IF_THAWING (static_ctors);

  /* cp/decl2.c */
  PFE_GLOBAL_TO_HDR_IF_FREEZING (static_dtors);
  PFE_FREEZE_THAW_WALK (hdr->static_dtors);
  PFE_HDR_TO_GLOBAL_IF_THAWING (static_dtors);
  
  /* We only freeze this because we are going to validate the
     consistency of the setting of this option on a load.  */
  PFE_GLOBAL_TO_HDR_IF_FREEZING (flag_apple_kext);

  /* cp/class.c */
  PFE_GLOBAL_TO_HDR_IF_FREEZING (local_classes);
  pfe_freeze_thaw_varray_tree (&hdr->local_classes);
  PFE_HDR_TO_GLOBAL_IF_THAWING (local_classes);

  pfe_freeze_thaw_decl_globals (hdr);

  /* cp/decl.c */
  PFE_GLOBAL_TO_HDR_IF_FREEZING (integer_two_node);
  PFE_FREEZE_THAW_WALK (hdr->integer_two_node);
  PFE_HDR_TO_GLOBAL_IF_THAWING (integer_two_node);

  /* cp/decl.c */
  PFE_GLOBAL_TO_HDR_IF_FREEZING (integer_three_node);
  PFE_FREEZE_THAW_WALK (hdr->integer_three_node);
  PFE_HDR_TO_GLOBAL_IF_THAWING (integer_three_node);

  /* cp/decl.c */
  PFE_GLOBAL_TO_HDR_IF_FREEZING (function_depth);
  PFE_HDR_TO_GLOBAL_IF_THAWING (function_depth);

  /* cp/decl.c */
  PFE_GLOBAL_TO_HDR_IF_FREEZING (scope_chain);
  pfe_freeze_thaw_saved_scope (&hdr->scope_chain);
  PFE_HDR_TO_GLOBAL_IF_THAWING (scope_chain);
  
  /* cp/decl.c */
  if (PFE_FREEZING)
    hdr->pfe_anon_cnt = pfe_get_anon_cnt ();
  else
    pfe_set_anon_cnt (hdr->pfe_anon_cnt);

  /* cp/pt.c.  */
  PFE_GLOBAL_TO_HDR_IF_FREEZING (processing_template_parmlist);
  PFE_HDR_TO_GLOBAL_IF_THAWING (processing_template_parmlist);

  pfe_freeze_thaw_pt_globals (hdr);

  /* cp/lex.c.  */
  for (i = 0; i < (int)LAST_CPLUS_TREE_CODE; ++i)
    {
       PFE_GLOBAL_TO_HDR_IF_FREEZING (operator_name_info[i]);
       pfe_freeze_thaw_operator_name_info (&hdr->operator_name_info[i]);
       PFE_HDR_TO_GLOBAL_IF_THAWING (operator_name_info[i]);

       PFE_GLOBAL_TO_HDR_IF_FREEZING (assignment_operator_name_info[i]);
       pfe_freeze_thaw_operator_name_info (&hdr->assignment_operator_name_info[i]);
       PFE_HDR_TO_GLOBAL_IF_THAWING (assignment_operator_name_info[i]);
    }
}

/* Check language-specific compiler options.  */
void 
cxx_pfe_check_settings (lang_specific)
    struct pfe_lang_compiler_state *lang_specific;
{
  if (pfe_operation == PFE_LOAD)
    if (lang_specific->flag_apple_kext != flag_apple_kext)
      fatal_error ("Inconsistent setting of -fapple-kext on pre-compiled header dump and load.");
}

/*-------------------------------------------------------------------*/

/* See freeze-thaw.c for documentation of these routines.  */

/* Handle 'd' nodes */
int 
cxx_pfe_freeze_thaw_decl (node)
     tree node;
{
  struct lang_decl *ld = DECL_LANG_SPECIFIC (node);
  
  if (ld
      && !DECL_GLOBAL_CTOR_P (node)
      && !DECL_GLOBAL_DTOR_P (node)
      && !DECL_THUNK_P (node)
      && !DECL_DISCRIMINATOR_P (node))
      PFE_FREEZE_THAW_WALK (DECL_ACCESS (node));

  switch (TREE_CODE (node))
    {
      case NAMESPACE_DECL:
        if (ld) 
	  pfe_freeze_thaw_binding_level (&NAMESPACE_LEVEL (node));
      	PFE_FREEZE_THAW_WALK (DECL_NAMESPACE_USING (node));
      	PFE_FREEZE_THAW_WALK (DECL_NAMESPACE_USERS (node));
      	return 1;
      
      case TYPE_DECL:
        if (ld)
          {
      	    PFE_FREEZE_THAW_WALK (DECL_TEMPLATE_INFO (node));
      	    PFE_FREEZE_THAW_WALK (DECL_SORTED_FIELDS (node)); /* NEEDED? */
      	  }
        return 0; /* let normal processing continue */
      	  
      case FUNCTION_DECL:
        if (ld)
          {
      	    PFE_FREEZE_THAW_WALK (DECL_TEMPLATE_INFO (node));
      	    if (DECL_THUNK_P (node))
      	      PFE_FREEZE_THAW_WALK (THUNK_VCALL_OFFSET (node));
      	    PFE_FREEZE_THAW_WALK (DECL_BEFRIENDING_CLASSES (node));
      	    PFE_FREEZE_THAW_WALK (ld->context);
      	    if (DECL_CLONED_FUNCTION_P (node))
      	      PFE_FREEZE_THAW_WALK (DECL_CLONED_FUNCTION (node));
      	    if (DECL_PENDING_INLINE_P (node))
      	      pfe_freeze_thaw_unparsed_text (&DECL_PENDING_INLINE_INFO (node));
      	    else
      	      pfe_freeze_thaw_language_function
      	      	((struct language_function **)&DECL_SAVED_FUNCTION_DATA (node));
      	  }
        return 0; /* let normal processing continue */

      case VAR_DECL:
        if (ld)
      	  PFE_FREEZE_THAW_WALK (DECL_TEMPLATE_INFO (node));
        return 0; /* let normal processing continue */

      case TEMPLATE_DECL:
        PFE_FREEZE_THAW_WALK (DECL_TEMPLATE_PARMS (node));
        PFE_FREEZE_THAW_WALK (DECL_TEMPLATE_INSTANTIATIONS (node));
        PFE_FREEZE_THAW_WALK (DECL_TEMPLATE_SPECIALIZATIONS (node));
        if (ld)
      	  {
            if (DECL_TEMPLATE_INFO (node))
              {
                PFE_FREEZE_THAW_WALK (DECL_TI_TEMPLATE (node));
                PFE_FREEZE_THAW_WALK (DECL_TI_ARGS (node));
              }
      	    PFE_FREEZE_THAW_WALK (DECL_TEMPLATE_INFO (node));
      	  }
      	PFE_FREEZE_THAW_WALK (DECL_TEMPLATE_RESULT (node));
        PFE_FREEZE_THAW_WALK (DECL_TEMPLATE_INSTANTIATIONS (node));
        PFE_FREEZE_THAW_WALK (DECL_INITIAL (node));
      	PFE_FREEZE_THAW_WALK (DECL_BEFRIENDING_CLASSES (node));
      	if (DECL_CLONED_FUNCTION_P (node))
      	  PFE_FREEZE_THAW_WALK (DECL_CLONED_FUNCTION (node));
        return 0; /* let normal processing continue */
      
      default:
	return 0; /* let normal processing continue */
    }
}

/* Handle 't' nodes */
int 
cxx_pfe_freeze_thaw_type (node)
     tree node;
{
  /* The qualification on the following code is patterned after the
     test done in cp/decl.c:lang_mark_tree().  */
     
  if (TYPE_LANG_SPECIFIC (node) &&
      !(TREE_CODE (node) == POINTER_TYPE
	&& TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE))
    {
      PFE_FREEZE_THAW_WALK (CLASSTYPE_PRIMARY_BINFO (node)); 		/* NEEDED? */
      PFE_FREEZE_THAW_WALK (CLASSTYPE_VFIELDS (node));			/* NEEDED? */
      PFE_FREEZE_THAW_WALK (CLASSTYPE_VBASECLASSES (node));		/* NEEDED? */
      PFE_FREEZE_THAW_WALK (CLASSTYPE_TAGS (node));			/* NEEDED? */
      PFE_FREEZE_THAW_WALK (CLASSTYPE_SIZE (node));			/* NEEDED? */
      PFE_FREEZE_THAW_WALK (CLASSTYPE_SIZE_UNIT (node));		/* NEEDED? */
      PFE_FREEZE_THAW_WALK (CLASSTYPE_PURE_VIRTUALS (node));		/* NEEDED? */
      PFE_FREEZE_THAW_WALK (CLASSTYPE_FRIEND_CLASSES (node));		/* NEEDED? */
      PFE_FREEZE_THAW_WALK (CLASSTYPE_RTTI (node));			/* NEEDED? */
      PFE_FREEZE_THAW_WALK (CLASSTYPE_METHOD_VEC (node));		/* NEEDED? */
      if (TREE_CODE (node) == RECORD_TYPE
          || TREE_CODE (node) == UNION_TYPE)
        PFE_FREEZE_THAW_WALK (CLASSTYPE_TEMPLATE_INFO (node));		/* NEEDED? */
      PFE_FREEZE_THAW_WALK (CLASSTYPE_BEFRIENDING_CLASSES (node));	/* NEEDED? */
    }
  
  switch (TREE_CODE (node))
    {      
      case TEMPLATE_TYPE_PARM:
         PFE_FREEZE_THAW_WALK (TEMPLATE_TYPE_PARM_INDEX (node));
         return 1;
   
      case FUNCTION_TYPE:
      case METHOD_TYPE:
         PFE_FREEZE_THAW_WALK (TYPE_RAISES_EXCEPTIONS (node));
         return 0;

      case TYPENAME_TYPE:
         PFE_FREEZE_THAW_WALK (TYPE_CONTEXT (node));
         PFE_FREEZE_THAW_WALK (TYPE_NAME (node));
         PFE_FREEZE_THAW_WALK (TYPENAME_TYPE_FULLNAME (node));
         PFE_FREEZE_THAW_WALK (TREE_TYPE (node));
         return 0; /* let normal processing continue */

      case TEMPLATE_TEMPLATE_PARM:
         PFE_FREEZE_THAW_WALK (TYPE_NAME (node));
         PFE_FREEZE_THAW_WALK (TEMPLATE_TYPE_PARM_INDEX (node));
         return 0; /* let normal processing continue */

      case BOUND_TEMPLATE_TEMPLATE_PARM:
         PFE_FREEZE_THAW_WALK (TEMPLATE_TYPE_PARM_INDEX (node));
         PFE_FREEZE_THAW_WALK (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (node));
         PFE_FREEZE_THAW_WALK (TYPE_NAME (node));
         if (PFE_FREEZING)
	   {
	    if (!PFE_IS_FROZEN (TYPE_TEMPLATE_INFO(node)))
	       {
		 PFE_FREEZE_THAW_WALK (TYPE_TI_TEMPLATE (node));
		 PFE_FREEZE_THAW_WALK (TYPE_TI_ARGS (node));
	       }
           }
         else if (PFE_IS_FROZEN (TYPE_TEMPLATE_INFO(node)))
           {
             PFE_FREEZE_THAW_WALK (TYPE_TI_TEMPLATE (node));
             PFE_FREEZE_THAW_WALK (TYPE_TI_ARGS (node));
           }
         return 0; /* let normal processing continue */

      case TYPEOF_TYPE:
         PFE_FREEZE_THAW_WALK (TYPE_FIELDS (node));
         return 0; /* let normal processing continue */

      case ENUMERAL_TYPE:
         PFE_FREEZE_THAW_WALK (ENUM_TEMPLATE_INFO (node));
         return 0; /* let normal processing continue */

      default:
  	 return 0; /* let normal processing continue */
    }
  
  return 0; /* let normal processing continue */
}

/* Handle 'c' and 'x' nodes */
int 
cxx_pfe_freeze_thaw_special (node)
     tree node;
{
  switch (TREE_CODE (node))
    {
      case IDENTIFIER_NODE:
	PFE_FREEZE_THAW_WALK (IDENTIFIER_NAMESPACE_BINDINGS (node));
	PFE_FREEZE_THAW_WALK (IDENTIFIER_CLASS_VALUE (node));
	PFE_FREEZE_THAW_WALK (IDENTIFIER_BINDING (node));
	PFE_FREEZE_THAW_WALK (IDENTIFIER_TEMPLATE (node));
	PFE_FREEZE_THAW_WALK (REAL_IDENTIFIER_TYPE_VALUE (node));
	
	/* The PFE_FREEZE_THAW_WALK() macro is defined to take the 
	   address of its argument.  IDENTIFIER_LABEL_VALUE,
	   IDENTIFIER_IMPLICIT_DECL, and IDENTIFIER_ERROR_LOCUS 
	   all use LANG_ID_FIELD to access their field.  But
	   LANG_ID_FIELD is defined as a ?: operation so we 
	   cannot just use the accessor macros as a argument to
	   PFE_FREEZE_THAW_WALK.  Thus we need to do what LANG_ID_FIELD
	   is trying to do explicitly here.  Sigh :-(  */
	   
	if (LANG_IDENTIFIER_CAST (node)->x)
	  {
	    PFE_FREEZE_THAW_WALK (LANG_IDENTIFIER_CAST (node)->x->label_value);
	    PFE_FREEZE_THAW_WALK (LANG_IDENTIFIER_CAST (node)->x->implicit_decl);
	    PFE_FREEZE_THAW_WALK (LANG_IDENTIFIER_CAST (node)->x->error_locus);
	  }
  	 return 0; /* let normal processing continue */
       
       case TEMPLATE_PARM_INDEX:
         PFE_FREEZE_THAW_WALK (TEMPLATE_PARM_DECL (node));	/* NEEDED? */
         PFE_FREEZE_THAW_WALK (TEMPLATE_PARM_DESCENDANTS (node)); /* NEEDED? */
         return 1;
       
       case PTRMEM_CST:
         PFE_FREEZE_THAW_WALK (PTRMEM_CST_MEMBER (node));	/* NEEDED? */
         return 1;
       
       case CPLUS_BINDING:
         if (BINDING_HAS_LEVEL_P (node))
           pfe_freeze_thaw_binding_level (&(((struct tree_binding*)node)->scope.level));
         else
           PFE_FREEZE_THAW_WALK (BINDING_SCOPE (node));		/* NEEDED? */
         PFE_FREEZE_THAW_WALK (BINDING_VALUE (node));		/* NEEDED? */
         PFE_FREEZE_THAW_WALK (TREE_CHAIN (node));
         return 1;
       
       case OVERLOAD:
         PFE_FREEZE_THAW_WALK (OVL_FUNCTION (node));		/* NEEDED? */
         PFE_FREEZE_THAW_WALK (OVL_CHAIN (node));		/* NEEDED? */
         return 1;
        
       case WRAPPER:
         /* FIXME?:ÊHOW DO I HANDLE WRAPPER_PTR VS. WRAPPER_INT ? */
         /* Currently it appears that WRAPPER_INT is never used in C++
            nor is routine that creates it -- build_int_wrapper().
            Therefore I will unconditionally always assume we have
            the pointer variant.  */
         pfe_freeze_thaw_ptr_fp (&WRAPPER_PTR (node));
         return 1;
       
       case SRCLOC:
         pfe_freeze_thaw_ptr_fp (&SRCLOC_FILE (node));
         return 1;
         
       default:
  	 return 0; /* let normal processing continue */
   }
}

/*-------------------------------------------------------------------*/

/* The routines below here are all to handle freezing/thawing of data
   specific to C++ that are not trees (although tree fields could
   point to this stuff).  */

/* Freeze/thaw cp_language_function defined in cp/cp-tree.h */
void 
pfe_freeze_thaw_language_function (pp)
     struct language_function **pp;
{
  tree *node;
  struct cp_language_function *p;
  
  p = (struct cp_language_function *)PFE_FREEZE_THAW_PTR (pp);
  if (!p)
    return;
    
  pfe_freeze_thaw_common_language_function (&p->base);
  PFE_FREEZE_THAW_WALK (p->x_dtor_label);
  PFE_FREEZE_THAW_WALK (p->x_current_class_ptr);
  PFE_FREEZE_THAW_WALK (p->x_current_class_ref);
  PFE_FREEZE_THAW_WALK (p->x_eh_spec_block);
  PFE_FREEZE_THAW_WALK (p->x_in_charge_parm);
  PFE_FREEZE_THAW_WALK (p->x_vtt_parm);
  PFE_FREEZE_THAW_WALK (p->x_return_value);
  
  node = (tree *)PFE_FREEZE_THAW_PTR (&p->x_vcalls_possible_p);
  PFE_FREEZE_THAW_WALK (*node);
  
  pfe_freeze_thaw_named_label_use_list (&p->x_named_label_uses);
  pfe_freeze_thaw_named_label_list (&p->x_named_labels);
  pfe_freeze_thaw_binding_level (&p->bindings);
  pfe_freeze_thaw_varray_tree (&p->x_local_names);
  pfe_freeze_thaw_ptr_fp (&p->cannot_inline);
}

/* Freeze/thaw saved_scope defined in cp/cp-tree.h */
void
pfe_freeze_thaw_saved_scope (pp)
     struct saved_scope **pp;
{
  struct saved_scope *p = (struct saved_scope *)PFE_FREEZE_THAW_PTR (pp);
  if (!p)
    return;

  PFE_FREEZE_THAW_WALK (p->old_bindings);
  PFE_FREEZE_THAW_WALK (p->old_namespace);
  PFE_FREEZE_THAW_WALK (p->decl_ns_list);
  PFE_FREEZE_THAW_WALK (p->class_name);
  PFE_FREEZE_THAW_WALK (p->class_type);
  PFE_FREEZE_THAW_WALK (p->access_specifier);
  PFE_FREEZE_THAW_WALK (p->function_decl);
  if (PFE_FREEZING)
    while (VARRAY_ACTIVE_SIZE (p->lang_base) > 0)
      pop_lang_context ();
  pfe_freeze_thaw_varray_tree (&p->lang_base);
  PFE_FREEZE_THAW_WALK (p->lang_name);
  PFE_FREEZE_THAW_WALK (p->template_parms);
  PFE_FREEZE_THAW_WALK (p->x_previous_class_type);
  PFE_FREEZE_THAW_WALK (p->x_previous_class_values);
  PFE_FREEZE_THAW_WALK (p->x_saved_tree);
  PFE_FREEZE_THAW_WALK (p->lookups);
  /* struct stmt_tree_s x_stmt_tree; Needed ??? */
  pfe_freeze_thaw_binding_level (&p->class_bindings);
  pfe_freeze_thaw_binding_level (&p->bindings);

  pfe_freeze_thaw_saved_scope (&p->prev);
 
}

/* Freeze/thaw operator_name_info arrays from lex.c  */
void
pfe_freeze_thaw_operator_name_info (p)
     struct operator_name_info_t *p;
{
  if (!p)
    return;

  PFE_FREEZE_THAW_WALK (p->identifier);
  pfe_freeze_thaw_ptr_fp (&p->name);
  pfe_freeze_thaw_ptr_fp (&p->mangled_name);
}

/*-------------------------------------------------------------------*/

/* This code below is to contol the checking of the size of various
   cp structs we freeze/thaw.  The reason for this is to attempt
   to verify that no fields of these structs are deleted or new ones
   added when each new merge is done with the fsf.  */

#define GCC_CP_STRUCTS
#define DEFCHECKSTRUCT(name, assumed_size) \
  extern void CONCAT2(check_struct_, name) PARAMS ((int));
#include "structs-to-check.def"
#undef DEFCHECKSTRUCT

#define DEFCHECKSTRUCT(name, assumed_size) CONCAT2(check_struct_, name),
static pfe_check_struct_t struct_check_functions[] =
{
#include "structs-to-check.def"
  NULL
};
#undef DEFCHECKSTRUCT

#define DEFCHECKSTRUCT(name, assumed_size)  assumed_size,
static int assumed_struct_size[] =
{
#include "structs-to-check.def"
  0
};
#undef DEFCHECKSTRUCT
#undef GCC_CP_STRUCTS

/* Called from pfe_check_all_struct_sizes() to check the cp struct
   sizes of the cxx-specific structs we freeze/thaw.  */
void 
cxx_pfe_check_all_struct_sizes ()
{
  int i;
  
  for (i = 0; i < (int)ARRAY_SIZE (struct_check_functions) - 1; ++i)
    (*struct_check_functions[i]) (assumed_struct_size[i]);
}

/*-------------------------------------------------------------------*/

DEFINE_CHECK_STRUCT_FUNCTION (cp_language_function)
DEFINE_CHECK_STRUCT_FUNCTION (saved_scope)
DEFINE_CHECK_STRUCT_FUNCTION (operator_name_info_t)

/*-------------------------------------------------------------------*/
#endif /* PFE */

#if 0

cd $gcc3/gcc/pfe; \
cc -no-cpp-precomp -c  -DIN_GCC  -g \
  -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wtraditional -pedantic -Wno-long-long \
  -DHAVE_CONFIG_H \
  -I$gcc3obj \
  -I. \
  -I.. \
  -I../config \
  -I../../include \
  cp-freeze-thaw.c -o ~/tmp.o -w 
  
#endif