(no commit message)
[geda-pcb/pcjc2.git] / src / mymem.c
blobb6b3c30db5381218aa2af62039bf03de93f8939b
1 /*
2 * COPYRIGHT
4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996 Thomas Nau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
23 * Thomas.Nau@rz.uni-ulm.de
28 /* memory management functions
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
35 #include "global.h"
37 #include <memory.h>
39 #include "data.h"
40 #include "error.h"
41 #include "mymem.h"
42 #include "misc.h"
43 #include "rats.h"
44 #include "rtree.h"
46 #ifdef HAVE_LIBDMALLOC
47 #include <dmalloc.h>
48 #endif
50 /* ---------------------------------------------------------------------------
51 * local prototypes
53 static void DSRealloc (DynamicStringType *, size_t);
56 /* This API is quite new, provide a version here */
57 #if !GLIB_CHECK_VERSION (2, 28, 0)
58 static void
59 g_list_free_full (GList *list, GDestroyNotify free_func)
61 g_list_foreach (list, (GFunc) free_func, NULL);
62 g_list_free (list);
64 #endif
66 /* ---------------------------------------------------------------------------
67 * get next slot for a rubberband connection, allocates memory if necessary
69 RubberbandType *
70 GetRubberbandMemory (void)
72 RubberbandType *ptr = Crosshair.AttachedObject.Rubberband;
74 /* realloc new memory if necessary and clear it */
75 if (Crosshair.AttachedObject.RubberbandN >=
76 Crosshair.AttachedObject.RubberbandMax)
78 Crosshair.AttachedObject.RubberbandMax += STEP_RUBBERBAND;
79 ptr = (RubberbandType *)realloc (ptr, Crosshair.AttachedObject.RubberbandMax *
80 sizeof (RubberbandType));
81 Crosshair.AttachedObject.Rubberband = ptr;
82 memset (ptr + Crosshair.AttachedObject.RubberbandN, 0,
83 STEP_RUBBERBAND * sizeof (RubberbandType));
85 return (ptr + Crosshair.AttachedObject.RubberbandN++);
88 void **
89 GetPointerMemory (PointerListType *list)
91 void **ptr = list->Ptr;
93 /* realloc new memory if necessary and clear it */
94 if (list->PtrN >= list->PtrMax)
96 list->PtrMax = STEP_POINT + (2 * list->PtrMax);
97 ptr = (void **)realloc (ptr, list->PtrMax * sizeof (void *));
98 list->Ptr = ptr;
99 memset (ptr + list->PtrN, 0,
100 (list->PtrMax - list->PtrN) * sizeof (void *));
102 return (ptr + list->PtrN++);
105 void
106 FreePointerListMemory (PointerListType *list)
108 free (list->Ptr);
109 memset (list, 0, sizeof (PointerListType));
112 /* ---------------------------------------------------------------------------
113 * get next slot for a box, allocates memory if necessary
115 BoxType *
116 GetBoxMemory (BoxListType *Boxes)
118 BoxType *box = Boxes->Box;
120 /* realloc new memory if necessary and clear it */
121 if (Boxes->BoxN >= Boxes->BoxMax)
123 Boxes->BoxMax = STEP_POINT + (2 * Boxes->BoxMax);
124 box = (BoxType *)realloc (box, Boxes->BoxMax * sizeof (BoxType));
125 Boxes->Box = box;
126 memset (box + Boxes->BoxN, 0,
127 (Boxes->BoxMax - Boxes->BoxN) * sizeof (BoxType));
129 return (box + Boxes->BoxN++);
133 /* ---------------------------------------------------------------------------
134 * get next slot for a connection, allocates memory if necessary
136 ConnectionType *
137 GetConnectionMemory (NetType *Net)
139 ConnectionType *con = Net->Connection;
141 /* realloc new memory if necessary and clear it */
142 if (Net->ConnectionN >= Net->ConnectionMax)
144 Net->ConnectionMax += STEP_POINT;
145 con = (ConnectionType *)realloc (con, Net->ConnectionMax * sizeof (ConnectionType));
146 Net->Connection = con;
147 memset (con + Net->ConnectionN, 0,
148 STEP_POINT * sizeof (ConnectionType));
150 return (con + Net->ConnectionN++);
153 /* ---------------------------------------------------------------------------
154 * get next slot for a subnet, allocates memory if necessary
156 NetType *
157 GetNetMemory (NetListType *Netlist)
159 NetType *net = Netlist->Net;
161 /* realloc new memory if necessary and clear it */
162 if (Netlist->NetN >= Netlist->NetMax)
164 Netlist->NetMax += STEP_POINT;
165 net = (NetType *)realloc (net, Netlist->NetMax * sizeof (NetType));
166 Netlist->Net = net;
167 memset (net + Netlist->NetN, 0, STEP_POINT * sizeof (NetType));
169 return (net + Netlist->NetN++);
172 /* ---------------------------------------------------------------------------
173 * get next slot for a net list, allocates memory if necessary
175 NetListType *
176 GetNetListMemory (NetListListType *Netlistlist)
178 NetListType *netlist = Netlistlist->NetList;
180 /* realloc new memory if necessary and clear it */
181 if (Netlistlist->NetListN >= Netlistlist->NetListMax)
183 Netlistlist->NetListMax += STEP_POINT;
184 netlist = (NetListType *)realloc (netlist,
185 Netlistlist->NetListMax * sizeof (NetListType));
186 Netlistlist->NetList = netlist;
187 memset (netlist + Netlistlist->NetListN, 0,
188 STEP_POINT * sizeof (NetListType));
190 return (netlist + Netlistlist->NetListN++);
192 /* ---------------------------------------------------------------------------
193 * get next slot for a pin, allocates memory if necessary
195 PinType *
196 GetPinMemory (ElementType *element)
198 PinType *new_obj;
200 new_obj = g_slice_new0 (PinType);
201 element->Pin = g_list_append (element->Pin, new_obj);
202 element->PinN ++;
204 return new_obj;
207 static void
208 FreePin (PinType *data)
210 g_slice_free (PinType, data);
213 /* ---------------------------------------------------------------------------
214 * get next slot for a pad, allocates memory if necessary
216 PadType *
217 GetPadMemory (ElementType *element)
219 PadType *new_obj;
221 new_obj = g_slice_new0 (PadType);
222 element->Pad = g_list_append (element->Pad, new_obj);
223 element->PadN ++;
225 return new_obj;
228 static void
229 FreePad (PadType *data)
231 g_slice_free (PadType, data);
234 /* ---------------------------------------------------------------------------
235 * get next slot for a via, allocates memory if necessary
237 PinType *
238 GetViaMemory (DataType *data)
240 PinType *new_obj;
242 new_obj = g_slice_new0 (PinType);
243 data->Via = g_list_append (data->Via, new_obj);
244 data->ViaN ++;
246 return new_obj;
249 static void
250 FreeVia (PinType *data)
252 g_slice_free (PinType, data);
255 /* ---------------------------------------------------------------------------
256 * get next slot for a Rat, allocates memory if necessary
258 RatType *
259 GetRatMemory (DataType *data)
261 RatType *new_obj;
263 new_obj = g_slice_new0 (RatType);
264 data->Rat = g_list_append (data->Rat, new_obj);
265 data->RatN ++;
267 return new_obj;
270 static void
271 FreeRat (RatType *data)
273 g_slice_free (RatType, data);
276 /* ---------------------------------------------------------------------------
277 * get next slot for a line, allocates memory if necessary
279 LineType *
280 GetLineMemory (LayerType *layer)
282 LineType *new_obj;
284 new_obj = g_slice_new0 (LineType);
285 layer->Line = g_list_append (layer->Line, new_obj);
286 layer->LineN ++;
288 return new_obj;
291 static void
292 FreeLine (LineType *data)
294 g_slice_free (LineType, data);
297 /* ---------------------------------------------------------------------------
298 * get next slot for an arc, allocates memory if necessary
300 ArcType *
301 GetArcMemory (LayerType *layer)
303 ArcType *new_obj;
305 new_obj = g_slice_new0 (ArcType);
306 layer->Arc = g_list_append (layer->Arc, new_obj);
307 layer->ArcN ++;
309 return new_obj;
312 static void
313 FreeArc (ArcType *data)
315 g_slice_free (ArcType, data);
318 /* ---------------------------------------------------------------------------
319 * get next slot for a text object, allocates memory if necessary
321 TextType *
322 GetTextMemory (LayerType *layer)
324 TextType *new_obj;
326 new_obj = g_slice_new0 (TextType);
327 layer->Text = g_list_append (layer->Text, new_obj);
328 layer->TextN ++;
330 return new_obj;
333 static void
334 FreeText (TextType *data)
336 g_slice_free (TextType, data);
339 /* ---------------------------------------------------------------------------
340 * get next slot for a polygon object, allocates memory if necessary
342 PolygonType *
343 GetPolygonMemory (LayerType *layer)
345 PolygonType *new_obj;
347 new_obj = g_slice_new0 (PolygonType);
348 layer->Polygon = g_list_append (layer->Polygon, new_obj);
349 layer->PolygonN ++;
351 return new_obj;
354 static void
355 FreePolygon (PolygonType *data)
357 g_slice_free (PolygonType, data);
360 /* ---------------------------------------------------------------------------
361 * gets the next slot for a point in a polygon struct, allocates memory
362 * if necessary
364 PointType *
365 GetPointMemoryInPolygon (PolygonType *Polygon)
367 PointType *points = Polygon->Points;
369 /* realloc new memory if necessary and clear it */
370 if (Polygon->PointN >= Polygon->PointMax)
372 Polygon->PointMax += STEP_POLYGONPOINT;
373 points = (PointType *)realloc (points, Polygon->PointMax * sizeof (PointType));
374 Polygon->Points = points;
375 memset (points + Polygon->PointN, 0,
376 STEP_POLYGONPOINT * sizeof (PointType));
378 return (points + Polygon->PointN++);
381 /* ---------------------------------------------------------------------------
382 * gets the next slot for a point in a polygon struct, allocates memory
383 * if necessary
385 Cardinal *
386 GetHoleIndexMemoryInPolygon (PolygonType *Polygon)
388 Cardinal *holeindex = Polygon->HoleIndex;
390 /* realloc new memory if necessary and clear it */
391 if (Polygon->HoleIndexN >= Polygon->HoleIndexMax)
393 Polygon->HoleIndexMax += STEP_POLYGONHOLEINDEX;
394 holeindex = (Cardinal *)realloc (holeindex, Polygon->HoleIndexMax * sizeof (int));
395 Polygon->HoleIndex = holeindex;
396 memset (holeindex + Polygon->HoleIndexN, 0,
397 STEP_POLYGONHOLEINDEX * sizeof (int));
399 return (holeindex + Polygon->HoleIndexN++);
402 /* ---------------------------------------------------------------------------
403 * get next slot for an element, allocates memory if necessary
405 ElementType *
406 GetElementMemory (DataType *data)
408 ElementType *new_obj;
410 new_obj = g_slice_new0 (ElementType);
412 if (data != NULL)
414 data->Element = g_list_append (data->Element, new_obj);
415 data->ElementN ++;
418 return new_obj;
421 static void
422 FreeElement (ElementType *data)
424 g_slice_free (ElementType, data);
427 /* ---------------------------------------------------------------------------
428 * get next slot for a library menu, allocates memory if necessary
430 LibraryMenuType *
431 GetLibraryMenuMemory (LibraryType *lib)
433 LibraryMenuType *menu = lib->Menu;
435 /* realloc new memory if necessary and clear it */
436 if (lib->MenuN >= lib->MenuMax)
438 lib->MenuMax += STEP_LIBRARYMENU;
439 menu = (LibraryMenuType *)realloc (menu, lib->MenuMax * sizeof (LibraryMenuType));
440 lib->Menu = menu;
441 memset (menu + lib->MenuN, 0,
442 STEP_LIBRARYMENU * sizeof (LibraryMenuType));
444 return (menu + lib->MenuN++);
447 /* ---------------------------------------------------------------------------
448 * get next slot for a library entry, allocates memory if necessary
450 LibraryEntryType *
451 GetLibraryEntryMemory (LibraryMenuType *Menu)
453 LibraryEntryType *entry = Menu->Entry;
455 /* realloc new memory if necessary and clear it */
456 if (Menu->EntryN >= Menu->EntryMax)
458 Menu->EntryMax += STEP_LIBRARYENTRY;
459 entry = (LibraryEntryType *)realloc (entry, Menu->EntryMax * sizeof (LibraryEntryType));
460 Menu->Entry = entry;
461 memset (entry + Menu->EntryN, 0,
462 STEP_LIBRARYENTRY * sizeof (LibraryEntryType));
464 return (entry + Menu->EntryN++);
467 /* ---------------------------------------------------------------------------
468 * get next slot for a DrillElement, allocates memory if necessary
470 ElementType **
471 GetDrillElementMemory (DrillType *Drill)
473 ElementType **element;
475 element = Drill->Element;
477 /* realloc new memory if necessary and clear it */
478 if (Drill->ElementN >= Drill->ElementMax)
480 Drill->ElementMax += STEP_ELEMENT;
481 element = (ElementType **)realloc (element,
482 Drill->ElementMax * sizeof (ElementType *));
483 Drill->Element = element;
484 memset (element + Drill->ElementN, 0,
485 STEP_ELEMENT * sizeof (ElementType *));
487 return (element + Drill->ElementN++);
490 /* ---------------------------------------------------------------------------
491 * get next slot for a DrillPoint, allocates memory if necessary
493 PinType **
494 GetDrillPinMemory (DrillType *Drill)
496 PinType **pin;
498 pin = Drill->Pin;
500 /* realloc new memory if necessary and clear it */
501 if (Drill->PinN >= Drill->PinMax)
503 Drill->PinMax += STEP_POINT;
504 pin = (PinType **)realloc (pin, Drill->PinMax * sizeof (PinType *));
505 Drill->Pin = pin;
506 memset (pin + Drill->PinN, 0, STEP_POINT * sizeof (PinType *));
508 return (pin + Drill->PinN++);
511 /* ---------------------------------------------------------------------------
512 * get next slot for a Drill, allocates memory if necessary
514 DrillType *
515 GetDrillInfoDrillMemory (DrillInfoType *DrillInfo)
517 DrillType *drill = DrillInfo->Drill;
519 /* realloc new memory if necessary and clear it */
520 if (DrillInfo->DrillN >= DrillInfo->DrillMax)
522 DrillInfo->DrillMax += STEP_DRILL;
523 drill = (DrillType *)realloc (drill, DrillInfo->DrillMax * sizeof (DrillType));
524 DrillInfo->Drill = drill;
525 memset (drill + DrillInfo->DrillN, 0, STEP_DRILL * sizeof (DrillType));
527 return (drill + DrillInfo->DrillN++);
530 /* ---------------------------------------------------------------------------
531 * frees memory used by a polygon
533 void
534 FreePolygonMemory (PolygonType *polygon)
536 if (polygon == NULL)
537 return;
539 free (polygon->Points);
540 free (polygon->HoleIndex);
542 if (polygon->Clipped)
543 poly_Free (&polygon->Clipped);
544 poly_FreeContours (&polygon->NoHoles);
546 memset (polygon, 0, sizeof (PolygonType));
549 /* ---------------------------------------------------------------------------
550 * frees memory used by a box list
552 void
553 FreeBoxListMemory (BoxListType *Boxlist)
555 if (Boxlist)
557 free (Boxlist->Box);
558 memset (Boxlist, 0, sizeof (BoxListType));
562 /* ---------------------------------------------------------------------------
563 * frees memory used by a net
565 void
566 FreeNetListMemory (NetListType *Netlist)
568 if (Netlist)
570 NET_LOOP (Netlist);
572 FreeNetMemory (net);
574 END_LOOP;
575 free (Netlist->Net);
576 memset (Netlist, 0, sizeof (NetListType));
580 /* ---------------------------------------------------------------------------
581 * frees memory used by a net list
583 void
584 FreeNetListListMemory (NetListListType *Netlistlist)
586 if (Netlistlist)
588 NETLIST_LOOP (Netlistlist);
590 FreeNetListMemory (netlist);
592 END_LOOP;
593 free (Netlistlist->NetList);
594 memset (Netlistlist, 0, sizeof (NetListListType));
598 /* ---------------------------------------------------------------------------
599 * frees memory used by a subnet
601 void
602 FreeNetMemory (NetType *Net)
604 if (Net)
606 free (Net->Connection);
607 memset (Net, 0, sizeof (NetType));
610 /* ---------------------------------------------------------------------------
611 * frees memory used by an attribute list
613 static void
614 FreeAttributeListMemory (AttributeListType *list)
616 int i;
618 for (i = 0; i < list->Number; i++)
620 free (list->List[i].name);
621 free (list->List[i].value);
623 free (list->List);
624 list->List = NULL;
625 list->Max = 0;
628 /* ---------------------------------------------------------------------------
629 * frees memory used by an element
631 void
632 FreeElementMemory (ElementType *element)
634 if (element == NULL)
635 return;
637 ELEMENTNAME_LOOP (element);
639 free (textstring);
641 END_LOOP;
642 PIN_LOOP (element);
644 free (pin->Name);
645 free (pin->Number);
647 END_LOOP;
648 PAD_LOOP (element);
650 free (pad->Name);
651 free (pad->Number);
653 END_LOOP;
655 g_list_free_full (element->Pin, (GDestroyNotify)FreePin);
656 g_list_free_full (element->Pad, (GDestroyNotify)FreePad);
657 g_list_free_full (element->Line, (GDestroyNotify)FreeLine);
658 g_list_free_full (element->Arc, (GDestroyNotify)FreeArc);
660 FreeAttributeListMemory (&element->Attributes);
661 memset (element, 0, sizeof (ElementType));
664 /* ---------------------------------------------------------------------------
665 * free memory used by PCB
667 void
668 FreePCBMemory (PCBType *pcb)
670 int i;
672 if (pcb == NULL)
673 return;
675 free (pcb->Name);
676 free (pcb->Filename);
677 free (pcb->PrintFilename);
678 FreeDataMemory (pcb->Data);
679 free (pcb->Data);
680 /* release font symbols */
681 for (i = 0; i <= MAX_FONTPOSITION; i++)
682 free (pcb->Font.Symbol[i].Line);
683 FreeLibraryMemory (&pcb->NetlistLib);
684 NetlistChanged (0);
685 FreeAttributeListMemory (&pcb->Attributes);
686 /* clear struct */
687 memset (pcb, 0, sizeof (PCBType));
690 /* ---------------------------------------------------------------------------
691 * free memory used by data struct
693 void
694 FreeDataMemory (DataType *data)
696 LayerType *layer;
697 int i;
699 if (data == NULL)
700 return;
702 VIA_LOOP (data);
704 free (via->Name);
706 END_LOOP;
707 g_list_free_full (data->Via, (GDestroyNotify)FreeVia);
708 ELEMENT_LOOP (data);
710 FreeElementMemory (element);
712 END_LOOP;
713 g_list_free_full (data->Element, (GDestroyNotify)FreeElement);
714 g_list_free_full (data->Rat, (GDestroyNotify)FreeRat);
716 for (layer = data->Layer, i = 0; i < MAX_LAYER + 2; layer++, i++)
718 FreeAttributeListMemory (&layer->Attributes);
719 TEXT_LOOP (layer);
721 free (text->TextString);
723 END_LOOP;
724 if (layer->Name)
725 free (layer->Name);
726 LINE_LOOP (layer);
728 if (line->Number)
729 free (line->Number);
731 END_LOOP;
732 g_list_free_full (layer->Line, (GDestroyNotify)FreeLine);
733 g_list_free_full (layer->Arc, (GDestroyNotify)FreeArc);
734 g_list_free_full (layer->Text, (GDestroyNotify)FreeText);
735 POLYGON_LOOP (layer);
737 FreePolygonMemory (polygon);
739 END_LOOP;
740 g_list_free_full (layer->Polygon, (GDestroyNotify)FreePolygon);
741 if (layer->line_tree)
742 r_destroy_tree (&layer->line_tree);
743 if (layer->arc_tree)
744 r_destroy_tree (&layer->arc_tree);
745 if (layer->text_tree)
746 r_destroy_tree (&layer->text_tree);
747 if (layer->polygon_tree)
748 r_destroy_tree (&layer->polygon_tree);
751 if (data->element_tree)
752 r_destroy_tree (&data->element_tree);
753 for (i = 0; i < MAX_ELEMENTNAMES; i++)
754 if (data->name_tree[i])
755 r_destroy_tree (&data->name_tree[i]);
756 if (data->via_tree)
757 r_destroy_tree (&data->via_tree);
758 if (data->pin_tree)
759 r_destroy_tree (&data->pin_tree);
760 if (data->pad_tree)
761 r_destroy_tree (&data->pad_tree);
762 if (data->rat_tree)
763 r_destroy_tree (&data->rat_tree);
764 /* clear struct */
765 memset (data, 0, sizeof (DataType));
768 /* ---------------------------------------------------------------------------
769 * releases the memory that's allocated by the library
771 void
772 FreeLibraryMemory (LibraryType *lib)
774 MENU_LOOP (lib);
776 ENTRY_LOOP (menu);
778 free (entry->AllocatedMemory);
779 free (entry->ListEntry);
781 END_LOOP;
782 free (menu->Entry);
783 free (menu->Name);
785 END_LOOP;
786 free (lib->Menu);
788 /* clear struct */
789 memset (lib, 0, sizeof (LibraryType));
792 /* ---------------------------------------------------------------------------
793 * reallocates memory for a dynamic length string if necessary
795 static void
796 DSRealloc (DynamicStringType *Ptr, size_t Length)
798 int input_null = (Ptr->Data == NULL);
799 if (input_null || Length >= Ptr->MaxLength)
801 Ptr->MaxLength = Length + 512;
802 Ptr->Data = (char *)realloc (Ptr->Data, Ptr->MaxLength);
803 if (input_null)
804 Ptr->Data[0] = '\0';
808 /* ---------------------------------------------------------------------------
809 * adds one character to a dynamic string
811 void
812 DSAddCharacter (DynamicStringType *Ptr, char Char)
814 size_t position = Ptr->Data ? strlen (Ptr->Data) : 0;
816 DSRealloc (Ptr, position + 1);
817 Ptr->Data[position++] = Char;
818 Ptr->Data[position] = '\0';
821 /* ---------------------------------------------------------------------------
822 * add a string to a dynamic string
824 void
825 DSAddString (DynamicStringType *Ptr, const char *S)
827 size_t position = Ptr->Data ? strlen (Ptr->Data) : 0;
829 if (S && *S)
831 DSRealloc (Ptr, position + 1 + strlen (S));
832 strcat (&Ptr->Data[position], S);
836 /* ----------------------------------------------------------------------
837 * clears a dynamic string
839 void
840 DSClearString (DynamicStringType *Ptr)
842 if (Ptr->Data)
843 Ptr->Data[0] = '\0';
846 /* ---------------------------------------------------------------------------
847 * strips leading and trailing blanks from the passed string and
848 * returns a pointer to the new 'duped' one or NULL if the old one
849 * holds only white space characters
851 char *
852 StripWhiteSpaceAndDup (const char *S)
854 const char *p1, *p2;
855 char *copy;
856 size_t length;
858 if (!S || !*S)
859 return (NULL);
861 /* strip leading blanks */
862 for (p1 = S; *p1 && isspace ((int) *p1); p1++);
864 /* strip trailing blanks and get string length */
865 length = strlen (p1);
866 for (p2 = p1 + length - 1; length && isspace ((int) *p2); p2--, length--);
868 /* string is not empty -> allocate memory */
869 if (length)
871 copy = (char *)realloc (NULL, length + 1);
872 strncpy (copy, p1, length);
873 copy[length] = '\0';
874 return (copy);
876 else
877 return (NULL);