Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

698 lines
20 KiB

/* pralloc.c */
/* allocation */
#include "prtypes.h"
#include "prstdio.h"
#include "prmain.h"
#include "prextern.h"
static char *my_Heap_alloc(int how_much);
static char *my_Str_alloc(int how_much);
static char *my_Temp_alloc(int how_much);
static char *my_alloc(int how_much,int status);
static void alloc_err(int msgNo);
static void fatal_alloc_err( int msgNo );
static void clean_pred(struct atom *atomptr);
#define NDEBUG 1 /* turn off checking */
/* #define PAIRS_TOGETHER 1 */
/* Only pairs are allocated on heap.
* This is useful in the case of 8086 architercture.
* as pairs take up a lot of room.
*/
/* define STATISTICS used to see how much each structure takes */
#define DEFAULTSIZE 32000 /* default memory zone size */
#define BUFFSIZE 1000 /* io buffer sizes */
/* byte alignment */
#define ALIGN(X) X>>=2,X<<=2,X+=4;
/* #define CAN_ALLOC(HOWMUCH, MAXPTR, CURRPTR) (((MAXPTR)-(CURRPTR)) > HOWMUCH)*/
#define CAN_ALLOC(HOWMUCH, MAXPTR, CURRPTR) ((CURRPTR + HOWMUCH) < MAXPTR)
/* This macro is used in the following circumstance:
* MAXPTR is the top of a zone,
* CURRPTR is the current pointer in the zone, it is less than MAXPTR.
* HOWMUCH is an integer that says how much you want to increase CURRPTR
* but you must stay less than MAXPTR.
*/
#define ADDRESS_DIFF(PTR1, PTR2) (char *)(PTR1) - (char *)(PTR2)
typedef char *void_ptr_t;
#ifdef STATISTICS
/* These numbers let you monitor how much the different
* structures consume.
* It may suprise you to know that integers and variables
* consume nothing because they are stored directly in a node.
*/
zone_size_t Atom_consumption;
zone_size_t Pair_consumption;
zone_size_t Node_consumption;
zone_size_t Clause_consumption;
zone_size_t String_consumption;
zone_size_t Predrec_consumption;
#ifdef REAL
zone_size_t Real_consumption;
#endif
#ifdef CHARACTER
zone_size_t Char_consumption;
#endif
/* Determine the upper bound used by data structures. */
static char *Heap_top_ptr;
static char *Str_top_ptr;
static dyn_ptr_t Dyn_top_ptr;
static node_ptr_t **Trail_top_ptr;
static subst_ptr_t Subst_top_ptr;
static temp_ptr_t Temp_top_ptr;
#define TestLimit(a,b) {if (a < b) a = b;}
#else /* ifndef STATISTICS */
#define TestLimit(a,b)
#endif
char *Read_buffer; /* read tokens into this */
char *Print_buffer; /* used by pr_string */
clause_ptr_t Bltn_pseudo_clause; /* see prlush.c */
node_ptr_t Printing_var_nodeptr; /* see prprint.c */
static zone_size_t heap_size, str_size, dyn_size, trail_size, subst_size, temp_size;
static char *Heap_mem; /* bottom of heap */
static char *Heap_ptr; /* allocate from this and move this up */
static char *HighHeap_ptr; /* top of heap */
static char *Str_mem; /* this is used to allocate permanent strings
and perhaps other objects if you want to keep the pairs
together
*/
static char *Str_ptr; /* allocate from this and move this up */
static char *HighStr_ptr; /* top of zone */
dyn_ptr_t Dyn_mem; /* bottom of control stack
(and zone for those temporary objects that disappear on backtrack,
although the substitution zone could do as well) */
dyn_ptr_t Dyn_ptr; /* allocate from this and move this up */
dyn_ptr_t HighDyn_ptr; /* top of control stack */
/* static start */
node_ptr_t **Trail_mem; /* the trail (used to reset variable bindings) */
node_ptr_t **Trail_ptr; /* like the others */
static node_ptr_t **HighTrail_ptr;/* top of zone */
subst_ptr_t Subst_mem; /* bottom of (global) variable bindings stack */
subst_ptr_t Subst_ptr; /* allocate from this and move this up */
static subst_ptr_t HighSubst_ptr;/* top of zone */
static zone_size_t subst_zone_size ;
static temp_ptr_t Temp_mem; /* For things you might want to
create with temp_assert...
clean with clean_temp */
static temp_ptr_t Temp_ptr; /* allocate from this and move this up */
static temp_ptr_t HighTemp_ptr;/* top of zone */
/* static end */
int Max_Readbuffer, Max_Printbuffer;
atom_ptr_t Nil;
node_ptr_t NilNodeptr;
/*******************************************************************************
ini_alloc()
Reserve zones and io buffers. On the Mac, all areas allocated are pointers
obtained through NewPtrClear.
******************************************************************************/
void ini_alloc()
{
extern void_ptr_t os_alloc(); /* see the machine dependent file */
extern int read_config(); /* see the machine dependent file */
if(!read_config(&heap_size, &str_size, &dyn_size, &trail_size, &subst_size, &temp_size,
&Max_Readbuffer, &Max_Printbuffer))
{
heap_size = DEFAULTSIZE;
str_size = DEFAULTSIZE;
dyn_size = DEFAULTSIZE;
trail_size = DEFAULTSIZE;
subst_size = DEFAULTSIZE;
temp_size = DEFAULTSIZE;
Max_Readbuffer = BUFFSIZE;
Max_Printbuffer = BUFFSIZE;
}
Heap_mem = os_alloc(heap_size);
Heap_ptr = Heap_mem;
HighHeap_ptr = Heap_mem + heap_size;
Str_mem = os_alloc(heap_size);
Str_ptr = Str_mem;
HighStr_ptr = Str_mem + str_size;
Dyn_mem = (dyn_ptr_t)os_alloc(dyn_size);
Dyn_ptr = Dyn_mem;
HighDyn_ptr = (dyn_ptr_t)((char *)Dyn_mem + dyn_size);
Trail_mem = (node_ptr_t **)os_alloc(trail_size);
Trail_ptr = Trail_mem;
HighTrail_ptr = (node_ptr_t **)((char *)Trail_mem + trail_size);
Subst_mem = (subst_ptr_t)os_alloc(subst_size);
subst_zone_size = subst_size ;
Subst_ptr = Subst_mem;
HighSubst_ptr = (subst_ptr_t)((char *)Subst_mem + subst_size);
Temp_mem = (temp_ptr_t)os_alloc(temp_size);
Temp_ptr = Temp_mem;
HighTemp_ptr = (temp_ptr_t)((char *)Temp_mem + temp_size);
Read_buffer = os_alloc((zone_size_t)Max_Readbuffer);
Print_buffer = os_alloc((zone_size_t)Max_Printbuffer);
#ifdef STATISTICS
Heap_top_ptr = Heap_ptr ;
Str_top_ptr = Str_ptr ;
Dyn_top_ptr = Dyn_ptr ;
Trail_top_ptr = Trail_ptr ;
Subst_top_ptr = Subst_ptr ;
Temp_top_ptr = Temp_ptr ;
#endif
}
/* Release all the memory allocated */
void end_alloc ( void )
{
os_free( (char *) Heap_mem ) ;
Heap_mem = Heap_ptr = HighHeap_ptr = NULL ;
os_free( (char *) Str_mem ) ;
Str_mem = Str_ptr = HighStr_ptr = NULL ;
os_free( (char *) Dyn_mem ) ;
Dyn_mem = Dyn_ptr = HighDyn_ptr = NULL ;
os_free( (char *) Trail_mem ) ;
Trail_mem = Trail_ptr = HighTrail_ptr = NULL ;
os_free( (char *) Subst_mem ) ;
Subst_mem = Subst_ptr = HighSubst_ptr = NULL ;
os_free( (char *) Temp_mem ) ;
Temp_mem = Temp_ptr = HighTemp_ptr = NULL ;
os_free( Read_buffer ) ;
Read_buffer = NULL ;
os_free( Print_buffer ) ;
Print_buffer = NULL ;
}
/*******************************************************************************
my_Heap_alloc()
******************************************************************************/
static void_ptr_t my_Heap_alloc(how_much)
my_alloc_size_t how_much;
{
void_ptr_t ret;
ALIGN(how_much);
if(!CAN_ALLOC(how_much ,HighHeap_ptr, Heap_ptr))
{
fatal_alloc_err(MSG_HEAPSPACE);
}
else
ret = Heap_ptr;
Heap_ptr += how_much;
TestLimit(Heap_top_ptr,Heap_ptr);
return(ret);
}
/*******************************************************************************
my_Str_alloc()
Allocate on permanent string space.
******************************************************************************/
static void_ptr_t my_Str_alloc(how_much)
my_alloc_size_t how_much;
{
void_ptr_t ret;
ALIGN(how_much);
if(!(CAN_ALLOC(how_much, HighStr_ptr, Str_ptr)))
{
fatal_alloc_err(MSG_STRINGSPACE);
}
else
ret = Str_ptr;
Str_ptr += how_much;
TestLimit(Str_top_ptr,Str_ptr);
return(ret);
}
/********************************************************************************
my_Dyn_alloc()
Allocate on the control stack.
This is for objects that disappear on backtracking.
******************************************************************************/
dyn_ptr_t my_Dyn_alloc(how_much)
my_alloc_size_t how_much; /* in bytes */
{
dyn_ptr_t ret;
ALIGN(how_much);
if(!(CAN_ALLOC(how_much ,HighDyn_ptr, Dyn_ptr)))
{
alloc_err(MSG_DYNSPACE);
}
else
ret = Dyn_ptr;
Dyn_ptr += how_much;
TestLimit(Dyn_top_ptr,Dyn_ptr);
return(ret);
}
/*******************************************************************************
my_Trail_alloc()
Allocate one trail element.
******************************************************************************/
node_ptr_t ** my_Trail_alloc()
{
node_ptr_t ** ret;
if( Trail_ptr >= HighTrail_ptr)
{
alloc_err(MSG_TRAILSPACE);
}
else
ret = Trail_ptr;
Trail_ptr ++;
TestLimit(Trail_top_ptr,Trail_ptr);
return(ret);
}
/*******************************************************************************
my_Subst_alloc()
Allocate how_much bytes on the substitution stack.
This is more speed-efficient than allocating struct substs on an array of
structures, as there is no multiplication.
******************************************************************************/
subst_ptr_t my_Subst_alloc(how_much)
my_alloc_size_t how_much; /* in bytes */
{
subst_ptr_t ret;
zone_size_t sz = Subst_ptr - Subst_mem ;
#ifndef NDEBUG
if(how_much % sizeof(struct subst))INTERNAL_ERROR("alignment");
#endif
if ( sz + how_much >= subst_zone_size )
{
alloc_err(MSG_SUBSTSPACE);
}
else
ret = Subst_ptr;
(char_ptr_t) Subst_ptr += how_much ;
if ( ret >= HighSubst_ptr ) {
INTERNAL_ERROR("subst alloc");
}
return ret ;
}
/********************************************************************************
my_Temp_alloc()
Allocate in temporary memory.
This is for objects that disappear
when you clean that zone.
******************************************************************************/
static temp_ptr_t my_Temp_alloc(how_much)
my_alloc_size_t how_much; /* in bytes */
{
temp_ptr_t ret;
ALIGN(how_much);
if(!(CAN_ALLOC(how_much, HighTemp_ptr, Temp_ptr)))
{
fatal_alloc_err(MSG_TEMPSPACE);
}
else
ret = Temp_ptr;
Temp_ptr += how_much;
TestLimit(Temp_top_ptr,Temp_ptr);
return(ret);
}
/*******************************************************************************
my_alloc()
Allocate anywhere.
******************************************************************************/
static char *my_alloc(how_much, status)
my_alloc_size_t how_much;
int status;
{
#ifdef DEBUG
char buff[80];
sprintf(buff, "my_alloc allocating %ld of type %d\n",
(long) how_much, status);
#endif
switch(status)
{
case PERMANENT:
return(my_Heap_alloc(how_much));
case DYNAMIC:
return(my_Dyn_alloc(how_much));
case TEMPORARY:
return(my_Temp_alloc(how_much));
case PERM_STRING:
return(my_Str_alloc(how_much));
default:
INTERNAL_ERROR("mem alloc status");
return(NULL);/* for lint */
}
}
/*******************************************************************************
offset_subst()
Check your compiler on this !! This should return the difference
between two far pointers
******************************************************************************/
long offset_subst(substptr)
subst_ptr_t substptr;
{
long result = substptr - Subst_mem ;
return result ;
}
/*******************************************************************************
get_string()
Allocate a string of length (how_much - 1)
******************************************************************************/
string_ptr_t get_string(how_much, status)
my_alloc_size_t how_much;
{
#ifdef STATISTICS
String_consumption += how_much;
#endif
return((string_ptr_t)my_alloc(how_much, status));
}
#ifdef REAL
/*******************************************************************************
get_real()
There is no need for a get_integer, as integers fit in a node.
******************************************************************************/
real_ptr_t get_real(status)
{
#ifdef STATISTICS
Real_consumption += sizeof(real);
#endif
#ifdef PAIRS_TOGETHER
if(status == PERMANENT)status = PERM_STRING;
#endif
return((real_ptr_t)my_alloc((my_alloc_size_t)sizeof(real), status));
}
#endif
/*******************************************************************************
get_atom();
******************************************************************************/
atom_ptr_t get_atom(status)
{
#ifdef STATISTICS
Atom_consumption += sizeof(struct atom);
#endif
#ifdef PAIRS_TOGETHER
if(status == PERMANENT)status = PERM_STRING;
#endif
return((atom_ptr_t)my_alloc((my_alloc_size_t)sizeof(struct atom), status));
}
/*******************************************************************************
get_pair()
******************************************************************************/
pair_ptr_t get_pair(status)
{
#ifdef STATISTICS
Pair_consumption += sizeof(struct pair);
#endif
return((pair_ptr_t)my_alloc((my_alloc_size_t)sizeof(struct pair), status));
}
/*******************************************************************************
get_node()
It might be an idea to actually allocate a pair and return the pointer
to the head. This would simplify garbage collection.
******************************************************************************/
node_ptr_t get_node(status)
{
#ifdef STATISTICS
Node_consumption += sizeof(struct node);
#endif
#ifdef PAIRS_TOGETHER
if(status == PERMANENT)status = PERM_STRING;
#endif
return((node_ptr_t)my_alloc((my_alloc_size_t)sizeof(struct node), status));
}
/*******************************************************************************
get_clause();
Allocate a clause.
******************************************************************************/
clause_ptr_t get_clause(status)
{
clause_ptr_t result;
#ifdef STATISTICS
Clause_consumption += sizeof(struct clause);
#endif
#ifdef PAIRS_TOGETHER
if(status == PERMANENT)status = PERM_STRING;
#endif
result = (clause_ptr_t) my_alloc((my_alloc_size_t)sizeof(struct clause), status);
if(status == TEMPORARY)
CLAUSEPTR_FLAGS(result) = 0x1;
else
CLAUSEPTR_FLAGS(result) = 0x0;
return( result );
}
/*******************************************************************************
get_pred()
This is called whenever a new predicate is defined.
******************************************************************************/
pred_rec_ptr_t get_pred()
{
pred_rec_ptr_t ret;
int status = PERMANENT;
#ifdef STATISTICS
Predrec_consumption += sizeof(struct predicate_record);
#endif
#ifdef PAIRS_TOGETHER
if(status == PERMANENT)status = PERM_STRING;
#endif
ret = (pred_rec_ptr_t)my_alloc((my_alloc_size_t)sizeof(struct predicate_record), status);
ret->next_pred = NULL;
ret->atom = Nil;
return(ret);
}
/*******************************************************************************
alloc_err()
******************************************************************************/
static void alloc_err(int msgNo)
{
extern dyn_ptr_t Parent;
char msg[100];
char * s = msgDeref( msgNo ) ;
sprintf(msg, "%s %s\n", s, msgDeref( MSG_OVERFLOW) ) ;
errmsg(msg);
tty_pr_mesg(MSG_SEESTACK);
if(read_yes())
dump_stack(Parent);
spexit(1);
}
/*******************************************************************************
fatal_alloc_err()
******************************************************************************/
static void fatal_alloc_err( int msgNo )
{
extern dyn_ptr_t Parent;
char msg[100];
char * s = msgDeref( msgNo ) ;
sprintf(msg, "%s %s\n", s, msgDeref( MSG_OVERFLOW ) );
errmsg(msg);
spexit(1);
}
/*******************************************************************************
check_object()
This should be used to check the internal consistency of the interpreter.
It doesnt make much sense on an IBM PC, because you can only meaningfully
compare pointers from the same segment.
******************************************************************************/
int check_object(objptr)
char *objptr;
{
if(((objptr >= HighHeap_ptr)||(objptr < Heap_mem))
&& ((objptr >= HighDyn_ptr)||(objptr < Dyn_mem))
&& ((objptr >= HighTemp_ptr)||(objptr < Temp_mem))
&& ((objptr >= HighStr_ptr)||(objptr < Str_mem))
)
{
errmsg(msgDeref(MSG_WILDPOINTER));
#ifndef HUNTBUGS
spexit(1);
#endif
return(0);
}
else
return(1);
}
/*********************************************************************
clean_temp()
Clean the temporary zone.
***************************************************************************************************************************************/
void clean_temp()
{
extern pred_rec_ptr_t First_pred;
extern atom_ptr_t LastBuiltin;
pred_rec_ptr_t predptr;
for(predptr = First_pred; predptr != NULL; predptr = predptr->next_pred)
{
if(predptr->atom > LastBuiltin)
clean_pred(predptr->atom);
}/* for */
Temp_ptr = Temp_mem;
}
/*********************************************************************
clean_pred()
Clean all temporary clauses from an atom.
***************************************************************************************************************************************/
static void clean_pred(atomptr)
atom_ptr_t atomptr;
{
clause_ptr_t previous, first, clauseptr;
clauseptr = ATOMPTR_CLAUSE(atomptr);
first = clauseptr;
while(first != NULL && IS_TEMPORARY_CLAUSE(first))
{
first = CLAUSEPTR_NEXT(first);
}
ATOMPTR_CLAUSE(atomptr) = first;
if(first == NULL)return;
else
clauseptr = first;
while(clauseptr)
{
while(clauseptr && !(IS_TEMPORARY_CLAUSE(clauseptr)))
{
previous = clauseptr;
clauseptr = CLAUSEPTR_NEXT(clauseptr);
}
if(clauseptr == NULL)return;
else
while(clauseptr && IS_TEMPORARY_CLAUSE(clauseptr))
{
clauseptr = CLAUSEPTR_NEXT(clauseptr);
}
CLAUSEPTR_NEXT(previous) = clauseptr;
}
}
/*********************************************************************************
space_left()
********************************************************************************/
void space_left(ph, pstr, pd, ps, ptr, pte)
zone_size_t *ph, *pstr, *pd, *ps, *ptr, *pte;
{
*ph = ADDRESS_DIFF(HighHeap_ptr, Heap_ptr);
*pstr = ADDRESS_DIFF(HighStr_ptr, Str_ptr);
*pd = ADDRESS_DIFF(HighDyn_ptr, Dyn_ptr);
*ps = ADDRESS_DIFF(HighTrail_ptr, Trail_ptr);
*ptr = ADDRESS_DIFF(HighSubst_ptr, Subst_ptr);
*pte = ADDRESS_DIFF(HighTemp_ptr, Temp_ptr);
}
/*******************************************************************************
ini_globals().
This is where global structures that are used everywhere are allocated
******************************************************************************/
void ini_globals()
{
extern PRFILE * Curr_infile, *Curr_outfile;
extern node_ptr_t Printing_var_nodeptr;
atom_ptr_t intern();
Nil = intern("()");
Curr_infile = PRSTDIN; /* Initially all input is from terminal */
Curr_outfile = PRSTDOUT;/* Initially all output is to terminal */
NilNodeptr = get_node(PERMANENT);
NODEPTR_TYPE(NilNodeptr) = ATOM;
NODEPTR_ATOM(NilNodeptr) = Nil;
Bltn_pseudo_clause = get_clause(PERMANENT);/* see prlush.c */
CLAUSEPTR_GOALS(Bltn_pseudo_clause) = NilNodeptr;
CLAUSEPTR_HEAD(Bltn_pseudo_clause) = NilNodeptr;
Printing_var_nodeptr = get_node(PERMANENT); /* used by pr_solution */
NODEPTR_TYPE(Printing_var_nodeptr) = VAR;
}
void end_globals ( void )
{
/* Nothing to do for now */
}
int allocPercent ( int status )
{
zone_size_t bottom, top, size ;
#ifdef STATISTICS
switch(status) {
case PERMANENT:
size = heap_size ;
bottom = (zone_size_t) Heap_mem ;
top = (zone_size_t) Heap_top_ptr ;
break ;
case DYNAMIC:
size = dyn_size ;
bottom = (zone_size_t) Dyn_mem ;
top = (zone_size_t) Dyn_top_ptr ;
break ;
case TEMPORARY:
size = temp_size ;
bottom = (zone_size_t) Temp_mem ;
top = (zone_size_t) Temp_top_ptr ;
break ;
case PERM_STRING:
size = str_size ;
bottom = (zone_size_t) Str_mem ;
top = (zone_size_t) Str_top_ptr ;
break ;
case SUBST_MEM:
size = subst_size ;
bottom = (zone_size_t) Subst_mem ;
top = (zone_size_t) Subst_top_ptr ;
break ;
case TRAIL_MEM:
size = trail_size ;
bottom = (zone_size_t) Trail_mem ;
top = (zone_size_t) Trail_top_ptr ;
break ;
default:
size = bottom = top = 0 ;
}
return ((top - bottom) * 100) / size ;
#else
return 0 ;
#endif
}
/* end of file */