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
46 #ifdef HAVE_LIBDMALLOC
50 /* ---------------------------------------------------------------------------
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)
59 g_list_free_full (GList
*list
, GDestroyNotify free_func
)
61 g_list_foreach (list
, (GFunc
) free_func
, NULL
);
66 /* ---------------------------------------------------------------------------
67 * get next slot for a rubberband connection, allocates memory if necessary
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
++);
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 *));
99 memset (ptr
+ list
->PtrN
, 0,
100 (list
->PtrMax
- list
->PtrN
) * sizeof (void *));
102 return (ptr
+ list
->PtrN
++);
106 FreePointerListMemory (PointerListType
*list
)
109 memset (list
, 0, sizeof (PointerListType
));
112 /* ---------------------------------------------------------------------------
113 * get next slot for a box, allocates memory if necessary
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
));
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
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
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
));
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
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
196 GetPinMemory (ElementType
*element
)
200 new_obj
= g_slice_new0 (PinType
);
201 element
->Pin
= g_list_append (element
->Pin
, new_obj
);
208 FreePin (PinType
*data
)
210 g_slice_free (PinType
, data
);
213 /* ---------------------------------------------------------------------------
214 * get next slot for a pad, allocates memory if necessary
217 GetPadMemory (ElementType
*element
)
221 new_obj
= g_slice_new0 (PadType
);
222 element
->Pad
= g_list_append (element
->Pad
, new_obj
);
229 FreePad (PadType
*data
)
231 g_slice_free (PadType
, data
);
234 /* ---------------------------------------------------------------------------
235 * get next slot for a via, allocates memory if necessary
238 GetViaMemory (DataType
*data
)
242 new_obj
= g_slice_new0 (PinType
);
243 data
->Via
= g_list_append (data
->Via
, new_obj
);
250 FreeVia (PinType
*data
)
252 g_slice_free (PinType
, data
);
255 /* ---------------------------------------------------------------------------
256 * get next slot for a Rat, allocates memory if necessary
259 GetRatMemory (DataType
*data
)
263 new_obj
= g_slice_new0 (RatType
);
264 data
->Rat
= g_list_append (data
->Rat
, new_obj
);
271 FreeRat (RatType
*data
)
273 g_slice_free (RatType
, data
);
276 /* ---------------------------------------------------------------------------
277 * get next slot for a line, allocates memory if necessary
280 GetLineMemory (LayerType
*layer
)
284 new_obj
= g_slice_new0 (LineType
);
285 layer
->Line
= g_list_append (layer
->Line
, new_obj
);
292 FreeLine (LineType
*data
)
294 g_slice_free (LineType
, data
);
297 /* ---------------------------------------------------------------------------
298 * get next slot for an arc, allocates memory if necessary
301 GetArcMemory (LayerType
*layer
)
305 new_obj
= g_slice_new0 (ArcType
);
306 layer
->Arc
= g_list_append (layer
->Arc
, new_obj
);
313 FreeArc (ArcType
*data
)
315 g_slice_free (ArcType
, data
);
318 /* ---------------------------------------------------------------------------
319 * get next slot for a text object, allocates memory if necessary
322 GetTextMemory (LayerType
*layer
)
326 new_obj
= g_slice_new0 (TextType
);
327 layer
->Text
= g_list_append (layer
->Text
, new_obj
);
334 FreeText (TextType
*data
)
336 g_slice_free (TextType
, data
);
339 /* ---------------------------------------------------------------------------
340 * get next slot for a polygon object, allocates memory if necessary
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
);
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
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
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
406 GetElementMemory (DataType
*data
)
408 ElementType
*new_obj
;
410 new_obj
= g_slice_new0 (ElementType
);
414 data
->Element
= g_list_append (data
->Element
, new_obj
);
422 FreeElement (ElementType
*data
)
424 g_slice_free (ElementType
, data
);
427 /* ---------------------------------------------------------------------------
428 * get next slot for a library menu, allocates memory if necessary
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
));
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
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
));
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
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
494 GetDrillPinMemory (DrillType
*Drill
)
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
*));
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
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
534 FreePolygonMemory (PolygonType
*polygon
)
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
553 FreeBoxListMemory (BoxListType
*Boxlist
)
558 memset (Boxlist
, 0, sizeof (BoxListType
));
562 /* ---------------------------------------------------------------------------
563 * frees memory used by a net
566 FreeNetListMemory (NetListType
*Netlist
)
576 memset (Netlist
, 0, sizeof (NetListType
));
580 /* ---------------------------------------------------------------------------
581 * frees memory used by a net list
584 FreeNetListListMemory (NetListListType
*Netlistlist
)
588 NETLIST_LOOP (Netlistlist
);
590 FreeNetListMemory (netlist
);
593 free (Netlistlist
->NetList
);
594 memset (Netlistlist
, 0, sizeof (NetListListType
));
598 /* ---------------------------------------------------------------------------
599 * frees memory used by a subnet
602 FreeNetMemory (NetType
*Net
)
606 free (Net
->Connection
);
607 memset (Net
, 0, sizeof (NetType
));
610 /* ---------------------------------------------------------------------------
611 * frees memory used by an attribute list
614 FreeAttributeListMemory (AttributeListType
*list
)
618 for (i
= 0; i
< list
->Number
; i
++)
620 free (list
->List
[i
].name
);
621 free (list
->List
[i
].value
);
628 /* ---------------------------------------------------------------------------
629 * frees memory used by an element
632 FreeElementMemory (ElementType
*element
)
637 ELEMENTNAME_LOOP (element
);
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
668 FreePCBMemory (PCBType
*pcb
)
676 free (pcb
->Filename
);
677 free (pcb
->PrintFilename
);
678 FreeDataMemory (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
);
685 FreeAttributeListMemory (&pcb
->Attributes
);
687 memset (pcb
, 0, sizeof (PCBType
));
690 /* ---------------------------------------------------------------------------
691 * free memory used by data struct
694 FreeDataMemory (DataType
*data
)
707 g_list_free_full (data
->Via
, (GDestroyNotify
)FreeVia
);
710 FreeElementMemory (element
);
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
);
721 free (text
->TextString
);
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
);
740 g_list_free_full (layer
->Polygon
, (GDestroyNotify
)FreePolygon
);
741 if (layer
->line_tree
)
742 r_destroy_tree (&layer
->line_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
]);
757 r_destroy_tree (&data
->via_tree
);
759 r_destroy_tree (&data
->pin_tree
);
761 r_destroy_tree (&data
->pad_tree
);
763 r_destroy_tree (&data
->rat_tree
);
765 memset (data
, 0, sizeof (DataType
));
768 /* ---------------------------------------------------------------------------
769 * releases the memory that's allocated by the library
772 FreeLibraryMemory (LibraryType
*lib
)
778 free (entry
->AllocatedMemory
);
779 free (entry
->ListEntry
);
789 memset (lib
, 0, sizeof (LibraryType
));
792 /* ---------------------------------------------------------------------------
793 * reallocates memory for a dynamic length string if necessary
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
);
808 /* ---------------------------------------------------------------------------
809 * adds one character to a dynamic string
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
825 DSAddString (DynamicStringType
*Ptr
, const char *S
)
827 size_t position
= Ptr
->Data
? strlen (Ptr
->Data
) : 0;
831 DSRealloc (Ptr
, position
+ 1 + strlen (S
));
832 strcat (&Ptr
->Data
[position
], S
);
836 /* ----------------------------------------------------------------------
837 * clears a dynamic string
840 DSClearString (DynamicStringType
*Ptr
)
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
852 StripWhiteSpaceAndDup (const char *S
)
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 */
871 copy
= (char *)realloc (NULL
, length
+ 1);
872 strncpy (copy
, p1
, length
);