#include #include #include #include #include #include "apl9.h" int arrayalloccounts = 0; int datumalloccounts = 0; int debugmem; void * emalloc(ulong size) { void *res = malloc(size); if(res == nil && size > 0){ print("Out of memory! :(\n"); exits("emalloc"); } return res; } void * emallocz(ulong size, int clr) { void *res = mallocz(size, clr); if(res == nil && size > 0){ print("Out of memory! :(\n"); exits("emallocz"); } return res; } void * erealloc(void *ptr, ulong size) { void *res = realloc(ptr, size); if(res == nil && size > 0){ print("Out of memory! :(\n"); exits("erealloc"); } return res; } void checkmem(char *where) { if(debugmem){ print("Checking memory at: %s\n", where); poolcheck(mainmem); } } void freearray(Array *a) { if(a == nil) return; if(decref(a) == 0){ if(GetType(a) == AtypeArray){ for(int i = 0; i < a->size; i++) freearray(a->arraydata[i]); } if(GetType(a) == AtypeArray && a->size == 0) freearray(a->prototype); else free(a->rawdata); free(a->shape); free(a); arrayalloccounts--; } } Array * allocarray(arrayDataType t, int rank, int size) { Array *a = emalloc(sizeof(Array)); SetRank(a, rank); SetType(a, t); SetStrand(a, 0); a->ref = 1; a->size = size; a->shape = emalloc(sizeof(*a->shape) * rank); a->rawdata = emalloc(datasizes[t] * size); arrayalloccounts++; return a; } Datum * allocdatum(int tag, int shy) { Datum *d = emallocz(sizeof(Datum), 1); d->ref = 1; d->tag = tag; d->shy = shy; datumalloccounts++; return d; } void freedatum(Datum *d) { if(d == nil) return; if(decref(d) == 0){ /* print("FREE DATUM: %S\n", ppdatum(d)); */ switch(d->tag){ case ArrayTag: freearray(d->array); break; case FunctionTag: case BoundFunctionTag: freefunction(d->func); break; case HybridTag: break; case MonadicOpTag: case DyadicOpTag: freeoperator(d->operator); break; case LParTag: freestatement(d->stmt); break; case RParTag: break; case ArrowTag: break; case AssignmentTag: freestatement(d->names); break; case NameTag: free(d->name); break; default: print("Don't know how to free datum with tag: %d\n", d->tag); exits("freedatum"); } free(d); datumalloccounts--; } } void freefunction(Function f) { freearray(f.left); switch(f.type){ case FunctypeDfn: free(f.dfn); break; case FunctypePrim: break; case FunctypeOp: freeoperator(f.operator); break; case FunctypeQuad: free(f.quad); break; case FunctypeHybrid: break; case FunctypeTrain: for(int i = 0; i < f.train.nfuncs; i++) freefunction(f.train.funcs[i]); free(f.train.funcs); break; default: print("Missing case in freefunction: %d\n", f.type); exits("freefunction"); } } void freeoperator(Operator o) { freedatum(o.left); freedatum(o.right); switch(o.type){ case OperatortypeDop: free(o.dop); break; case OperatortypePrim: case OperatortypeHybrid: break; default: print("Missing case in freeoperator: %d\n", o.type); exits("freeoperator"); } } void freestatement(Statement s) { for(int i = 0; i < s.ntoks; i++) freedatum(s.toks[i]); free(s.toks); if(s.guard) freestatement(*s.guard); } Function dupfunction(Function f) { Function g = f; if(g.left) incref(g.left); switch(f.type){ case FunctypeDfn: g.dfn = runestrdup(f.dfn); break; case FunctypePrim: break; case FunctypeOp: g.operator = dupoperator(f.operator); break; case FunctypeQuad: g.quad = emalloc(sizeof(QuadnameDef)); *g.quad = *f.quad; break; case FunctypeHybrid: break; case FunctypeTrain: g.train.funcs = emalloc(sizeof(Function) * g.train.nfuncs); for(int i = 0; i < g.train.nfuncs; i++) g.train.funcs[i] = dupfunction(f.train.funcs[i]); break; default: print("Missing case in dupfunction: %d\n", f.type); exits("dupfunction"); } return g; } Operator dupoperator(Operator o) { Operator p = o; if(p.left) incref(p.left); if(p.right) incref(p.right); switch(o.type){ case OperatortypeDop: p.dop = runestrdup(o.dop); break; case OperatortypePrim: case OperatortypeHybrid: break; default: print("Missing case in dupoperator: %d\n", o.type); exits("dupoperator"); } return p; } void freeerrorguards(ErrorGuard *e) { ErrorGuard *next; while(e != nil){ next = e->next; freeerrorguard(e); e = next; } } void freeerrorguard(ErrorGuard *e) { if(e->active) freedfnframe(e->frame, 1); /* otherwise the frame is on the dfn stack and will be free'd that way */ free(e); }