4 * \brief Memory management functions.
8 * <h1><b>Copyright.</b></h1>\n
10 * PCB, interactive printed circuit board design
12 * Copyright (C) 1994,1995,1996 Thomas Nau
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 * Contact addresses for paper mail and Email:
30 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
32 * Thomas.Nau@rz.uni-ulm.de
50 #ifdef HAVE_LIBDMALLOC
54 /* ---------------------------------------------------------------------------
57 static void DSRealloc (DynamicStringType
*, size_t);
60 /* This API is quite new, provide a version here */
61 #if !GLIB_CHECK_VERSION (2, 28, 0)
63 g_list_free_full (GList
*list
, GDestroyNotify free_func
)
65 g_list_foreach (list
, (GFunc
) free_func
, NULL
);
71 * \brief Get the next slot for a rubberband connection.
73 * Allocates memory if necessary.
76 GetRubberbandMemory (void)
78 RubberbandType
*ptr
= Crosshair
.AttachedObject
.Rubberband
;
80 /* realloc new memory if necessary and clear it */
81 if (Crosshair
.AttachedObject
.RubberbandN
>=
82 Crosshair
.AttachedObject
.RubberbandMax
)
84 Crosshair
.AttachedObject
.RubberbandMax
+= STEP_RUBBERBAND
;
85 ptr
= (RubberbandType
*)realloc (ptr
, Crosshair
.AttachedObject
.RubberbandMax
*
86 sizeof (RubberbandType
));
87 Crosshair
.AttachedObject
.Rubberband
= ptr
;
88 memset (ptr
+ Crosshair
.AttachedObject
.RubberbandN
, 0,
89 STEP_RUBBERBAND
* sizeof (RubberbandType
));
91 return (ptr
+ Crosshair
.AttachedObject
.RubberbandN
++);
95 GetPointerMemory (PointerListType
*list
)
97 void **ptr
= list
->Ptr
;
99 /* realloc new memory if necessary and clear it */
100 if (list
->PtrN
>= list
->PtrMax
)
102 list
->PtrMax
= STEP_POINT
+ (2 * list
->PtrMax
);
103 ptr
= (void **)realloc (ptr
, list
->PtrMax
* sizeof (void *));
105 memset (ptr
+ list
->PtrN
, 0,
106 (list
->PtrMax
- list
->PtrN
) * sizeof (void *));
108 return (ptr
+ list
->PtrN
++);
112 FreePointerListMemory (PointerListType
*list
)
115 memset (list
, 0, sizeof (PointerListType
));
119 * \brief Get the next slot for a box.
121 * Allocates memory if necessary.
124 GetBoxMemory (BoxListType
*Boxes
)
126 BoxType
*box
= Boxes
->Box
;
128 /* realloc new memory if necessary and clear it */
129 if (Boxes
->BoxN
>= Boxes
->BoxMax
)
131 Boxes
->BoxMax
= STEP_POINT
+ (2 * Boxes
->BoxMax
);
132 box
= (BoxType
*)realloc (box
, Boxes
->BoxMax
* sizeof (BoxType
));
134 memset (box
+ Boxes
->BoxN
, 0,
135 (Boxes
->BoxMax
- Boxes
->BoxN
) * sizeof (BoxType
));
137 return (box
+ Boxes
->BoxN
++);
142 * \brief Get the next slot for a connection.
144 * Allocates memory if necessary.
147 GetConnectionMemory (NetType
*Net
)
149 ConnectionType
*con
= Net
->Connection
;
151 /* realloc new memory if necessary and clear it */
152 if (Net
->ConnectionN
>= Net
->ConnectionMax
)
154 Net
->ConnectionMax
+= STEP_POINT
;
155 con
= (ConnectionType
*)realloc (con
, Net
->ConnectionMax
* sizeof (ConnectionType
));
156 Net
->Connection
= con
;
157 memset (con
+ Net
->ConnectionN
, 0,
158 STEP_POINT
* sizeof (ConnectionType
));
160 return (con
+ Net
->ConnectionN
++);
164 * \brief Get the next slot for a subnet.
166 * Allocates memory if necessary.
169 GetNetMemory (NetListType
*Netlist
)
171 NetType
*net
= Netlist
->Net
;
173 /* realloc new memory if necessary and clear it */
174 if (Netlist
->NetN
>= Netlist
->NetMax
)
176 Netlist
->NetMax
+= STEP_POINT
;
177 net
= (NetType
*)realloc (net
, Netlist
->NetMax
* sizeof (NetType
));
179 memset (net
+ Netlist
->NetN
, 0, STEP_POINT
* sizeof (NetType
));
181 return (net
+ Netlist
->NetN
++);
185 * \brief Get the next slot for a net list.
187 * Allocates memory if necessary.
190 GetNetListMemory (NetListListType
*Netlistlist
)
192 NetListType
*netlist
= Netlistlist
->NetList
;
194 /* realloc new memory if necessary and clear it */
195 if (Netlistlist
->NetListN
>= Netlistlist
->NetListMax
)
197 Netlistlist
->NetListMax
+= STEP_POINT
;
198 netlist
= (NetListType
*)realloc (netlist
,
199 Netlistlist
->NetListMax
* sizeof (NetListType
));
200 Netlistlist
->NetList
= netlist
;
201 memset (netlist
+ Netlistlist
->NetListN
, 0,
202 STEP_POINT
* sizeof (NetListType
));
204 return (netlist
+ Netlistlist
->NetListN
++);
208 * \brief Get the next slot for a pin.
210 * Allocates memory if necessary.
213 GetPinMemory (ElementType
*element
)
217 new_obj
= g_slice_new0 (PinType
);
218 element
->Pin
= g_list_append (element
->Pin
, new_obj
);
225 FreePin (PinType
*data
)
227 g_slice_free (PinType
, data
);
231 * \brief Get the next slot for a pad.
233 * Allocates memory if necessary.
236 GetPadMemory (ElementType
*element
)
240 new_obj
= g_slice_new0 (PadType
);
241 element
->Pad
= g_list_append (element
->Pad
, new_obj
);
248 FreePad (PadType
*data
)
250 g_slice_free (PadType
, data
);
254 * \brief Get the next slot for a via.
256 * Allocates memory if necessary.
259 GetViaMemory (DataType
*data
)
263 new_obj
= g_slice_new0 (PinType
);
264 data
->Via
= g_list_append (data
->Via
, new_obj
);
271 FreeVia (PinType
*data
)
273 g_slice_free (PinType
, data
);
277 * \brief Get the next slot for a Rat.
279 * Allocates memory if necessary.
282 GetRatMemory (DataType
*data
)
286 new_obj
= g_slice_new0 (RatType
);
287 data
->Rat
= g_list_append (data
->Rat
, new_obj
);
294 FreeRat (RatType
*data
)
296 g_slice_free (RatType
, data
);
300 * \brief Get the next slot for a line.
302 * Allocates memory if necessary.
305 GetLineMemory (LayerType
*layer
)
309 new_obj
= g_slice_new0 (LineType
);
310 layer
->Line
= g_list_append (layer
->Line
, new_obj
);
317 FreeLine (LineType
*data
)
319 g_slice_free (LineType
, data
);
323 * \brief Get the next slot for an arc.
325 * Allocates memory if necessary.
328 GetArcMemory (LayerType
*layer
)
332 new_obj
= g_slice_new0 (ArcType
);
333 layer
->Arc
= g_list_append (layer
->Arc
, new_obj
);
340 FreeArc (ArcType
*data
)
342 g_slice_free (ArcType
, data
);
346 * \brief Get the next slot for a text object.
348 * Allocates memory if necessary.
351 GetTextMemory (LayerType
*layer
)
355 new_obj
= g_slice_new0 (TextType
);
356 layer
->Text
= g_list_append (layer
->Text
, new_obj
);
363 FreeText (TextType
*data
)
365 g_slice_free (TextType
, data
);
369 * \brief Get the next slot for a polygon object.
371 * Allocates memory if necessary.
374 GetPolygonMemory (LayerType
*layer
)
376 PolygonType
*new_obj
;
378 new_obj
= g_slice_new0 (PolygonType
);
379 layer
->Polygon
= g_list_append (layer
->Polygon
, new_obj
);
386 FreePolygon (PolygonType
*data
)
388 g_slice_free (PolygonType
, data
);
392 * \brief Get the next slot for a point in a polygon struct.
394 * Allocates memory if necessary.
397 GetPointMemoryInPolygon (PolygonType
*Polygon
)
399 PointType
*points
= Polygon
->Points
;
401 /* realloc new memory if necessary and clear it */
402 if (Polygon
->PointN
>= Polygon
->PointMax
)
404 Polygon
->PointMax
+= STEP_POLYGONPOINT
;
405 points
= (PointType
*)realloc (points
, Polygon
->PointMax
* sizeof (PointType
));
406 Polygon
->Points
= points
;
407 memset (points
+ Polygon
->PointN
, 0,
408 STEP_POLYGONPOINT
* sizeof (PointType
));
410 return (points
+ Polygon
->PointN
++);
414 * \brief Gets the next slot for a point in a polygon struct.
416 * Allocates memory if necessary.
419 GetHoleIndexMemoryInPolygon (PolygonType
*Polygon
)
421 Cardinal
*holeindex
= Polygon
->HoleIndex
;
423 /* realloc new memory if necessary and clear it */
424 if (Polygon
->HoleIndexN
>= Polygon
->HoleIndexMax
)
426 Polygon
->HoleIndexMax
+= STEP_POLYGONHOLEINDEX
;
427 holeindex
= (Cardinal
*)realloc (holeindex
, Polygon
->HoleIndexMax
* sizeof (int));
428 Polygon
->HoleIndex
= holeindex
;
429 memset (holeindex
+ Polygon
->HoleIndexN
, 0,
430 STEP_POLYGONHOLEINDEX
* sizeof (int));
432 return (holeindex
+ Polygon
->HoleIndexN
++);
436 * \brief Get the next slot for an element.
438 * Allocates memory if necessary.
441 GetElementMemory (DataType
*data
)
443 ElementType
*new_obj
;
445 new_obj
= g_slice_new0 (ElementType
);
449 data
->Element
= g_list_append (data
->Element
, new_obj
);
457 FreeElement (ElementType
*data
)
459 g_slice_free (ElementType
, data
);
463 * \brief Get the next slot for a library menu.
465 * Allocates memory if necessary.
468 GetLibraryMenuMemory (LibraryType
*lib
)
470 LibraryMenuType
*menu
= lib
->Menu
;
472 /* realloc new memory if necessary and clear it */
473 if (lib
->MenuN
>= lib
->MenuMax
)
475 lib
->MenuMax
+= STEP_LIBRARYMENU
;
476 menu
= (LibraryMenuType
*)realloc (menu
, lib
->MenuMax
* sizeof (LibraryMenuType
));
478 memset (menu
+ lib
->MenuN
, 0,
479 STEP_LIBRARYMENU
* sizeof (LibraryMenuType
));
481 return (menu
+ lib
->MenuN
++);
485 * \brief Get the next slot for a library entry.
487 * Allocates memory if necessary.
490 GetLibraryEntryMemory (LibraryMenuType
*Menu
)
492 LibraryEntryType
*entry
= Menu
->Entry
;
494 /* realloc new memory if necessary and clear it */
495 if (Menu
->EntryN
>= Menu
->EntryMax
)
497 Menu
->EntryMax
+= STEP_LIBRARYENTRY
;
498 entry
= (LibraryEntryType
*)realloc (entry
, Menu
->EntryMax
* sizeof (LibraryEntryType
));
500 memset (entry
+ Menu
->EntryN
, 0,
501 STEP_LIBRARYENTRY
* sizeof (LibraryEntryType
));
503 return (entry
+ Menu
->EntryN
++);
507 * \brief Get the next slot for a DrillElement.
509 * Allocates memory if necessary.
512 GetDrillElementMemory (DrillType
*Drill
)
514 ElementType
**element
;
516 element
= Drill
->Element
;
518 /* realloc new memory if necessary and clear it */
519 if (Drill
->ElementN
>= Drill
->ElementMax
)
521 Drill
->ElementMax
+= STEP_ELEMENT
;
522 element
= (ElementType
**)realloc (element
,
523 Drill
->ElementMax
* sizeof (ElementType
*));
524 Drill
->Element
= element
;
525 memset (element
+ Drill
->ElementN
, 0,
526 STEP_ELEMENT
* sizeof (ElementType
*));
528 return (element
+ Drill
->ElementN
++);
532 * \brief Get the next slot for a DrillPoint.
534 * Allocates memory if necessary.
537 GetDrillPinMemory (DrillType
*Drill
)
543 /* realloc new memory if necessary and clear it */
544 if (Drill
->PinN
>= Drill
->PinMax
)
546 Drill
->PinMax
+= STEP_POINT
;
547 pin
= (PinType
**)realloc (pin
, Drill
->PinMax
* sizeof (PinType
*));
549 memset (pin
+ Drill
->PinN
, 0, STEP_POINT
* sizeof (PinType
*));
551 return (pin
+ Drill
->PinN
++);
555 * \brief Get the next slot for a Drill.
557 * Allocates memory if necessary.
560 GetDrillInfoDrillMemory (DrillInfoType
*DrillInfo
)
562 DrillType
*drill
= DrillInfo
->Drill
;
564 /* realloc new memory if necessary and clear it */
565 if (DrillInfo
->DrillN
>= DrillInfo
->DrillMax
)
567 DrillInfo
->DrillMax
+= STEP_DRILL
;
568 drill
= (DrillType
*)realloc (drill
, DrillInfo
->DrillMax
* sizeof (DrillType
));
569 DrillInfo
->Drill
= drill
;
570 memset (drill
+ DrillInfo
->DrillN
, 0, STEP_DRILL
* sizeof (DrillType
));
572 return (drill
+ DrillInfo
->DrillN
++);
576 * \brief Free the memory used by a polygon.
579 FreePolygonMemory (PolygonType
*polygon
)
584 free (polygon
->Points
);
585 free (polygon
->HoleIndex
);
587 if (polygon
->Clipped
)
588 poly_Free (&polygon
->Clipped
);
589 poly_FreeContours (&polygon
->NoHoles
);
591 memset (polygon
, 0, sizeof (PolygonType
));
595 * \brief Free the memory used by a box list.
598 FreeBoxListMemory (BoxListType
*Boxlist
)
603 memset (Boxlist
, 0, sizeof (BoxListType
));
608 * \brief Free the memory used by a net.
611 FreeNetListMemory (NetListType
*Netlist
)
621 memset (Netlist
, 0, sizeof (NetListType
));
626 * \brief Free the memory used by a net list.
629 FreeNetListListMemory (NetListListType
*Netlistlist
)
633 NETLIST_LOOP (Netlistlist
);
635 FreeNetListMemory (netlist
);
638 free (Netlistlist
->NetList
);
639 memset (Netlistlist
, 0, sizeof (NetListListType
));
644 * \brief Free the memory used by a subnet.
647 FreeNetMemory (NetType
*Net
)
651 free (Net
->Connection
);
652 memset (Net
, 0, sizeof (NetType
));
656 * \brief Free the memory used by an attribute list.
659 FreeAttributeListMemory (AttributeListType
*list
)
663 for (i
= 0; i
< list
->Number
; i
++)
665 free (list
->List
[i
].name
);
666 free (list
->List
[i
].value
);
674 * \brief Free the memory used by an element.
677 FreeElementMemory (ElementType
*element
)
682 ELEMENTNAME_LOOP (element
);
700 g_list_free_full (element
->Pin
, (GDestroyNotify
)FreePin
);
701 g_list_free_full (element
->Pad
, (GDestroyNotify
)FreePad
);
702 g_list_free_full (element
->Line
, (GDestroyNotify
)FreeLine
);
703 g_list_free_full (element
->Arc
, (GDestroyNotify
)FreeArc
);
705 FreeAttributeListMemory (&element
->Attributes
);
706 memset (element
, 0, sizeof (ElementType
));
710 * \brief Free the memory used by PCB.
713 FreePCBMemory (PCBType
*pcb
)
721 free (pcb
->Filename
);
722 free (pcb
->PrintFilename
);
723 FreeDataMemory (pcb
->Data
);
725 /* release font symbols */
726 for (i
= 0; i
<= MAX_FONTPOSITION
; i
++)
727 free (pcb
->Font
.Symbol
[i
].Line
);
728 FreeLibraryMemory (&pcb
->NetlistLib
);
730 FreeAttributeListMemory (&pcb
->Attributes
);
732 memset (pcb
, 0, sizeof (PCBType
));
736 * \brief Free the memory used by data struct.
739 FreeDataMemory (DataType
*data
)
752 g_list_free_full (data
->Via
, (GDestroyNotify
)FreeVia
);
755 FreeElementMemory (element
);
758 g_list_free_full (data
->Element
, (GDestroyNotify
)FreeElement
);
759 g_list_free_full (data
->Rat
, (GDestroyNotify
)FreeRat
);
761 for (layer
= data
->Layer
, i
= 0; i
< MAX_ALL_LAYER
; layer
++, i
++)
763 FreeAttributeListMemory (&layer
->Attributes
);
766 free (text
->TextString
);
777 g_list_free_full (layer
->Line
, (GDestroyNotify
)FreeLine
);
778 g_list_free_full (layer
->Arc
, (GDestroyNotify
)FreeArc
);
779 g_list_free_full (layer
->Text
, (GDestroyNotify
)FreeText
);
780 POLYGON_LOOP (layer
);
782 FreePolygonMemory (polygon
);
785 g_list_free_full (layer
->Polygon
, (GDestroyNotify
)FreePolygon
);
786 if (layer
->line_tree
)
787 r_destroy_tree (&layer
->line_tree
);
789 r_destroy_tree (&layer
->arc_tree
);
790 if (layer
->text_tree
)
791 r_destroy_tree (&layer
->text_tree
);
792 if (layer
->polygon_tree
)
793 r_destroy_tree (&layer
->polygon_tree
);
796 if (data
->element_tree
)
797 r_destroy_tree (&data
->element_tree
);
798 for (i
= 0; i
< MAX_ELEMENTNAMES
; i
++)
799 if (data
->name_tree
[i
])
800 r_destroy_tree (&data
->name_tree
[i
]);
802 r_destroy_tree (&data
->via_tree
);
804 r_destroy_tree (&data
->pin_tree
);
806 r_destroy_tree (&data
->pad_tree
);
808 r_destroy_tree (&data
->rat_tree
);
810 memset (data
, 0, sizeof (DataType
));
814 * \brief Free the memory that's allocated by the library.
817 FreeLibraryMemory (LibraryType
*lib
)
823 free (entry
->AllocatedMemory
);
824 free (entry
->ListEntry
);
834 memset (lib
, 0, sizeof (LibraryType
));
838 * \brief Reallocates memory for a dynamic length string if necessary.
841 DSRealloc (DynamicStringType
*Ptr
, size_t Length
)
843 int input_null
= (Ptr
->Data
== NULL
);
844 if (input_null
|| Length
>= Ptr
->MaxLength
)
846 Ptr
->MaxLength
= Length
+ 512;
847 Ptr
->Data
= (char *)realloc (Ptr
->Data
, Ptr
->MaxLength
);
854 * \brief Adds one character to a dynamic string.
857 DSAddCharacter (DynamicStringType
*Ptr
, char Char
)
859 size_t position
= Ptr
->Data
? strlen (Ptr
->Data
) : 0;
861 DSRealloc (Ptr
, position
+ 1);
862 Ptr
->Data
[position
++] = Char
;
863 Ptr
->Data
[position
] = '\0';
867 * \brief Add a string to a dynamic string.
870 DSAddString (DynamicStringType
*Ptr
, const char *S
)
872 size_t position
= Ptr
->Data
? strlen (Ptr
->Data
) : 0;
876 DSRealloc (Ptr
, position
+ 1 + strlen (S
));
877 strcat (&Ptr
->Data
[position
], S
);
882 * \brief Clear a dynamic string.
885 DSClearString (DynamicStringType
*Ptr
)
892 * \brief Strips leading and trailing blanks from the passed string.
894 * \return a pointer to the new 'duped' one or NULL if the old one
895 * holds only white space characters.
898 StripWhiteSpaceAndDup (const char *S
)
907 /* strip leading blanks */
908 for (p1
= S
; *p1
&& isspace ((int) *p1
); p1
++);
910 /* strip trailing blanks and get string length */
911 length
= strlen (p1
);
912 for (p2
= p1
+ length
- 1; length
&& isspace ((int) *p2
); p2
--, length
--);
914 /* string is not empty -> allocate memory */
917 copy
= (char *)realloc (NULL
, length
+ 1);
918 strncpy (copy
, p1
, length
);