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
);
411 data
->Element
= g_list_append (data
->Element
, new_obj
);
418 FreeElement (ElementType
*data
)
420 g_slice_free (ElementType
, data
);
423 /* ---------------------------------------------------------------------------
424 * get next slot for a library menu, allocates memory if necessary
427 GetLibraryMenuMemory (LibraryType
*lib
)
429 LibraryMenuType
*menu
= lib
->Menu
;
431 /* realloc new memory if necessary and clear it */
432 if (lib
->MenuN
>= lib
->MenuMax
)
434 lib
->MenuMax
+= STEP_LIBRARYMENU
;
435 menu
= (LibraryMenuType
*)realloc (menu
, lib
->MenuMax
* sizeof (LibraryMenuType
));
437 memset (menu
+ lib
->MenuN
, 0,
438 STEP_LIBRARYMENU
* sizeof (LibraryMenuType
));
440 return (menu
+ lib
->MenuN
++);
443 /* ---------------------------------------------------------------------------
444 * get next slot for a library entry, allocates memory if necessary
447 GetLibraryEntryMemory (LibraryMenuType
*Menu
)
449 LibraryEntryType
*entry
= Menu
->Entry
;
451 /* realloc new memory if necessary and clear it */
452 if (Menu
->EntryN
>= Menu
->EntryMax
)
454 Menu
->EntryMax
+= STEP_LIBRARYENTRY
;
455 entry
= (LibraryEntryType
*)realloc (entry
, Menu
->EntryMax
* sizeof (LibraryEntryType
));
457 memset (entry
+ Menu
->EntryN
, 0,
458 STEP_LIBRARYENTRY
* sizeof (LibraryEntryType
));
460 return (entry
+ Menu
->EntryN
++);
463 /* ---------------------------------------------------------------------------
464 * get next slot for a DrillElement, allocates memory if necessary
467 GetDrillElementMemory (DrillType
*Drill
)
469 ElementType
**element
;
471 element
= Drill
->Element
;
473 /* realloc new memory if necessary and clear it */
474 if (Drill
->ElementN
>= Drill
->ElementMax
)
476 Drill
->ElementMax
+= STEP_ELEMENT
;
477 element
= (ElementType
**)realloc (element
,
478 Drill
->ElementMax
* sizeof (ElementType
*));
479 Drill
->Element
= element
;
480 memset (element
+ Drill
->ElementN
, 0,
481 STEP_ELEMENT
* sizeof (ElementType
*));
483 return (element
+ Drill
->ElementN
++);
486 /* ---------------------------------------------------------------------------
487 * get next slot for a DrillPoint, allocates memory if necessary
490 GetDrillPinMemory (DrillType
*Drill
)
496 /* realloc new memory if necessary and clear it */
497 if (Drill
->PinN
>= Drill
->PinMax
)
499 Drill
->PinMax
+= STEP_POINT
;
500 pin
= (PinType
**)realloc (pin
, Drill
->PinMax
* sizeof (PinType
*));
502 memset (pin
+ Drill
->PinN
, 0, STEP_POINT
* sizeof (PinType
*));
504 return (pin
+ Drill
->PinN
++);
507 /* ---------------------------------------------------------------------------
508 * get next slot for a Drill, allocates memory if necessary
511 GetDrillInfoDrillMemory (DrillInfoType
*DrillInfo
)
513 DrillType
*drill
= DrillInfo
->Drill
;
515 /* realloc new memory if necessary and clear it */
516 if (DrillInfo
->DrillN
>= DrillInfo
->DrillMax
)
518 DrillInfo
->DrillMax
+= STEP_DRILL
;
519 drill
= (DrillType
*)realloc (drill
, DrillInfo
->DrillMax
* sizeof (DrillType
));
520 DrillInfo
->Drill
= drill
;
521 memset (drill
+ DrillInfo
->DrillN
, 0, STEP_DRILL
* sizeof (DrillType
));
523 return (drill
+ DrillInfo
->DrillN
++);
526 /* ---------------------------------------------------------------------------
527 * frees memory used by a polygon
530 FreePolygonMemory (PolygonType
*polygon
)
535 free (polygon
->Points
);
536 free (polygon
->HoleIndex
);
538 if (polygon
->Clipped
)
539 poly_Free (&polygon
->Clipped
);
540 poly_FreeContours (&polygon
->NoHoles
);
542 memset (polygon
, 0, sizeof (PolygonType
));
545 /* ---------------------------------------------------------------------------
546 * frees memory used by a box list
549 FreeBoxListMemory (BoxListType
*Boxlist
)
554 memset (Boxlist
, 0, sizeof (BoxListType
));
558 /* ---------------------------------------------------------------------------
559 * frees memory used by a net
562 FreeNetListMemory (NetListType
*Netlist
)
572 memset (Netlist
, 0, sizeof (NetListType
));
576 /* ---------------------------------------------------------------------------
577 * frees memory used by a net list
580 FreeNetListListMemory (NetListListType
*Netlistlist
)
584 NETLIST_LOOP (Netlistlist
);
586 FreeNetListMemory (netlist
);
589 free (Netlistlist
->NetList
);
590 memset (Netlistlist
, 0, sizeof (NetListListType
));
594 /* ---------------------------------------------------------------------------
595 * frees memory used by a subnet
598 FreeNetMemory (NetType
*Net
)
602 free (Net
->Connection
);
603 memset (Net
, 0, sizeof (NetType
));
606 /* ---------------------------------------------------------------------------
607 * frees memory used by an attribute list
610 FreeAttributeListMemory (AttributeListType
*list
)
614 for (i
= 0; i
< list
->Number
; i
++)
616 free (list
->List
[i
].name
);
617 free (list
->List
[i
].value
);
624 /* ---------------------------------------------------------------------------
625 * frees memory used by an element
628 FreeElementMemory (ElementType
*element
)
633 ELEMENTNAME_LOOP (element
);
651 g_list_free_full (element
->Pin
, (GDestroyNotify
)FreePin
);
652 g_list_free_full (element
->Pad
, (GDestroyNotify
)FreePad
);
653 g_list_free_full (element
->Line
, (GDestroyNotify
)FreeLine
);
654 g_list_free_full (element
->Arc
, (GDestroyNotify
)FreeArc
);
656 FreeAttributeListMemory (&element
->Attributes
);
657 memset (element
, 0, sizeof (ElementType
));
660 /* ---------------------------------------------------------------------------
661 * free memory used by PCB
664 FreePCBMemory (PCBType
*pcb
)
672 free (pcb
->Filename
);
673 free (pcb
->PrintFilename
);
674 FreeDataMemory (pcb
->Data
);
676 /* release font symbols */
677 for (i
= 0; i
<= MAX_FONTPOSITION
; i
++)
678 free (pcb
->Font
.Symbol
[i
].Line
);
679 FreeLibraryMemory (&pcb
->NetlistLib
);
681 FreeAttributeListMemory (&pcb
->Attributes
);
683 memset (pcb
, 0, sizeof (PCBType
));
686 /* ---------------------------------------------------------------------------
687 * free memory used by data struct
690 FreeDataMemory (DataType
*data
)
703 g_list_free_full (data
->Via
, (GDestroyNotify
)FreeVia
);
706 FreeElementMemory (element
);
709 g_list_free_full (data
->Element
, (GDestroyNotify
)FreeElement
);
710 g_list_free_full (data
->Rat
, (GDestroyNotify
)FreeRat
);
712 for (layer
= data
->Layer
, i
= 0; i
< MAX_LAYER
+ 2; layer
++, i
++)
714 FreeAttributeListMemory (&layer
->Attributes
);
717 free (text
->TextString
);
728 g_list_free_full (layer
->Line
, (GDestroyNotify
)FreeLine
);
729 g_list_free_full (layer
->Arc
, (GDestroyNotify
)FreeArc
);
730 g_list_free_full (layer
->Text
, (GDestroyNotify
)FreeText
);
731 POLYGON_LOOP (layer
);
733 FreePolygonMemory (polygon
);
736 g_list_free_full (layer
->Polygon
, (GDestroyNotify
)FreePolygon
);
737 if (layer
->line_tree
)
738 r_destroy_tree (&layer
->line_tree
);
740 r_destroy_tree (&layer
->arc_tree
);
741 if (layer
->text_tree
)
742 r_destroy_tree (&layer
->text_tree
);
743 if (layer
->polygon_tree
)
744 r_destroy_tree (&layer
->polygon_tree
);
747 if (data
->element_tree
)
748 r_destroy_tree (&data
->element_tree
);
749 for (i
= 0; i
< MAX_ELEMENTNAMES
; i
++)
750 if (data
->name_tree
[i
])
751 r_destroy_tree (&data
->name_tree
[i
]);
753 r_destroy_tree (&data
->via_tree
);
755 r_destroy_tree (&data
->pin_tree
);
757 r_destroy_tree (&data
->pad_tree
);
759 r_destroy_tree (&data
->rat_tree
);
761 memset (data
, 0, sizeof (DataType
));
764 /* ---------------------------------------------------------------------------
765 * releases the memory that's allocated by the library
768 FreeLibraryMemory (LibraryType
*lib
)
774 free (entry
->AllocatedMemory
);
775 free (entry
->ListEntry
);
785 memset (lib
, 0, sizeof (LibraryType
));
788 /* ---------------------------------------------------------------------------
789 * reallocates memory for a dynamic length string if necessary
792 DSRealloc (DynamicStringType
*Ptr
, size_t Length
)
794 int input_null
= (Ptr
->Data
== NULL
);
795 if (input_null
|| Length
>= Ptr
->MaxLength
)
797 Ptr
->MaxLength
= Length
+ 512;
798 Ptr
->Data
= (char *)realloc (Ptr
->Data
, Ptr
->MaxLength
);
804 /* ---------------------------------------------------------------------------
805 * adds one character to a dynamic string
808 DSAddCharacter (DynamicStringType
*Ptr
, char Char
)
810 size_t position
= Ptr
->Data
? strlen (Ptr
->Data
) : 0;
812 DSRealloc (Ptr
, position
+ 1);
813 Ptr
->Data
[position
++] = Char
;
814 Ptr
->Data
[position
] = '\0';
817 /* ---------------------------------------------------------------------------
818 * add a string to a dynamic string
821 DSAddString (DynamicStringType
*Ptr
, const char *S
)
823 size_t position
= Ptr
->Data
? strlen (Ptr
->Data
) : 0;
827 DSRealloc (Ptr
, position
+ 1 + strlen (S
));
828 strcat (&Ptr
->Data
[position
], S
);
832 /* ----------------------------------------------------------------------
833 * clears a dynamic string
836 DSClearString (DynamicStringType
*Ptr
)
842 /* ---------------------------------------------------------------------------
843 * strips leading and trailing blanks from the passed string and
844 * returns a pointer to the new 'duped' one or NULL if the old one
845 * holds only white space characters
848 StripWhiteSpaceAndDup (const char *S
)
857 /* strip leading blanks */
858 for (p1
= S
; *p1
&& isspace ((int) *p1
); p1
++);
860 /* strip trailing blanks and get string length */
861 length
= strlen (p1
);
862 for (p2
= p1
+ length
- 1; length
&& isspace ((int) *p2
); p2
--, length
--);
864 /* string is not empty -> allocate memory */
867 copy
= (char *)realloc (NULL
, length
+ 1);
868 strncpy (copy
, p1
, length
);