/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#ifndef INCLUDE_ECXX_CTL_CXX_PORTABILITY_CPP
#error "this file cannot be compiled directly"
#endif
#undef INCLUDE_ECXX_CTL_CXX_PORTABILITY_CPP


//
// Function protoypes from standard C library
//
extern "C" void abort();

extern "C" void *malloc(size_t size);
extern "C" void free(void* ptr);


//
// Generic C++ portability helper functions
//
extern "C" {


    int       atexit(void(*)(void )              ) { return -1; }
    int __cxa_atexit(void(*)(void*), void*, void*) { return -1; }


    void      _pure_virtual   () __ECXX_ATTR_NORETURN;
    void      _pure_virtual   () { abort(); }

    void     __pure_virtual   () __ECXX_ATTR_NORETURN;
    void     __pure_virtual   () { abort(); }

    void __cxa_pure_virtual   () __ECXX_ATTR_NORETURN;
    void __cxa_pure_virtual   () { abort(); }

    void __cxa_deleted_virtual() __ECXX_ATTR_NORETURN;
    void __cxa_deleted_virtual() { abort(); }


    __extension__ typedef int __guard __ECXX_ATTR_MODE_DI;

    int  __cxa_guard_acquire(__guard* g) { return !*( (char *) g ); }
    void __cxa_guard_release(__guard* g) { *( (char*) g ) = 1;      }
    void __cxa_guard_abort  (__guard*  ) {                          }


} // extern "C"


//
// Implementations of operator new and delete
//
void* operator new(size_t size) noexcept
{
    void* ret = malloc(size);
    if(!ret) abort();

    return ret;
}


void* operator new[](size_t size) noexcept
{
    void* ret = malloc(size);
    if(!ret) abort();

    return ret;
}


void operator delete(void* ptr) noexcept
{ if(ptr) free(ptr); }


void operator delete[](void* ptr) noexcept
{ if(ptr) free(ptr ); }


#if __cplusplus >= 201300L


void operator delete(void* ptr, size_t) noexcept
{ if(ptr) free(ptr); }


void operator delete[](void* ptr, size_t) noexcept
{ if(ptr) free(ptr ); }


#endif
