6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
30 /* memory management functions
48 #ifdef HAVE_LIBDMALLOC
54 /* ---------------------------------------------------------------------------
57 static void DSRealloc (DynamicStringTypePtr
, 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
);
70 /* ---------------------------------------------------------------------------
71 * get next slot for a rubberband connection, allocates memory if necessary
74 GetRubberbandMemory (void)
76 RubberbandTypePtr ptr
= Crosshair
.AttachedObject
.Rubberband
;
78 /* realloc new memory if necessary and clear it */
79 if (Crosshair
.AttachedObject
.RubberbandN
>=
80 Crosshair
.AttachedObject
.RubberbandMax
)
82 Crosshair
.AttachedObject
.RubberbandMax
+= STEP_RUBBERBAND
;
83 ptr
= (RubberbandTypePtr
)realloc (ptr
, Crosshair
.AttachedObject
.RubberbandMax
*
84 sizeof (RubberbandType
));
85 Crosshair
.AttachedObject
.Rubberband
= ptr
;
86 memset (ptr
+ Crosshair
.AttachedObject
.RubberbandN
, 0,
87 STEP_RUBBERBAND
* sizeof (RubberbandType
));
89 return (ptr
+ Crosshair
.AttachedObject
.RubberbandN
++);
93 GetPointerMemory (PointerListTypePtr list
)
95 void **ptr
= list
->Ptr
;
97 /* realloc new memory if necessary and clear it */
98 if (list
->PtrN
>= list
->PtrMax
)
100 list
->PtrMax
= STEP_POINT
+ (2 * list
->PtrMax
);
101 ptr
= (void **)realloc (ptr
, list
->PtrMax
* sizeof (void *));
103 memset (ptr
+ list
->PtrN
, 0,
104 (list
->PtrMax
- list
->PtrN
) * sizeof (void *));
106 return (ptr
+ list
->PtrN
++);
110 FreePointerListMemory (PointerListTypePtr list
)
113 memset (list
, 0, sizeof (PointerListType
));
116 /* ---------------------------------------------------------------------------
117 * get next slot for a box, allocates memory if necessary
120 GetBoxMemory (BoxListTypePtr Boxes
)
122 BoxTypePtr box
= Boxes
->Box
;
124 /* realloc new memory if necessary and clear it */
125 if (Boxes
->BoxN
>= Boxes
->BoxMax
)
127 Boxes
->BoxMax
= STEP_POINT
+ (2 * Boxes
->BoxMax
);
128 box
= (BoxTypePtr
)realloc (box
, Boxes
->BoxMax
* sizeof (BoxType
));
130 memset (box
+ Boxes
->BoxN
, 0,
131 (Boxes
->BoxMax
- Boxes
->BoxN
) * sizeof (BoxType
));
133 return (box
+ Boxes
->BoxN
++);
137 /* ---------------------------------------------------------------------------
138 * get next slot for a connection, allocates memory if necessary
141 GetConnectionMemory (NetTypePtr Net
)
143 ConnectionTypePtr con
= Net
->Connection
;
145 /* realloc new memory if necessary and clear it */
146 if (Net
->ConnectionN
>= Net
->ConnectionMax
)
148 Net
->ConnectionMax
+= STEP_POINT
;
149 con
= (ConnectionTypePtr
)realloc (con
, Net
->ConnectionMax
* sizeof (ConnectionType
));
150 Net
->Connection
= con
;
151 memset (con
+ Net
->ConnectionN
, 0,
152 STEP_POINT
* sizeof (ConnectionType
));
154 return (con
+ Net
->ConnectionN
++);
157 /* ---------------------------------------------------------------------------
158 * get next slot for a subnet, allocates memory if necessary
161 GetNetMemory (NetListTypePtr Netlist
)
163 NetTypePtr net
= Netlist
->Net
;
165 /* realloc new memory if necessary and clear it */
166 if (Netlist
->NetN
>= Netlist
->NetMax
)
168 Netlist
->NetMax
+= STEP_POINT
;
169 net
= (NetTypePtr
)realloc (net
, Netlist
->NetMax
* sizeof (NetType
));
171 memset (net
+ Netlist
->NetN
, 0, STEP_POINT
* sizeof (NetType
));
173 return (net
+ Netlist
->NetN
++);
176 /* ---------------------------------------------------------------------------
177 * get next slot for a net list, allocates memory if necessary
180 GetNetListMemory (NetListListTypePtr Netlistlist
)
182 NetListTypePtr netlist
= Netlistlist
->NetList
;
184 /* realloc new memory if necessary and clear it */
185 if (Netlistlist
->NetListN
>= Netlistlist
->NetListMax
)
187 Netlistlist
->NetListMax
+= STEP_POINT
;
188 netlist
= (NetListTypePtr
)realloc (netlist
,
189 Netlistlist
->NetListMax
* sizeof (NetListType
));
190 Netlistlist
->NetList
= netlist
;
191 memset (netlist
+ Netlistlist
->NetListN
, 0,
192 STEP_POINT
* sizeof (NetListType
));
194 return (netlist
+ Netlistlist
->NetListN
++);
196 /* ---------------------------------------------------------------------------
197 * get next slot for a pin, allocates memory if necessary
200 GetPinMemory (ElementType
*element
)
204 new_obj
= g_slice_new0 (PinType
);
205 element
->Pin
= g_list_append (element
->Pin
, new_obj
);
212 FreePin (PinType
*data
)
214 g_slice_free (PinType
, data
);
217 /* ---------------------------------------------------------------------------
218 * get next slot for a pad, allocates memory if necessary
221 GetPadMemory (ElementType
*element
)
225 new_obj
= g_slice_new0 (PadType
);
226 element
->Pad
= g_list_append (element
->Pad
, new_obj
);
233 FreePad (PadType
*data
)
235 g_slice_free (PadType
, data
);
238 /* ---------------------------------------------------------------------------
239 * get next slot for a via, allocates memory if necessary
242 GetViaMemory (DataType
*data
)
246 new_obj
= g_slice_new0 (PinType
);
247 data
->Via
= g_list_append (data
->Via
, new_obj
);
254 FreeVia (PinType
*data
)
256 g_slice_free (PinType
, data
);
259 /* ---------------------------------------------------------------------------
260 * get next slot for a Rat, allocates memory if necessary
263 GetRatMemory (DataType
*data
)
267 new_obj
= g_slice_new0 (RatType
);
268 data
->Rat
= g_list_append (data
->Rat
, new_obj
);
275 FreeRat (RatType
*data
)
277 g_slice_free (RatType
, data
);
280 /* ---------------------------------------------------------------------------
281 * get next slot for a line, allocates memory if necessary
284 GetLineMemory (LayerType
*layer
)
288 new_obj
= g_slice_new0 (LineType
);
289 layer
->Line
= g_list_append (layer
->Line
, new_obj
);
296 FreeLine (LineType
*data
)
298 g_slice_free (LineType
, data
);
301 /* ---------------------------------------------------------------------------
302 * get next slot for an arc, allocates memory if necessary
305 GetArcMemory (LayerType
*layer
)
309 new_obj
= g_slice_new0 (ArcType
);
310 layer
->Arc
= g_list_append (layer
->Arc
, new_obj
);
317 FreeArc (ArcType
*data
)
319 g_slice_free (ArcType
, data
);
322 /* ---------------------------------------------------------------------------
323 * get next slot for a text object, allocates memory if necessary
326 GetTextMemory (LayerType
*layer
)
330 new_obj
= g_slice_new0 (TextType
);
331 layer
->Text
= g_list_append (layer
->Text
, new_obj
);
338 FreeText (TextType
*data
)
340 g_slice_free (TextType
, data
);
343 /* ---------------------------------------------------------------------------
344 * get next slot for a polygon object, allocates memory if necessary
347 GetPolygonMemory (LayerType
*layer
)
349 PolygonType
*new_obj
;
351 new_obj
= g_slice_new0 (PolygonType
);
352 layer
->Polygon
= g_list_append (layer
->Polygon
, new_obj
);
359 FreePolygon (PolygonType
*data
)
361 g_slice_free (PolygonType
, data
);
364 /* ---------------------------------------------------------------------------
365 * gets the next slot for a point in a polygon struct, allocates memory
369 GetPointMemoryInPolygon (PolygonTypePtr Polygon
)
371 PointTypePtr points
= Polygon
->Points
;
373 /* realloc new memory if necessary and clear it */
374 if (Polygon
->PointN
>= Polygon
->PointMax
)
376 Polygon
->PointMax
+= STEP_POLYGONPOINT
;
377 points
= (PointTypePtr
)realloc (points
, Polygon
->PointMax
* sizeof (PointType
));
378 Polygon
->Points
= points
;
379 memset (points
+ Polygon
->PointN
, 0,
380 STEP_POLYGONPOINT
* sizeof (PointType
));
382 return (points
+ Polygon
->PointN
++);
385 /* ---------------------------------------------------------------------------
386 * gets the next slot for a point in a polygon struct, allocates memory
390 GetHoleIndexMemoryInPolygon (PolygonTypePtr Polygon
)
392 Cardinal
*holeindex
= Polygon
->HoleIndex
;
394 /* realloc new memory if necessary and clear it */
395 if (Polygon
->HoleIndexN
>= Polygon
->HoleIndexMax
)
397 Polygon
->HoleIndexMax
+= STEP_POLYGONHOLEINDEX
;
398 holeindex
= (Cardinal
*)realloc (holeindex
, Polygon
->HoleIndexMax
* sizeof (int));
399 Polygon
->HoleIndex
= holeindex
;
400 memset (holeindex
+ Polygon
->HoleIndexN
, 0,
401 STEP_POLYGONHOLEINDEX
* sizeof (int));
403 return (holeindex
+ Polygon
->HoleIndexN
++);
406 /* ---------------------------------------------------------------------------
407 * get next slot for an element, allocates memory if necessary
410 GetElementMemory (DataType
*data
)
412 ElementType
*new_obj
;
414 new_obj
= g_slice_new0 (ElementType
);
415 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 (LibraryTypePtr lib
)
433 LibraryMenuTypePtr 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
= (LibraryMenuTypePtr
)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 (LibraryMenuTypePtr Menu
)
453 LibraryEntryTypePtr 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
= (LibraryEntryTypePtr
)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 (DrillTypePtr Drill
)
473 ElementTypePtr
*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
= (ElementTypePtr
*)realloc (element
,
482 Drill
->ElementMax
* sizeof (ElementTypeHandle
));
483 Drill
->Element
= element
;
484 memset (element
+ Drill
->ElementN
, 0,
485 STEP_ELEMENT
* sizeof (ElementTypeHandle
));
487 return (element
+ Drill
->ElementN
++);
490 /* ---------------------------------------------------------------------------
491 * get next slot for a DrillPoint, allocates memory if necessary
494 GetDrillPinMemory (DrillTypePtr Drill
)
500 /* realloc new memory if necessary and clear it */
501 if (Drill
->PinN
>= Drill
->PinMax
)
503 Drill
->PinMax
+= STEP_POINT
;
504 pin
= (PinTypePtr
*)realloc (pin
, Drill
->PinMax
* sizeof (PinTypeHandle
));
506 memset (pin
+ Drill
->PinN
, 0, STEP_POINT
* sizeof (PinTypeHandle
));
508 return (pin
+ Drill
->PinN
++);
511 /* ---------------------------------------------------------------------------
512 * get next slot for a Drill, allocates memory if necessary
515 GetDrillInfoDrillMemory (DrillInfoTypePtr DrillInfo
)
517 DrillTypePtr 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
= (DrillTypePtr
)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 (BoxListTypePtr Boxlist
)
558 memset (Boxlist
, 0, sizeof (BoxListType
));
562 /* ---------------------------------------------------------------------------
563 * frees memory used by a net
566 FreeNetListMemory (NetListTypePtr Netlist
)
576 memset (Netlist
, 0, sizeof (NetListType
));
580 /* ---------------------------------------------------------------------------
581 * frees memory used by a net list
584 FreeNetListListMemory (NetListListTypePtr 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 (NetTypePtr Net
)
606 free (Net
->Connection
);
607 memset (Net
, 0, sizeof (NetType
));
610 /* ---------------------------------------------------------------------------
611 * frees memory used by an attribute list
614 FreeAttributeListMemory (AttributeListTypePtr 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
);
684 FreeAttributeListMemory (&pcb
->Attributes
);
686 memset (pcb
, 0, sizeof (PCBType
));
689 /* ---------------------------------------------------------------------------
690 * free memory used by data struct
693 FreeDataMemory (DataType
*data
)
706 g_list_free_full (data
->Via
, (GDestroyNotify
)FreeVia
);
709 FreeElementMemory (element
);
712 g_list_free_full (data
->Element
, (GDestroyNotify
)FreeElement
);
713 g_list_free_full (data
->Rat
, (GDestroyNotify
)FreeRat
);
715 for (layer
= data
->Layer
, i
= 0; i
< MAX_LAYER
+ 2; layer
++, i
++)
717 FreeAttributeListMemory (&layer
->Attributes
);
720 free (text
->TextString
);
731 g_list_free_full (layer
->Line
, (GDestroyNotify
)FreeLine
);
732 g_list_free_full (layer
->Arc
, (GDestroyNotify
)FreeArc
);
733 g_list_free_full (layer
->Text
, (GDestroyNotify
)FreeText
);
734 POLYGON_LOOP (layer
);
736 FreePolygonMemory (polygon
);
739 g_list_free_full (layer
->Polygon
, (GDestroyNotify
)FreePolygon
);
740 if (layer
->line_tree
)
741 r_destroy_tree (&layer
->line_tree
);
743 r_destroy_tree (&layer
->arc_tree
);
744 if (layer
->text_tree
)
745 r_destroy_tree (&layer
->text_tree
);
746 if (layer
->polygon_tree
)
747 r_destroy_tree (&layer
->polygon_tree
);
750 if (data
->element_tree
)
751 r_destroy_tree (&data
->element_tree
);
752 for (i
= 0; i
< MAX_ELEMENTNAMES
; i
++)
753 if (data
->name_tree
[i
])
754 r_destroy_tree (&data
->name_tree
[i
]);
756 r_destroy_tree (&data
->via_tree
);
758 r_destroy_tree (&data
->pin_tree
);
760 r_destroy_tree (&data
->pad_tree
);
762 r_destroy_tree (&data
->rat_tree
);
764 memset (data
, 0, sizeof (DataType
));
767 /* ---------------------------------------------------------------------------
768 * releases the memory that's allocated by the library
771 FreeLibraryMemory (LibraryTypePtr lib
)
777 free (entry
->AllocatedMemory
);
778 free (entry
->ListEntry
);
788 memset (lib
, 0, sizeof (LibraryType
));
791 /* ---------------------------------------------------------------------------
792 * reallocates memory for a dynamic length string if necessary
795 DSRealloc (DynamicStringTypePtr Ptr
, size_t Length
)
797 int input_null
= (Ptr
->Data
== NULL
);
798 if (input_null
|| Length
>= Ptr
->MaxLength
)
800 Ptr
->MaxLength
= Length
+ 512;
801 Ptr
->Data
= (char *)realloc (Ptr
->Data
, Ptr
->MaxLength
);
807 /* ---------------------------------------------------------------------------
808 * adds one character to a dynamic string
811 DSAddCharacter (DynamicStringTypePtr Ptr
, char Char
)
813 size_t position
= Ptr
->Data
? strlen (Ptr
->Data
) : 0;
815 DSRealloc (Ptr
, position
+ 1);
816 Ptr
->Data
[position
++] = Char
;
817 Ptr
->Data
[position
] = '\0';
820 /* ---------------------------------------------------------------------------
821 * add a string to a dynamic string
824 DSAddString (DynamicStringTypePtr Ptr
, const char *S
)
826 size_t position
= Ptr
->Data
? strlen (Ptr
->Data
) : 0;
830 DSRealloc (Ptr
, position
+ 1 + strlen (S
));
831 strcat (&Ptr
->Data
[position
], S
);
835 /* ----------------------------------------------------------------------
836 * clears a dynamic string
839 DSClearString (DynamicStringTypePtr Ptr
)
845 /* ---------------------------------------------------------------------------
846 * strips leading and trailing blanks from the passed string and
847 * returns a pointer to the new 'duped' one or NULL if the old one
848 * holds only white space characters
851 StripWhiteSpaceAndDup (const char *S
)
860 /* strip leading blanks */
861 for (p1
= S
; *p1
&& isspace ((int) *p1
); p1
++);
863 /* strip trailing blanks and get string length */
864 length
= strlen (p1
);
865 for (p2
= p1
+ length
- 1; length
&& isspace ((int) *p2
); p2
--, length
--);
867 /* string is not empty -> allocate memory */
870 copy
= (char *)realloc (NULL
, length
+ 1);
871 strncpy (copy
, p1
, length
);