/* sbrk1.c (emx+gcc) */

#define INCL_DOSMEMMGR
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ulimit.h>
#include <sys/uflags.h>

#ifdef SYS
#ifdef HEAPSIZE
/* Set the default heap size. */
unsigned long _sys_heap_size = HEAPSIZE;
#endif
extern void _sys_dump_heap_objs (FILE *f);
#endif

#define FALSE 0
#define TRUE  1

extern void showmem (void);


int main (int argc, char *argv[])
{
  ULONG rc;
  char buf[256], *p, *mem, *os2_mem;
  int i, n, fill_flag, read_flag, write_flag, size;
  int gmemlim, objrest;

  setvbuf (stdout, NULL, _IONBF, 0);
  if (argc == 2 && strcmp (argv[1], "-c") == 0)
    _uflags (_UF_SBRK_MODEL, _UF_SBRK_CONTIGUOUS);
  else if (argc == 2 && strcmp (argv[1], "-m") == 0)
    _uflags (_UF_SBRK_MODEL, _UF_SBRK_MONOTONOUS);
  else if (argc == 2 && strcmp (argv[1], "-a") == 0)
    _uflags (_UF_SBRK_MODEL, _UF_SBRK_ARBITRARY);
  else if (argc != 1)
    {
      printf ("Usage: %s [-cma]", argv[0]);
      return 1;
    }

  if (_osmode == OS2_MODE)
    showmem ();
#ifdef SYS
  _sys_dump_heap_objs (stdout);
#endif

  fill_flag = FALSE; read_flag = FALSE; write_flag = FALSE;
  mem = NULL; os2_mem = NULL;
  for (;;)
    {
      n = (int)sbrk (0);
      gmemlim = (int)ulimit (UL_GMEMLIM);
      objrest = (int)ulimit (UL_OBJREST);
      printf ("brk: 0x%x, UL_GMEMLIM: 0x%x, UL_OBJREST: 0x%x\n",
              n, gmemlim, objrest);
      printf ("? ");
      if (fgets (buf, sizeof (buf), stdin) == NULL)
        return 0;
      p = strchr (buf, '\n');
      if (p != NULL) *p = 0;
      switch (buf[0])
        {
        case 'q':
          return 0;
        case 'F':
          fill_flag = !fill_flag;
          printf ("Fill = %s\n", (fill_flag ? "on" : "off"));
          break;
        case 'R':
          read_flag = !read_flag;
          printf ("Read = %s\n", (read_flag ? "on" : "off"));
          break;
        case 'W':
          write_flag = !write_flag;
          printf ("Write = %s\n", (write_flag ? "on" : "off"));
          break;
        case 'm':
          n =  _uflags (0, 0) & _UF_SBRK_MODEL;
          if (n == _UF_SBRK_CONTIGUOUS)
            {
              _uflags (_UF_SBRK_MODEL, _UF_SBRK_MONOTONOUS);
              printf ("sbrk model: monotonous\n");
            }
          else if (n == _UF_SBRK_MONOTONOUS)
            {
              _uflags (_UF_SBRK_MODEL, _UF_SBRK_ARBITRARY);
              printf ("sbrk model: arbitrary\n");
            }
          else
            {
              _uflags (_UF_SBRK_MODEL, _UF_SBRK_CONTIGUOUS);
              printf ("sbrk model: contiguous\n");
            }
          break;
        case 'r':
          printf ("read -> 0x%.2x\n", *mem);
          break;
        case 's':
          if (_osmode == OS2_MODE)
            showmem ();
#ifdef SYS
          _sys_dump_heap_objs (stdout);
#endif
          break;
        case 'w':
          *mem = 'X';
          break;
        case 'f':
          memset (mem, '*', size);
          break;
        case 'o':
          if (buf[1] == 0)
            {
              if (os2_mem == NULL)
                puts ("OS/2 memory not allocated");
              else
                {
                  DosFreeMem (os2_mem);
                  os2_mem = NULL;
                }
            }
          else if (os2_mem != NULL)
            puts ("OS/2 memory already allocated");
          else if (_osmode == DOS_MODE)
            puts ("Cannot do this under DOS");
          else
            {
              size = (int)strtol (buf+1, NULL, 0);
              rc = DosAllocMem ((PPVOID)&os2_mem, size, PAG_READ | PAG_WRITE);
              if (rc != 0)
                printf ("DosAllocMem failed, rc=%lu\n", rc);
              else
                printf ("DosAllocMem -> 0x%x\n", (unsigned)os2_mem);
            }
          break;
        case '=':
          i = (int)strtol (buf+1, NULL, 0);
          p = brk ((void *)i);
          if ((int)p == 0)
            {
              printf ("ok.\n");
#ifdef SYS
              _sys_dump_heap_objs (stdout);
#endif
            }

          else
            perror ("brk()");
          break;
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
        case '+': case '-':
          size = (int)strtol (buf, NULL, 0);
          mem = sbrk (size);
          if (mem == (char *)-1)
            perror ("sbrk()");
          else
            {
              printf ("ok -> 0x%x\n", (int)mem);
#ifdef SYS
              _sys_dump_heap_objs (stdout);
#endif
              if (size > 0)
                {
                  if (read_flag)
                    printf ("read -> 0x%.2x\n", *mem);
                  if (write_flag)
                    *mem = 'X';
                  if (fill_flag)
                    memset (mem, '*', size);
                }
            }
          break;
        default:
          printf ("Pardon?\n");
          break;
        }
    }
}
