/*
     Compile this program without optimization.  The last values of data and
     stack size printed before the program stops give the approximate data
     and stack sizes available to you.  The single command line argument
     is the amount of physical memory on the machine in MegaBytes, which by
     default is taken to be 2048 MB in 32-bit mode and 4096 MB in 64-bit mode.

     For example, on a machine with 2 GB of physical memory, you would do the 
     following:

% gcc memchk.c
% a.out 2048
*/

#include <stdio.h>
#include <stdlib.h>

#define STKSZ	8096L
#define DATSZ	1024L * 1024L
#define DEFMS	2L * 1024L
#define DEFML	4L * 1024L

static long base;
static long data;

int stkchk(long lev, long mx) {
  long i,arr[STKSZ],sz;

  if (!lev) base = (long) arr;
  sz = ((long)arr)-((long)base);
  if (sz < 0L) sz = -sz;
  printf("datasize = %ld; stacksize = %ld\n",data,sz);
  if (sz > mx) exit(0);
  stkchk(lev+1, mx);
  for (i = 0; i < STKSZ; i++) arr[i] = lev;
}

int datchk(long mx) {
  long *hpalloc;

  data = DATSZ;
  hpalloc = (long *) malloc(data);
  while (hpalloc != NULL && data < mx) {
    printf("datasize = %ld; stacksize = %ld\n",data,0);
    free(hpalloc);
    data += DATSZ;
    hpalloc = (long *) malloc(data);
  }
}
  
int main(int argc, char **argv) {
  long mx, *ptr;

  if (sizeof(ptr) == 4)
    mx = DEFMS * DATSZ - 1L;
  else
    mx = DEFML * DATSZ - 1L;
  printf("Default mx = %ld\n",mx);
  if (argc > 1) mx = (long) atoi(argv[1]);
  if (sizeof(ptr) == 4 && (mx >= DEFMS || mx <= 0)) mx = DEFMS * DATSZ - 1L;
  else                                              mx = mx * DATSZ;
  printf("Final mx   = %ld\n",mx);
  datchk(mx);
  stkchk(0L,mx);
}
  
