echo ; /*  Note that this declares an int available externally 
 lc -cwusf -v -M -y Frags.c
 blink Frags.o LIB lib:amiga.lib DEFINE _stdout=_echo SD SC ND VERBOSE
 quit
*/

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* |_o_o|\\ Copyright (c) 1987 The Software Distillery.  All Rights Reserved */
/* |. o.| || This program may not be distributed without the permission of   */
/* | .  | || the authors:                                          BBS:      */
/* | o  | ||   Gordon Keener    John Toebes                  (919)-471-6436  */
/* |  . |//                                                                  */
/* ======                                                                    */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                           */
/* Frags.c - Original version found on 1.2 Gamma Toolkit disk.               */
/*           But this doesn't look much like it anymore...                   */
/*                                                                           */
/*  To compile, simply execute the C program as an execute script            */
/*    SHAR eat your heart out...                                             */
/*                                                                           */
/*  Requires Lattice 4.0 and does not use any assembler startup...           */
/*   Runs ONLY from CLI and ignores all parameters - the same restrictions   */
/*   as the original one..                                                   */
/*                                                                           */
/*  In doing this we might have just broken every rule in the book as well   */
/*   as made up several new tricks along the way.  But then again, what can  */
/*   you say when we produce a 552 byte module COMPLETELY written in C?      */
/*                                                                           */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "exec/types.h"
#include "exec/exec.h" 
#include "exec/execbase.h"
#include "libraries/dosextens.h"
#include "proto/exec.h"
#include "proto/dos.h"
#include <string.h>

struct DosLibrary  *DOSBase;
/* BPTR               stdout; */

int    printf(char *,);

#define ABSEXECBASE ((struct ExecBase **)4L)
#define MAXSIZE 30
#define MINSIZE 3

frags()   /* What difference does it make since it has no startup code? */
{
   /* these used in inner loop */
   register unsigned long      size;
   register unsigned long      compare;
   register long               *range;

   long                        counts[32];  /* Guard against overflow */
   register struct MemChunk    *chunk; 
   register struct MemHeader   *mem;

   memset((char *)counts, 0, sizeof(counts));

   if (!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",0)))
      return;

   echo = (int)Output();

   Forbid();
   for (mem = (struct MemHeader *)(*ABSEXECBASE)->MemList.lh_Head;
        mem -> mh_Node.ln_Succ;
        mem = (struct MemHeader *)mem->mh_Node.ln_Succ)
      {
      for (chunk = mem -> mh_First; chunk; chunk = chunk -> mc_Next)
         {
         /* We check powers of 2 until we find one bigger than */
         /* the current element size. We also track a pointer  */
         /* through our table so we don't have to do an array  */
         /* index at the end.                                  */

         /* Anyone caught coding like this will be shot..      */
         for (range = counts, compare = 1 << MINSIZE;
             (compare <<= 1) < (unsigned long)chunk->mc_Bytes;
             range++);

         /* We don't overflow because the array is big enough */
         (*range)++;
         }
      }
   Permit();

   printf (" Free memory size distribution:\n      Size  Count\n");

   for (size  = (1 << MINSIZE), range = counts;
        size <= (1 << MAXSIZE);
        size <<= 1, range++)
      if (*range)
         printf ("%10ld: %4ld\n", size, *range);

   CloseLibrary((struct Library *)DOSBase);
}
