Remove calls to SaveFindFlag()
[geda-pcb/pcjc2.git] / src / mymem.c
blob3de31f685ee0170647098ac8e187ba151e2daebb
1 /*
2 * COPYRIGHT
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
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
35 #include "global.h"
37 #include <memory.h>
39 #include "data.h"
40 #include "error.h"
41 #include "mymem.h"
42 #include "misc.h"
43 #include "rats.h"
44 #include "rtree.h"
46 #ifdef HAVE_LIBDMALLOC
47 #include <dmalloc.h>
48 #endif
50 /* ---------------------------------------------------------------------------
51 * local prototypes
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)
58 static void
59 g_list_free_full (GList *list, GDestroyNotify free_func)
61 g_list_foreach (list, (GFunc) free_func, NULL);
62 g_list_free (list);
64 #endif
66 /* ---------------------------------------------------------------------------
67 * get next slot for a rubberband connection, allocates memory if necessary
69 RubberbandType *
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++);
88 void **
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 *));
98 list->Ptr = ptr;
99 memset (ptr + list->PtrN, 0,
100 (list->PtrMax - list->PtrN) * sizeof (void *));
102 return (ptr + list->PtrN++);
105 void
106 FreePointerListMemory (PointerListType *list)
108 free (list->Ptr);
109 memset (list, 0, sizeof (PointerListType));
112 /* ---------------------------------------------------------------------------
113 * get next slot for a box, allocates memory if necessary
115 BoxType *
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));
125 Boxes->Box = box;
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
136 ConnectionType *
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
156 NetType *
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));
166 Netlist->Net = net;
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
175 NetListType *
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
195 PinType *
196 GetPinMemory (ElementType *element)
198 PinType *new_obj;
200 new_obj = g_slice_new0 (PinType);
201 element->Pin = g_list_append (element->Pin, new_obj);
202 element->PinN ++;
204 return new_obj;
207 static void
208 FreePin (PinType *data)
210 g_slice_free (PinType, data);
213 /* ---------------------------------------------------------------------------
214 * get next slot for a pad, allocates memory if necessary
216 PadType *
217 GetPadMemory (ElementType *element)
219 PadType *new_obj;
221 new_obj = g_slice_new0 (PadType);
222 element->Pad = g_list_append (element->Pad, new_obj);
223 element->PadN ++;
225 return new_obj;
228 static void
229 FreePad (PadType *data)
231 g_slice_free (PadType, data);
234 /* ---------------------------------------------------------------------------
235 * get next slot for a via, allocates memory if necessary
237 PinType *
238 GetViaMemory (DataType *data)
240 PinType *new_obj;
242 new_obj = g_slice_new0 (PinType);
243 data->Via = g_list_append (data->Via, new_obj);
244 data->ViaN ++;
246 return new_obj;
249 static void
250 FreeVia (PinType *data)
252 g_slice_free (PinType, data);
255 /* ---------------------------------------------------------------------------
256 * get next slot for a Rat, allocates memory if necessary
258 RatType *
259 GetRatMemory (DataType *data)
261 RatType *new_obj;
263 new_obj = g_slice_new0 (RatType);
264 data->Rat = g_list_append (data->Rat, new_obj);
265 data->RatN ++;
267 return new_obj;
270 static void
271 FreeRat (RatType *data)
273 g_slice_free (RatType, data);
276 /* ---------------------------------------------------------------------------
277 * get next slot for a line, allocates memory if necessary
279 LineType *
280 GetLineMemory (LayerType *layer)
282 LineType *new_obj;
284 new_obj = g_slice_new0 (LineType);
285 layer->Line = g_list_append (layer->Line, new_obj);
286 layer->LineN ++;
288 return new_obj;
291 static void
292 FreeLine (LineType *data)
294 g_slice_free (LineType, data);
297 /* ---------------------------------------------------------------------------
298 * get next slot for an arc, allocates memory if necessary
300 ArcType *
301 GetArcMemory (LayerType *layer)
303 ArcType *new_obj;
305 new_obj = g_slice_new0 (ArcType);
306 layer->Arc = g_list_append (layer->Arc, new_obj);
307 layer->ArcN ++;
309 return new_obj;
312 static void
313 FreeArc (ArcType *data)
315 g_slice_free (ArcType, data);
318 /* ---------------------------------------------------------------------------
319 * get next slot for a text object, allocates memory if necessary
321 TextType *
322 GetTextMemory (LayerType *layer)
324 TextType *new_obj;
326 new_obj = g_slice_new0 (TextType);
327 layer->Text = g_list_append (layer->Text, new_obj);
328 layer->TextN ++;
330 return new_obj;
333 static void
334 FreeText (TextType *data)
336 g_slice_free (TextType, data);
339 /* ---------------------------------------------------------------------------
340 * get next slot for a polygon object, allocates memory if necessary
342 PolygonType *
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);
349 layer->PolygonN ++;
351 return new_obj;
354 static void
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
362 * if necessary
364 PointType *
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
383 * if necessary
385 Cardinal *
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
405 ElementType *
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);
412 data->ElementN ++;
414 return new_obj;
417 static void
418 FreeElement (ElementType *data)
420 g_slice_free (ElementType, data);
423 /* ---------------------------------------------------------------------------
424 * get next slot for a library menu, allocates memory if necessary
426 LibraryMenuType *
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));
436 lib->Menu = menu;
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
446 LibraryEntryType *
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));
456 Menu->Entry = entry;
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
466 ElementType **
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
489 PinType **
490 GetDrillPinMemory (DrillType *Drill)
492 PinType **pin;
494 pin = Drill->Pin;
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 *));
501 Drill->Pin = pin;
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
510 DrillType *
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
529 void
530 FreePolygonMemory (PolygonType *polygon)
532 if (polygon == NULL)
533 return;
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
548 void
549 FreeBoxListMemory (BoxListType *Boxlist)
551 if (Boxlist)
553 free (Boxlist->Box);
554 memset (Boxlist, 0, sizeof (BoxListType));
558 /* ---------------------------------------------------------------------------
559 * frees memory used by a net
561 void
562 FreeNetListMemory (NetListType *Netlist)
564 if (Netlist)
566 NET_LOOP (Netlist);
568 FreeNetMemory (net);
570 END_LOOP;
571 free (Netlist->Net);
572 memset (Netlist, 0, sizeof (NetListType));
576 /* ---------------------------------------------------------------------------
577 * frees memory used by a net list
579 void
580 FreeNetListListMemory (NetListListType *Netlistlist)
582 if (Netlistlist)
584 NETLIST_LOOP (Netlistlist);
586 FreeNetListMemory (netlist);
588 END_LOOP;
589 free (Netlistlist->NetList);
590 memset (Netlistlist, 0, sizeof (NetListListType));
594 /* ---------------------------------------------------------------------------
595 * frees memory used by a subnet
597 void
598 FreeNetMemory (NetType *Net)
600 if (Net)
602 free (Net->Connection);
603 memset (Net, 0, sizeof (NetType));
606 /* ---------------------------------------------------------------------------
607 * frees memory used by an attribute list
609 static void
610 FreeAttributeListMemory (AttributeListType *list)
612 int i;
614 for (i = 0; i < list->Number; i++)
616 free (list->List[i].name);
617 free (list->List[i].value);
619 free (list->List);
620 list->List = NULL;
621 list->Max = 0;
624 /* ---------------------------------------------------------------------------
625 * frees memory used by an element
627 void
628 FreeElementMemory (ElementType *element)
630 if (element == NULL)
631 return;
633 ELEMENTNAME_LOOP (element);
635 free (textstring);
637 END_LOOP;
638 PIN_LOOP (element);
640 free (pin->Name);
641 free (pin->Number);
643 END_LOOP;
644 PAD_LOOP (element);
646 free (pad->Name);
647 free (pad->Number);
649 END_LOOP;
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
663 void
664 FreePCBMemory (PCBType *pcb)
666 int i;
668 if (pcb == NULL)
669 return;
671 free (pcb->Name);
672 free (pcb->Filename);
673 free (pcb->PrintFilename);
674 FreeDataMemory (pcb->Data);
675 free (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);
680 NetlistChanged (0);
681 FreeAttributeListMemory (&pcb->Attributes);
682 /* clear struct */
683 memset (pcb, 0, sizeof (PCBType));
686 /* ---------------------------------------------------------------------------
687 * free memory used by data struct
689 void
690 FreeDataMemory (DataType *data)
692 LayerType *layer;
693 int i;
695 if (data == NULL)
696 return;
698 VIA_LOOP (data);
700 free (via->Name);
702 END_LOOP;
703 g_list_free_full (data->Via, (GDestroyNotify)FreeVia);
704 ELEMENT_LOOP (data);
706 FreeElementMemory (element);
708 END_LOOP;
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);
715 TEXT_LOOP (layer);
717 free (text->TextString);
719 END_LOOP;
720 if (layer->Name)
721 free (layer->Name);
722 LINE_LOOP (layer);
724 if (line->Number)
725 free (line->Number);
727 END_LOOP;
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);
735 END_LOOP;
736 g_list_free_full (layer->Polygon, (GDestroyNotify)FreePolygon);
737 if (layer->line_tree)
738 r_destroy_tree (&layer->line_tree);
739 if (layer->arc_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]);
752 if (data->via_tree)
753 r_destroy_tree (&data->via_tree);
754 if (data->pin_tree)
755 r_destroy_tree (&data->pin_tree);
756 if (data->pad_tree)
757 r_destroy_tree (&data->pad_tree);
758 if (data->rat_tree)
759 r_destroy_tree (&data->rat_tree);
760 /* clear struct */
761 memset (data, 0, sizeof (DataType));
764 /* ---------------------------------------------------------------------------
765 * releases the memory that's allocated by the library
767 void
768 FreeLibraryMemory (LibraryType *lib)
770 MENU_LOOP (lib);
772 ENTRY_LOOP (menu);
774 free (entry->AllocatedMemory);
775 free (entry->ListEntry);
777 END_LOOP;
778 free (menu->Entry);
779 free (menu->Name);
781 END_LOOP;
782 free (lib->Menu);
784 /* clear struct */
785 memset (lib, 0, sizeof (LibraryType));
788 /* ---------------------------------------------------------------------------
789 * reallocates memory for a dynamic length string if necessary
791 static void
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);
799 if (input_null)
800 Ptr->Data[0] = '\0';
804 /* ---------------------------------------------------------------------------
805 * adds one character to a dynamic string
807 void
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
820 void
821 DSAddString (DynamicStringType *Ptr, const char *S)
823 size_t position = Ptr->Data ? strlen (Ptr->Data) : 0;
825 if (S && *S)
827 DSRealloc (Ptr, position + 1 + strlen (S));
828 strcat (&Ptr->Data[position], S);
832 /* ----------------------------------------------------------------------
833 * clears a dynamic string
835 void
836 DSClearString (DynamicStringType *Ptr)
838 if (Ptr->Data)
839 Ptr->Data[0] = '\0';
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
847 char *
848 StripWhiteSpaceAndDup (const char *S)
850 const char *p1, *p2;
851 char *copy;
852 size_t length;
854 if (!S || !*S)
855 return (NULL);
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 */
865 if (length)
867 copy = (char *)realloc (NULL, length + 1);
868 strncpy (copy, p1, length);
869 copy[length] = '\0';
870 return (copy);
872 else
873 return (NULL);