/***************************************************************************** * "Irit" - the 3d polygonal solid modeller. * * * * Written by: Gershon Elber Ver 0.2, Mar. 1990 * ****************************************************************************** * Dynamic allocation module of "Irit" - the 3d polygonal solid modeller. * *****************************************************************************/ /* #define DEBUG Print more messages in free/allocating. */ #ifdef __MSDOS__ #include #include #endif /* __MSDOS__ */ #include #include #include "program.h" #include "allocate.h" #include "attribut.h" #include "ctrl-brk.h" #include "graphgen.h" #include "windows.h" #define MAGIC_FREE_NUM 1234567890L /* Used in DEBUG mode to mark free. */ #define ALLOCATE_NUM 100 /* Number of objects to allocate at once. */ #ifdef __MSDOS__ /* Used to say when to update core left on screen: */ static time_t LastTimeAlloc = 0; #endif /* __MSDOS__ */ /* Used for fast reallocation of most common object types: */ static VertexStruct *VertexFreedList = NULL; static PolygonStruct *PolygonFreedList = NULL; static ObjectStruct *ObjectFreedList = NULL; static void FreePolygonList(PolygonStruct * PPoly); static void FreeVertexList(VertexStruct * VFirst); /***************************************************************************** * My Routine to allocate dynamic memory. All program requests must call this * * routine (no direct call to malloc). Dies if no memory. * * In order to reduce the overhead of the allocation, basic objects are * * allocated in ALLOCATE_NUM number of objects blocks. * *****************************************************************************/ char *MyMalloc(unsigned int Size, AllocateStructType Type) { char *p; int i; # ifdef __MSDOS__ if (time(NULL) != LastTimeAlloc) { if (GlblWasCtrlBrk) FatalError(NULL); /* Jump to main loop. */ WndwStatusWindowUpdate(); /* Print free memory. */ LastTimeAlloc = time(NULL); } # endif /* __MSDOS__ */ switch (Type) { case ALLOC_VERTEX: # ifdef DEBUG fprintf(stderr, "MyMalloc: Allocate vertex type"); # endif /* DEBUG */ if (VertexFreedList != NULL) { p = (char *) VertexFreedList; VertexFreedList = VertexFreedList -> Pnext; } else { VertexStruct *V; /* Allocate ALLOCATE_NUM objects, returns first one as new */ /* and chain together the rest of them into the free list. */ p = malloc(Size * ALLOCATE_NUM); V = (VertexStruct *) p; if (V != NULL) { for (i = 1; i < ALLOCATE_NUM-1; i++) V[i].Pnext = &V[i+1]; V[ALLOCATE_NUM-1].Pnext = NULL; VertexFreedList = &V[1]; } } break; case ALLOC_POLYGON: # ifdef DEBUG fprintf(stderr, "MyMalloc: Allocate polygon type"); # endif /* DEBUG */ if (PolygonFreedList != NULL) { p = (char *) PolygonFreedList; PolygonFreedList = PolygonFreedList -> Pnext; } else { PolygonStruct *V; /* Allocate ALLOCATE_NUM objects, returns first one as new */ /* and chain together the rest of them into the free list. */ p = malloc(Size * ALLOCATE_NUM); V = (PolygonStruct *) p; if (V != NULL) { for (i = 1; i < ALLOCATE_NUM-1; i++) V[i].Pnext = &V[i+1]; V[ALLOCATE_NUM-1].Pnext = NULL; PolygonFreedList = &V[1]; } } break; case ALLOC_OBJECT: # ifdef DEBUG fprintf(stderr, "MyMalloc: Allocate object type"); # endif /* DEBUG */ if (ObjectFreedList != NULL) { p = (char *) ObjectFreedList; ObjectFreedList = ObjectFreedList -> Pnext; } else { ObjectStruct *V; /* Allocate ALLOCATE_NUM objects, returns first one as new */ /* and chain together the rest of them into the free list. */ p = malloc(Size * ALLOCATE_NUM); V = (ObjectStruct *) p; if (V != NULL) { for (i = 1; i < ALLOCATE_NUM-1; i++) V[i].Pnext = &V[i+1]; V[ALLOCATE_NUM-1].Pnext = NULL; ObjectFreedList = &V[1]; } } break; default: # ifdef DEBUG fprintf(stderr, "MyMalloc: Allocate undefined Type %d", Type); # endif /* DEBUG */ p = malloc(Size); break; } # ifdef DEBUG fprintf(stderr, " (Size = %d, ptr = %p)\n", Size, p); # endif /* DEBUG */ if (p != NULL) return p; WndwInputWindowPutStr("Not enough memory - program cannt continue"); GlblFatalError = TRUE; /* Long jump to main intraction loop - irit.c module */ longjmp(GlblLongJumpBuffer, 2); return NULL; /* Only makes warnings silent... */ } /***************************************************************************** * Routine to free a given structure, which is not needed any more * * Note usually only object will be given directly to MyFree which * * recursively free its structure... * * Also, it is perfectly legal to call with NULL to MyFree... * *****************************************************************************/ void MyFree(char *p, AllocateStructType Type) { int index; char Line[LINE_LEN]; ObjectStruct *PObj; # ifdef __MSDOS__ if (time(NULL) != LastTimeAlloc) { if (GlblWasCtrlBrk) FatalError(NULL); /* Jump to main loop. */ WndwStatusWindowUpdate(); /* Print free memory. */ LastTimeAlloc = time(NULL); } # endif /* __MSDOS__ */ if (p == NULL) return; # ifdef DEBUG /* The following might fail if a record is freed without any usage! */ if (*((long *) p) == MAGIC_FREE_NUM) FatalError("MyFree:Free the same record twice, dies"); *((long *) p) = MAGIC_FREE_NUM; /* And set it for next time... */ # endif /* DEBUG */ switch (Type) { case ALLOC_VERTEX: # ifdef DEBUG fprintf(stderr, "MyFree: free vertex type\n"); # endif /* DEBUG */ FreeVertexList((VertexStruct *) p); break; case ALLOC_POLYGON: # ifdef DEBUG fprintf(stderr, "MyFree: free polygon type\n"); # endif /* DEBUG */ FreePolygonList((PolygonStruct *) p); break; case ALLOC_OBJECT: # ifdef DEBUG fprintf(stderr, "MyFree: free object type\n"); # endif /* DEBUG */ PObj = (ObjectStruct *) p; if (PObj -> Count > 1) { /* Do not free object - just decrease its reference count. */ PObj -> Count--; break; } switch (((ObjectStruct *) p) -> ObjType) { case UNDEF_OBJ: break; case POLY_OBJ: /* Free the polygon list. */ MyFree((char *) (PObj -> U.Pl.P), ALLOC_POLYGON); ReleaseStrAttrib(PObj); break; case NUMERIC_OBJ: case VECTOR_OBJ: case CTLPT_OBJ: case MATRIX_OBJ: case STRING_OBJ: break; case OBJ_LIST_OBJ: /* Need to dereference elements in list. */ index = 0; while (index < MAX_OBJ_LIST && PObj -> U.PObjList[index] != NULL) { if (PObj -> U.PObjList[index] -> Count-- == 1) MyFree((char *) (PObj -> U.PObjList[index]), ALLOC_OBJECT); index++; } break; case CURVE_OBJ: CagdCrvFree(PObj -> U.Crv.Crv); if (PObj -> U.Crv.PLPolys) CagdPolylineFree(PObj -> U.Crv.PLPolys); if (PObj -> U.Crv.CtlPoly) CagdPolylineFree(PObj -> U.Crv.CtlPoly); ReleaseStrAttrib(PObj); break; case SURFACE_OBJ: CagdSrfFree(PObj -> U.Srf.Srf); if (PObj -> U.Srf.PLPolys) CagdPolylineFreeList(PObj -> U.Srf.PLPolys); if (PObj -> U.Srf.CtlMesh) CagdPolylineFreeList(PObj -> U.Srf.CtlMesh); if (PObj -> U.Srf.Polygons) MyFree((char *) PObj -> U.Srf.Polygons, ALLOC_OBJECT); ReleaseStrAttrib(PObj); break; default: /* Kill the program - something is WRONG! */ sprintf(Line, "MyFree: Attempt to free undefined Object type %d", PObj -> ObjType); FatalError(Line); break; } /* Add it to global freed object list: */ PObj -> Pnext = ObjectFreedList; ObjectFreedList = PObj; break; default: # ifdef DEBUG fprintf(stderr, "MyFree: Free undefined Type %d\n", Type); # endif /* DEBUG */ free(p); break; } } /***************************************************************************** * Routine to free a polygon list each consists of circular vertex list. * *****************************************************************************/ static void FreePolygonList(PolygonStruct *PPoly) { PolygonStruct *Ptemp, *PPolyHead = PPoly; # ifdef DEBUG fprintf(stderr, "FreePolygonList: free polygon list\n"); # endif /* DEBUG */ while (PPoly) { FreeVertexList(PPoly -> V); Ptemp = PPoly; PPoly = PPoly -> Pnext; } /* Now chain this new list to the global freed polygon list: */ Ptemp -> Pnext = PolygonFreedList; PolygonFreedList = PPolyHead; } /***************************************************************************** * Routine to free a circular vertex list - one polygon contour. * *****************************************************************************/ static void FreeVertexList(VertexStruct *VFirst) { VertexStruct *V = VFirst, *Vtemp; # ifdef DEBUG fprintf(stderr, "FreeVertexList: free vertex list\n"); # endif /* DEBUG */ if (VFirst == NULL) return; do { Vtemp = V; V = V -> Pnext; } while (V != NULL && V != VFirst); /* Both - circular or NULL terminated. */ /* Now chain this new list to the global freed vertex list: */ Vtemp -> Pnext = VertexFreedList; VertexFreedList = VFirst; } /***************************************************************************** * Allocate one Vertex Structure: * *****************************************************************************/ VertexStruct * AllocVertex(ByteType Count, ByteType Tags, PolygonStruct * PAdj, VertexStruct * Pnext) { VertexStruct *p; p = (VertexStruct *) MyMalloc(sizeof(VertexStruct), ALLOC_VERTEX); p -> Normal[0] = p -> Normal[1] = p -> Normal[2] = 0.0; p -> Count = Count; p -> Tags = Tags; p -> Pnext = Pnext; p -> PAdj = PAdj; return p; } /***************************************************************************** * Allocate one Polygon Structure: * *****************************************************************************/ PolygonStruct * AllocPolygon(ByteType Count, ByteType Tags, VertexStruct * V, PolygonStruct * Pnext) { PolygonStruct *p; p = (PolygonStruct *) MyMalloc(sizeof(PolygonStruct), ALLOC_POLYGON); p -> Plane[0] = p -> Plane[1] = p -> Plane[2] = p -> Plane[3] = 0.0; p -> Count = Count; p -> Tags = Tags; p -> V = V; p -> Pnext = Pnext; return p; } /***************************************************************************** * Allocate one Object Structure: * *****************************************************************************/ ObjectStruct * AllocObject(char *Name, IritObjectType ObjType, ObjectStruct * Pnext) { ObjectStruct *p; p = (ObjectStruct *) MyMalloc(sizeof(ObjectStruct), ALLOC_OBJECT); strcpy(p -> Name, Name); p -> ObjType = ObjType; p -> Count = 1; p -> Pnext = Pnext; p -> U.Pl.P = NULL; /* To be on the safe size... */ p -> U.Crv.PLPolys = NULL; p -> U.Crv.CtlPoly = NULL; p -> U.Srf.PLPolys = NULL; p -> U.Srf.CtlMesh = NULL; p -> U.Srf.Polygons = NULL; p -> U.Attr.NumStrAttribs = 0; return p; }