
/* "WOL", an integrated circuit layout tool,
   Copyright (C) 1983, 1990 California Institute of Technology.
   Author: Massimo Sivilotti
   Thanks to: Glenn Gribble, Marty Sirkin, Sylvie Rychebusch
	      Maryann Mayer, Carver Mead, Rick Koshi, Torre Lande
   Maintainer: John Lazzaro
   Maintainers's address: lazzaro@hobiecat.cs.caltech.edu;
                          CB 425/ CU Boulder/Boulder CO 91125. 
			  Send questions, bug fixes, to this address.

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 (Version 1, 1989).

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; see the file COPYING.  If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

/* Output from p2c, the Pascal-to-C translator */
/* p2c: wolopt.text, line 9: Note: Range checking is OFF [216] */
/* p2c: wolopt.text, line 10: Note: Stack checking is OFF [217] */
/* p2c: wolopt.text, line 16: Note: Range checking is ON [216] */
/* From input file "core.text" */


/* Change these for testing */



#include "global.h"


#define CORE_G
#include "core.h"


/*extern void cell_stuff_check_mem(void);*/


void core_init(void)
{
/* p2c: core.text, line 55:
 * Warning: Procedure mark not yet supported [118] */
  mark((void *)(&core_base));
  core_kinds = 0;
}


long core_add(long s, Char *n)
{
  long Result;
  core_info_rec *WITH;

  Result = -1;
  if (core_kinds >= core_max_kinds) {
    printf("\007core_add: out of core_kinds--re-compile core.\n");
    return Result;
  }
  WITH = &core_info[core_kinds];
  Result = core_kinds;
  core_kinds++;   /* increment for next stuff */
  WITH->list = NULL;
  if (s & 1)
    s++;
  WITH->size = s + sizeof(core_rec);   /*-sizeof(core_recp)*/
  if (WITH->size & 1)
    printf("\007We're fucked.\n");
  WITH->free = 0;
  WITH->used = 0;
  WITH->alloc = 0;
  WITH->news = 0;
  WITH->frees = 0;
  WITH->rels = 0;
  strcpy(WITH->name, n);
  return Result;
}


/*extern void asm_newbytes(void **p, long z);*/


void core_new(core_rec **ptr, short kind)
{
  core_info_rec *WITH;

  if (kind >= core_kinds) {
    printf("core_alloc: unknown kind=%d\n", kind);
    *ptr = NULL;
    return;
  }
  WITH = &core_info[kind];
  WITH->news++;
  WITH->used++;
  if (WITH->list == NULL) {
    asm_newbytes((void **)ptr, WITH->size+4);
    (*ptr)->magic = core_magic;
    (*ptr)->kind = kind;
    WITH->alloc++;
    /* CHECK FOR MEMORY RUNNING OUT HERE!!! */
/*    cell_stuff_check_mem();*/
  } else {
    *ptr = WITH->list;
    if ((*ptr)->magic != core_magic)
      printf("\007core_new: magic=%d ptr=%ld\n", (*ptr)->magic, (long)(*ptr));
    if ((*ptr)->kind != kind)
      printf("\007core_new: kind=%d ptr=%ld\n", (*ptr)->kind, (long)(*ptr));
    WITH->list = WITH->list->next;
    WITH->free--;
  }
  (*ptr)++;
}


/* Same as core_new, but zero all fields in the user's area */
void core_cnew(core_rec **ptr, short kind)
{
  core_new(ptr, kind);
  if (*ptr != NULL)
    memset(*ptr, 0, core_info[kind].size - sizeof(core_rec));
/* p2c: core.text, line 122:
 * Note: Suspicious mixture of sizes in NA_FILLBYTE [173] */
}


void core_free(core_rec **ptr)
{
  core_rec *lptr;
  core_info_rec *WITH;

  if (*ptr == NULL) {
    printf("\007core_free:  Ptr=NIL.\n");
    return;
  }
  lptr = *ptr - 1;
  if (lptr->magic != core_magic) {
    printf("\007core_free:  Ptr not allocated by core_new.\n");
    printf("Ptr=%ld lptr=%ld magic=%d\n",
	   (long)(*ptr), (long)lptr, lptr->magic);
  } else {
    WITH = &core_info[lptr->kind];
    WITH->frees++;
    WITH->used--;
    WITH->free++;
    lptr->next = WITH->list;
    WITH->list = lptr;
  }
  *ptr = NULL;
}


#define field           8


void core_stats(FILE **out)
{
  long i, total_total, used_total, FORLIM;
  core_info_rec *WITH;

  fprintf(*out, "   Type    %*s%*s%*s%*s%*s%*s%*s%*s\n\n",
	  field, "Size", field, "News", field, "Frees", field, "Free", field,
	  "Used", field, "Alloc", field, "Rels", field, "TOTAL");
  total_total = 0;
  used_total = 0;
  FORLIM = core_kinds;
  for (i = 0; i < FORLIM; i++) {
    WITH = &core_info[i];
    fprintf(*out, "#%ld %*s%*ld%*ld%*ld%*ld%*ld%*ld%*ld%*ld\n",
	    i, field, WITH->name, field, WITH->size, field, WITH->news, field,
	    WITH->frees, field, WITH->free, field, WITH->used, field,
	    WITH->alloc, field, WITH->rels, field, WITH->size * WITH->alloc);
    total_total += WITH->size * WITH->alloc;
    used_total += WITH->size * WITH->used;
  }
  fprintf(*out, "%75s\n", "-------");
  fprintf(*out, "%64ld%%%10ld\n", used_total * 100 / total_total, total_total);
}

#undef field


void core_mark(core_rec **ptr)
{
  core_rec *m;

  asm_newbytes((void **)ptr, sizeof(core_rec)+4);
/* p2c: core.text, line 177:
 * Warning: Procedure mark not yet supported [118] */
  mark((void *)(&m));
  (*ptr)->next = m;   /* Real marker */
  (*ptr)->magic = core_magic;
  (*ptr)->kind = core_marker;
}


void core_release(core_rec **ptr)
{
  core_rec **l;
  long i, r;
  void *real_mark;
  long FORLIM;
  core_info_rec *WITH;

  if (*ptr == NULL) {
    printf("\007core_release:  Ptr=NIL.\n");
    return;
  }
  if ((*ptr)->magic != core_magic || (*ptr)->kind != core_marker) {
    printf("\007core_release:  Ptr not allocated by core_mark.\n");
    return;
  }
  real_mark = (*ptr)->next;
  FORLIM = core_kinds;
  for (i = 0; i < FORLIM; i++) {
    WITH = &core_info[i];
    if (WITH->list != NULL) {
      r = 0;
      l = &WITH->list;
      while (*l != NULL) {
	if ((long)(*l) >= (long)real_mark) {   /* Release this object */
	  /*writeln('Releasing object at ',ord(l^));*/
	  *l = (*l)->next;
	  r++;
	} else
	  l = &(*l)->next;
      }
      WITH->rels += r;
      WITH->free -= r;
      WITH->alloc -= r;
    }
  }
/* p2c: core.text, line 215:
 * Warning: Procedure release not yet supported [118] */
  release((void *)(&real_mark));
}


/* module CORE */




/* End. */
