/*      mem.cpp
//
//      Copyright 2005-2011 Lucas Tsatiris <systester.project@gmail.com>
//
//      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.
//
*/


/* Determine the total amount of RAM and the amount of RAM used in bytes */

#include <stdio.h>

#if defined(_MSC_VER) || defined (__MINGW32__)	/* MS Windows */
#if !defined(_CLI)
#define _CRT_SECURE_NO_DEPRECATE 1
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable: 4996)
#endif
#include <windows.h>
#include <memory.h>
#else
#if defined(__osf__)		/* Tru64 unix */
#include <sys/sysinfo.h>
#include <machine/hal_sysinfo.h>
#else
#if defined(__hppa)		/* HPUX */
#include <sys/param.h>
#include <sys/pstat.h>
#else
#if defined (__APPLE__)	/* Mac OS X */
#include <stdint.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#else /* All others */
#include <unistd.h>
#endif /* __APPLE__ */
#endif /* __hppa */
#endif /* __osf__ */
#endif /* _MSC_VER ... */

/* Determine the total amount of RAM */
double
totalmem ()
{
  double systemram = 0;
  char fpbug_workaround[1024];
#if defined(__linux) || defined(__sun)	/* Linux or Solaris */
  systemram =
    (double) sysconf (_SC_PHYS_PAGES) * (double) sysconf (_SC_PAGESIZE);
#else
#if defined(__osf__)		/* Tru64 Unix */
  long long_buff;
  getsysinfo (GSI_PHYSMEM, (caddr_t) & long_buff, sizeof (long_buff), 0, 0);
  systemram = (double) long_buff *(double) 1024;
#else
#if defined(__hppa)		/* HPUX */
  struct pst_static pst;
  if (pstat_getstatic (&pst, sizeof (pst), (size_t) 1, 0) != -1)
    systemram = (double) pst.physical_memory * 1024;
#else    
#if defined (__APPLE__)	/* Mac OS X */
  uint64_t size;
  size_t len = sizeof(size);
  int mib[2] = { CTL_HW, HW_MEMSIZE };
  u_int namelen = sizeof(mib) / sizeof(mib[0]);

  if (sysctl(mib, namelen, &size, &len, NULL, 0) == 0)
    systemram = (double) size;
#else
#if defined (_MSC_VER) || defined (__MINGW32__)	/* Microsoft Windows */
  MEMORYSTATUS memstatus;
  GlobalMemoryStatus (&memstatus);
  systemram = memstatus.dwTotalPhys;
#endif /* _MSC_VER */
#endif /* __APPLE__ */
#endif /* __hppa */
#endif /* __osf__ */
#endif /* __linux || __sun */
  sprintf (fpbug_workaround, "%f", systemram);
  return systemram;
}
