Cleanup r_string when leaving make_route_string().
[geda-pcb/pcjc2.git] / src / mymem.c
blob5c9ac3efa464732a322b342a1397e48446926231
1 /*!
2 * \file src/mymem.c
4 * \brief Memory management functions.
6 * <hr>
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
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
39 #include "global.h"
41 #include <memory.h>
43 #include "data.h"
44 #include "error.h"
45 #include "mymem.h"
46 #include "misc.h"
47 #include "rats.h"
48 #include "rtree.h"
50 #ifdef HAVE_LIBDMALLOC
51 #include <dmalloc.h>
52 #endif
54 /* ---------------------------------------------------------------------------
55 * local prototypes
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)
62 static void
63 g_list_free_full (GList *list, GDestroyNotify free_func)
65 g_list_foreach (list, (GFunc) free_func, NULL);
66 g_list_free (list);
68 #endif
70 /*!
71 * \brief Get the next slot for a rubberband connection.
73 * Allocates memory if necessary.
75 RubberbandType *
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++);
94 void **
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 *));
104 list->Ptr = ptr;
105 memset (ptr + list->PtrN, 0,
106 (list->PtrMax - list->PtrN) * sizeof (void *));
108 return (ptr + list->PtrN++);
111 void
112 FreePointerListMemory (PointerListType *list)
114 free (list->Ptr);
115 memset (list, 0, sizeof (PointerListType));
119 * \brief Get the next slot for a box.
121 * Allocates memory if necessary.
123 BoxType *
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));
133 Boxes->Box = box;
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.
146 ConnectionType *
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.
168 NetType *
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));
178 Netlist->Net = net;
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.
189 NetListType *
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.
212 PinType *
213 GetPinMemory (ElementType *element)
215 PinType *new_obj;
217 new_obj = g_slice_new0 (PinType);
218 element->Pin = g_list_append (element->Pin, new_obj);
219 element->PinN ++;
221 return new_obj;
224 static void
225 FreePin (PinType *data)
227 g_slice_free (PinType, data);
231 * \brief Get the next slot for a pad.
233 * Allocates memory if necessary.
235 PadType *
236 GetPadMemory (ElementType *element)
238 PadType *new_obj;
240 new_obj = g_slice_new0 (PadType);
241 element->Pad = g_list_append (element->Pad, new_obj);
242 element->PadN ++;
244 return new_obj;
247 static void
248 FreePad (PadType *data)
250 g_slice_free (PadType, data);
254 * \brief Get the next slot for a via.
256 * Allocates memory if necessary.
258 PinType *
259 GetViaMemory (DataType *data)
261 PinType *new_obj;
263 new_obj = g_slice_new0 (PinType);
264 data->Via = g_list_append (data->Via, new_obj);
265 data->ViaN ++;
267 return new_obj;
270 static void
271 FreeVia (PinType *data)
273 g_slice_free (PinType, data);
277 * \brief Get the next slot for a Rat.
279 * Allocates memory if necessary.
281 RatType *
282 GetRatMemory (DataType *data)
284 RatType *new_obj;
286 new_obj = g_slice_new0 (RatType);
287 data->Rat = g_list_append (data->Rat, new_obj);
288 data->RatN ++;
290 return new_obj;
293 static void
294 FreeRat (RatType *data)
296 g_slice_free (RatType, data);
300 * \brief Get the next slot for a line.
302 * Allocates memory if necessary.
304 LineType *
305 GetLineMemory (LayerType *layer)
307 LineType *new_obj;
309 new_obj = g_slice_new0 (LineType);
310 layer->Line = g_list_append (layer->Line, new_obj);
311 layer->LineN ++;
313 return new_obj;
316 static void
317 FreeLine (LineType *data)
319 g_slice_free (LineType, data);
323 * \brief Get the next slot for an arc.
325 * Allocates memory if necessary.
327 ArcType *
328 GetArcMemory (LayerType *layer)
330 ArcType *new_obj;
332 new_obj = g_slice_new0 (ArcType);
333 layer->Arc = g_list_append (layer->Arc, new_obj);
334 layer->ArcN ++;
336 return new_obj;
339 static void
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.
350 TextType *
351 GetTextMemory (LayerType *layer)
353 TextType *new_obj;
355 new_obj = g_slice_new0 (TextType);
356 layer->Text = g_list_append (layer->Text, new_obj);
357 layer->TextN ++;
359 return new_obj;
362 static void
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.
373 PolygonType *
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);
380 layer->PolygonN ++;
382 return new_obj;
385 static void
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.
396 PointType *
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.
418 Cardinal *
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.
440 ElementType *
441 GetElementMemory (DataType *data)
443 ElementType *new_obj;
445 new_obj = g_slice_new0 (ElementType);
447 if (data != NULL)
449 data->Element = g_list_append (data->Element, new_obj);
450 data->ElementN ++;
453 return new_obj;
456 static void
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.
467 LibraryMenuType *
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));
477 lib->Menu = menu;
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.
489 LibraryEntryType *
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));
499 Menu->Entry = entry;
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.
511 ElementType **
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.
536 PinType **
537 GetDrillPinMemory (DrillType *Drill)
539 PinType **pin;
541 pin = Drill->Pin;
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 *));
548 Drill->Pin = pin;
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.
559 DrillType *
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.
578 void
579 FreePolygonMemory (PolygonType *polygon)
581 if (polygon == NULL)
582 return;
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.
597 void
598 FreeBoxListMemory (BoxListType *Boxlist)
600 if (Boxlist)
602 free (Boxlist->Box);
603 memset (Boxlist, 0, sizeof (BoxListType));
608 * \brief Free the memory used by a net.
610 void
611 FreeNetListMemory (NetListType *Netlist)
613 if (Netlist)
615 NET_LOOP (Netlist);
617 FreeNetMemory (net);
619 END_LOOP;
620 free (Netlist->Net);
621 memset (Netlist, 0, sizeof (NetListType));
626 * \brief Free the memory used by a net list.
628 void
629 FreeNetListListMemory (NetListListType *Netlistlist)
631 if (Netlistlist)
633 NETLIST_LOOP (Netlistlist);
635 FreeNetListMemory (netlist);
637 END_LOOP;
638 free (Netlistlist->NetList);
639 memset (Netlistlist, 0, sizeof (NetListListType));
644 * \brief Free the memory used by a subnet.
646 void
647 FreeNetMemory (NetType *Net)
649 if (Net)
651 free (Net->Connection);
652 memset (Net, 0, sizeof (NetType));
656 * \brief Free the memory used by an attribute list.
658 static void
659 FreeAttributeListMemory (AttributeListType *list)
661 int i;
663 for (i = 0; i < list->Number; i++)
665 free (list->List[i].name);
666 free (list->List[i].value);
668 free (list->List);
669 list->List = NULL;
670 list->Max = 0;
674 * \brief Free the memory used by an element.
676 void
677 FreeElementMemory (ElementType *element)
679 if (element == NULL)
680 return;
682 ELEMENTNAME_LOOP (element);
684 free (textstring);
686 END_LOOP;
687 PIN_LOOP (element);
689 free (pin->Name);
690 free (pin->Number);
692 END_LOOP;
693 PAD_LOOP (element);
695 free (pad->Name);
696 free (pad->Number);
698 END_LOOP;
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.
712 void
713 FreePCBMemory (PCBType *pcb)
715 int i;
717 if (pcb == NULL)
718 return;
720 free (pcb->Name);
721 free (pcb->Filename);
722 free (pcb->PrintFilename);
723 FreeDataMemory (pcb->Data);
724 free (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);
729 NetlistChanged (0);
730 FreeAttributeListMemory (&pcb->Attributes);
731 /* clear struct */
732 memset (pcb, 0, sizeof (PCBType));
736 * \brief Free the memory used by data struct.
738 void
739 FreeDataMemory (DataType *data)
741 LayerType *layer;
742 int i;
744 if (data == NULL)
745 return;
747 VIA_LOOP (data);
749 free (via->Name);
751 END_LOOP;
752 g_list_free_full (data->Via, (GDestroyNotify)FreeVia);
753 ELEMENT_LOOP (data);
755 FreeElementMemory (element);
757 END_LOOP;
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);
764 TEXT_LOOP (layer);
766 free (text->TextString);
768 END_LOOP;
769 if (layer->Name)
770 free (layer->Name);
771 LINE_LOOP (layer);
773 if (line->Number)
774 free (line->Number);
776 END_LOOP;
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);
784 END_LOOP;
785 g_list_free_full (layer->Polygon, (GDestroyNotify)FreePolygon);
786 if (layer->line_tree)
787 r_destroy_tree (&layer->line_tree);
788 if (layer->arc_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]);
801 if (data->via_tree)
802 r_destroy_tree (&data->via_tree);
803 if (data->pin_tree)
804 r_destroy_tree (&data->pin_tree);
805 if (data->pad_tree)
806 r_destroy_tree (&data->pad_tree);
807 if (data->rat_tree)
808 r_destroy_tree (&data->rat_tree);
809 /* clear struct */
810 memset (data, 0, sizeof (DataType));
814 * \brief Free the memory that's allocated by the library.
816 void
817 FreeLibraryMemory (LibraryType *lib)
819 MENU_LOOP (lib);
821 ENTRY_LOOP (menu);
823 free (entry->AllocatedMemory);
824 free (entry->ListEntry);
826 END_LOOP;
827 free (menu->Entry);
828 free (menu->Name);
830 END_LOOP;
831 free (lib->Menu);
833 /* clear struct */
834 memset (lib, 0, sizeof (LibraryType));
838 * \brief Reallocates memory for a dynamic length string if necessary.
840 static void
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);
848 if (input_null)
849 Ptr->Data[0] = '\0';
854 * \brief Adds one character to a dynamic string.
856 void
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.
869 void
870 DSAddString (DynamicStringType *Ptr, const char *S)
872 size_t position = Ptr->Data ? strlen (Ptr->Data) : 0;
874 if (S && *S)
876 DSRealloc (Ptr, position + 1 + strlen (S));
877 strcat (&Ptr->Data[position], S);
882 * \brief Clear a dynamic string.
884 void
885 DSClearString (DynamicStringType *Ptr)
887 if (Ptr->Data)
888 Ptr->Data[0] = '\0';
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.
897 char *
898 StripWhiteSpaceAndDup (const char *S)
900 const char *p1, *p2;
901 char *copy;
902 size_t length;
904 if (!S || !*S)
905 return (NULL);
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 */
915 if (length)
917 copy = (char *)realloc (NULL, length + 1);
918 strncpy (copy, p1, length);
919 copy[length] = '\0';
920 return (copy);
922 else
923 return (NULL);