1 /*!
2 * \file src/mymem.c
3 *
4 * \brief Memory management functions.
5 *
6 * <hr>
7 *
8 * <h1><b>Copyright.</b></h1>\n
9 *
10 * PCB, interactive printed circuit board design
11 *
12 * Copyright (C) 1994,1995,1996 Thomas Nau
13 *
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.
18 *
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.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 *
28 * Contact addresses for paper mail and Email:
29 *
30 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
31 *
32 * Thomas.Nau@rz.uni-ulm.de
33 */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include "global.h"
40
41 #include <memory.h>
42
43 #include "data.h"
44 #include "error.h"
45 #include "mymem.h"
46 #include "misc.h"
47 #include "rats.h"
48 #include "rtree.h"
49
50 #ifdef HAVE_LIBDMALLOC
51 #include <dmalloc.h>
52 #endif
53
54 /* ---------------------------------------------------------------------------
55 * local prototypes
56 */
57 static void DSRealloc (DynamicStringType *, size_t);
58
59
60 /* This API is quite new, provide a version here */
61 #if !GLIB_CHECK_VERSION (2, 28, 0)
62 static void
g_list_free_full(GList * list,GDestroyNotify free_func)63 g_list_free_full (GList *list, GDestroyNotify free_func)
64 {
65 g_list_foreach (list, (GFunc) free_func, NULL);
66 g_list_free (list);
67 }
68 #endif
69
70 /*!
71 * \brief Get the next slot for a rubberband connection.
72 *
73 * Allocates memory if necessary.
74 */
75 RubberbandType *
GetRubberbandMemory(void)76 GetRubberbandMemory (void)
77 {
78 RubberbandType *ptr = Crosshair.AttachedObject.Rubberband;
79
80 /* realloc new memory if necessary and clear it */
81 if (Crosshair.AttachedObject.RubberbandN >=
82 Crosshair.AttachedObject.RubberbandMax)
83 {
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));
90 }
91 return (ptr + Crosshair.AttachedObject.RubberbandN++);
92 }
93
94 void **
GetPointerMemory(PointerListType * list)95 GetPointerMemory (PointerListType *list)
96 {
97 void **ptr = list->Ptr;
98
99 /* realloc new memory if necessary and clear it */
100 if (list->PtrN >= list->PtrMax)
101 {
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 *));
107 }
108 return (ptr + list->PtrN++);
109 }
110
111 void
FreePointerListMemory(PointerListType * list)112 FreePointerListMemory (PointerListType *list)
113 {
114 free (list->Ptr);
115 memset (list, 0, sizeof (PointerListType));
116 }
117
118 /*!
119 * \brief Get the next slot for a box.
120 *
121 * Allocates memory if necessary.
122 */
123 BoxType *
GetBoxMemory(BoxListType * Boxes)124 GetBoxMemory (BoxListType *Boxes)
125 {
126 BoxType *box = Boxes->Box;
127
128 /* realloc new memory if necessary and clear it */
129 if (Boxes->BoxN >= Boxes->BoxMax)
130 {
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));
136 }
137 return (box + Boxes->BoxN++);
138 }
139
140
141 /*!
142 * \brief Get the next slot for a connection.
143 *
144 * Allocates memory if necessary.
145 */
146 ConnectionType *
GetConnectionMemory(NetType * Net)147 GetConnectionMemory (NetType *Net)
148 {
149 ConnectionType *con = Net->Connection;
150
151 /* realloc new memory if necessary and clear it */
152 if (Net->ConnectionN >= Net->ConnectionMax)
153 {
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));
159 }
160 return (con + Net->ConnectionN++);
161 }
162
163 /*!
164 * \brief Get the next slot for a subnet.
165 *
166 * Allocates memory if necessary.
167 */
168 NetType *
GetNetMemory(NetListType * Netlist)169 GetNetMemory (NetListType *Netlist)
170 {
171 NetType *net = Netlist->Net;
172
173 /* realloc new memory if necessary and clear it */
174 if (Netlist->NetN >= Netlist->NetMax)
175 {
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));
180 }
181 return (net + Netlist->NetN++);
182 }
183
184 /*!
185 * \brief Get the next slot for a net list.
186 *
187 * Allocates memory if necessary.
188 */
189 NetListType *
GetNetListMemory(NetListListType * Netlistlist)190 GetNetListMemory (NetListListType *Netlistlist)
191 {
192 NetListType *netlist = Netlistlist->NetList;
193
194 /* realloc new memory if necessary and clear it */
195 if (Netlistlist->NetListN >= Netlistlist->NetListMax)
196 {
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));
203 }
204 return (netlist + Netlistlist->NetListN++);
205 }
206
207 /*!
208 * \brief Get the next slot for a pin.
209 *
210 * Allocates memory if necessary.
211 */
212 PinType *
GetPinMemory(ElementType * element)213 GetPinMemory (ElementType *element)
214 {
215 PinType *new_obj;
216
217 new_obj = g_slice_new0 (PinType);
218 element->Pin = g_list_append (element->Pin, new_obj);
219 element->PinN ++;
220
221 return new_obj;
222 }
223
224 static void
FreePin(PinType * data)225 FreePin (PinType *data)
226 {
227 g_slice_free (PinType, data);
228 }
229
230 /*!
231 * \brief Get the next slot for a pad.
232 *
233 * Allocates memory if necessary.
234 */
235 PadType *
GetPadMemory(ElementType * element)236 GetPadMemory (ElementType *element)
237 {
238 PadType *new_obj;
239
240 new_obj = g_slice_new0 (PadType);
241 element->Pad = g_list_append (element->Pad, new_obj);
242 element->PadN ++;
243
244 return new_obj;
245 }
246
247 static void
FreePad(PadType * data)248 FreePad (PadType *data)
249 {
250 g_slice_free (PadType, data);
251 }
252
253 /*!
254 * \brief Get the next slot for a via.
255 *
256 * Allocates memory if necessary.
257 */
258 PinType *
GetViaMemory(DataType * data)259 GetViaMemory (DataType *data)
260 {
261 PinType *new_obj;
262
263 new_obj = g_slice_new0 (PinType);
264 data->Via = g_list_append (data->Via, new_obj);
265 data->ViaN ++;
266
267 return new_obj;
268 }
269
270 static void
FreeVia(PinType * data)271 FreeVia (PinType *data)
272 {
273 g_slice_free (PinType, data);
274 }
275
276 /*!
277 * \brief Get the next slot for a Rat.
278 *
279 * Allocates memory if necessary.
280 */
281 RatType *
GetRatMemory(DataType * data)282 GetRatMemory (DataType *data)
283 {
284 RatType *new_obj;
285
286 new_obj = g_slice_new0 (RatType);
287 data->Rat = g_list_append (data->Rat, new_obj);
288 data->RatN ++;
289
290 return new_obj;
291 }
292
293 static void
FreeRat(RatType * data)294 FreeRat (RatType *data)
295 {
296 g_slice_free (RatType, data);
297 }
298
299 /*!
300 * \brief Get the next slot for a line.
301 *
302 * Allocates memory if necessary.
303 */
304 LineType *
GetLineMemory(LayerType * layer)305 GetLineMemory (LayerType *layer)
306 {
307 LineType *new_obj;
308
309 new_obj = g_slice_new0 (LineType);
310 layer->Line = g_list_append (layer->Line, new_obj);
311 layer->LineN ++;
312
313 return new_obj;
314 }
315
316 static void
FreeLine(LineType * data)317 FreeLine (LineType *data)
318 {
319 g_slice_free (LineType, data);
320 }
321
322 /*!
323 * \brief Get the next slot for an arc.
324 *
325 * Allocates memory if necessary.
326 */
327 ArcType *
GetArcMemory(LayerType * layer)328 GetArcMemory (LayerType *layer)
329 {
330 ArcType *new_obj;
331
332 new_obj = g_slice_new0 (ArcType);
333 layer->Arc = g_list_append (layer->Arc, new_obj);
334 layer->ArcN ++;
335
336 return new_obj;
337 }
338
339 static void
FreeArc(ArcType * data)340 FreeArc (ArcType *data)
341 {
342 g_slice_free (ArcType, data);
343 }
344
345 /*!
346 * \brief Get the next slot for a text object.
347 *
348 * Allocates memory if necessary.
349 */
350 TextType *
GetTextMemory(LayerType * layer)351 GetTextMemory (LayerType *layer)
352 {
353 TextType *new_obj;
354
355 new_obj = g_slice_new0 (TextType);
356 layer->Text = g_list_append (layer->Text, new_obj);
357 layer->TextN ++;
358
359 return new_obj;
360 }
361
362 static void
FreeText(TextType * data)363 FreeText (TextType *data)
364 {
365 g_slice_free (TextType, data);
366 }
367
368 /*!
369 * \brief Get the next slot for a polygon object.
370 *
371 * Allocates memory if necessary.
372 */
373 PolygonType *
GetPolygonMemory(LayerType * layer)374 GetPolygonMemory (LayerType *layer)
375 {
376 PolygonType *new_obj;
377
378 new_obj = g_slice_new0 (PolygonType);
379 layer->Polygon = g_list_append (layer->Polygon, new_obj);
380 layer->PolygonN ++;
381
382 return new_obj;
383 }
384
385 static void
FreePolygon(PolygonType * data)386 FreePolygon (PolygonType *data)
387 {
388 g_slice_free (PolygonType, data);
389 }
390
391 /*!
392 * \brief Get the next slot for a point in a polygon struct.
393 *
394 * Allocates memory if necessary.
395 */
396 PointType *
GetPointMemoryInPolygon(PolygonType * Polygon)397 GetPointMemoryInPolygon (PolygonType *Polygon)
398 {
399 PointType *points = Polygon->Points;
400
401 /* realloc new memory if necessary and clear it */
402 if (Polygon->PointN >= Polygon->PointMax)
403 {
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));
409 }
410 return (points + Polygon->PointN++);
411 }
412
413 /*!
414 * \brief Gets the next slot for a point in a polygon struct.
415 *
416 * Allocates memory if necessary.
417 */
418 Cardinal *
GetHoleIndexMemoryInPolygon(PolygonType * Polygon)419 GetHoleIndexMemoryInPolygon (PolygonType *Polygon)
420 {
421 Cardinal *holeindex = Polygon->HoleIndex;
422
423 /* realloc new memory if necessary and clear it */
424 if (Polygon->HoleIndexN >= Polygon->HoleIndexMax)
425 {
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));
431 }
432 return (holeindex + Polygon->HoleIndexN++);
433 }
434
435 /*!
436 * \brief Get the next slot for an element.
437 *
438 * Allocates memory if necessary.
439 */
440 ElementType *
GetElementMemory(DataType * data)441 GetElementMemory (DataType *data)
442 {
443 ElementType *new_obj;
444
445 new_obj = g_slice_new0 (ElementType);
446
447 if (data != NULL)
448 {
449 data->Element = g_list_append (data->Element, new_obj);
450 data->ElementN ++;
451 }
452
453 return new_obj;
454 }
455
456 static void
FreeElement(ElementType * data)457 FreeElement (ElementType *data)
458 {
459 g_slice_free (ElementType, data);
460 }
461
462 /*!
463 * \brief Get the next slot for a library menu.
464 *
465 * Allocates memory if necessary.
466 */
467 LibraryMenuType *
GetLibraryMenuMemory(LibraryType * lib)468 GetLibraryMenuMemory (LibraryType *lib)
469 {
470 LibraryMenuType *menu = lib->Menu;
471
472 /* realloc new memory if necessary and clear it */
473 if (lib->MenuN >= lib->MenuMax)
474 {
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));
480 }
481 return (menu + lib->MenuN++);
482 }
483
484 /*!
485 * \brief Get the next slot for a library entry.
486 *
487 * Allocates memory if necessary.
488 */
489 LibraryEntryType *
GetLibraryEntryMemory(LibraryMenuType * Menu)490 GetLibraryEntryMemory (LibraryMenuType *Menu)
491 {
492 LibraryEntryType *entry = Menu->Entry;
493
494 /* realloc new memory if necessary and clear it */
495 if (Menu->EntryN >= Menu->EntryMax)
496 {
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));
502 }
503 return (entry + Menu->EntryN++);
504 }
505
506 /*!
507 * \brief Get the next slot for a DrillElement.
508 *
509 * Allocates memory if necessary.
510 */
511 ElementType **
GetDrillElementMemory(DrillType * Drill)512 GetDrillElementMemory (DrillType *Drill)
513 {
514 ElementType **element;
515
516 element = Drill->Element;
517
518 /* realloc new memory if necessary and clear it */
519 if (Drill->ElementN >= Drill->ElementMax)
520 {
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 *));
527 }
528 return (element + Drill->ElementN++);
529 }
530
531 /*!
532 * \brief Get the next slot for a DrillPoint.
533 *
534 * Allocates memory if necessary.
535 */
536 PinType **
GetDrillPinMemory(DrillType * Drill)537 GetDrillPinMemory (DrillType *Drill)
538 {
539 PinType **pin;
540
541 pin = Drill->Pin;
542
543 /* realloc new memory if necessary and clear it */
544 if (Drill->PinN >= Drill->PinMax)
545 {
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 *));
550 }
551 return (pin + Drill->PinN++);
552 }
553
554 /*!
555 * \brief Get the next slot for a Drill.
556 *
557 * Allocates memory if necessary.
558 */
559 DrillType *
GetDrillInfoDrillMemory(DrillInfoType * DrillInfo)560 GetDrillInfoDrillMemory (DrillInfoType *DrillInfo)
561 {
562 DrillType *drill = DrillInfo->Drill;
563
564 /* realloc new memory if necessary and clear it */
565 if (DrillInfo->DrillN >= DrillInfo->DrillMax)
566 {
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));
571 }
572 return (drill + DrillInfo->DrillN++);
573 }
574
575 /*!
576 * \brief Free the memory used by a polygon.
577 */
578 void
FreePolygonMemory(PolygonType * polygon)579 FreePolygonMemory (PolygonType *polygon)
580 {
581 if (polygon == NULL)
582 return;
583
584 free (polygon->Points);
585 free (polygon->HoleIndex);
586
587 if (polygon->Clipped)
588 poly_Free (&polygon->Clipped);
589 poly_FreeContours (&polygon->NoHoles);
590
591 memset (polygon, 0, sizeof (PolygonType));
592 }
593
594 /*!
595 * \brief Free the memory used by a box list.
596 */
597 void
FreeBoxListMemory(BoxListType * Boxlist)598 FreeBoxListMemory (BoxListType *Boxlist)
599 {
600 if (Boxlist)
601 {
602 free (Boxlist->Box);
603 memset (Boxlist, 0, sizeof (BoxListType));
604 }
605 }
606
607 /*!
608 * \brief Free the memory used by a net.
609 */
610 void
FreeNetListMemory(NetListType * Netlist)611 FreeNetListMemory (NetListType *Netlist)
612 {
613 if (Netlist)
614 {
615 NET_LOOP (Netlist);
616 {
617 FreeNetMemory (net);
618 }
619 END_LOOP;
620 free (Netlist->Net);
621 memset (Netlist, 0, sizeof (NetListType));
622 }
623 }
624
625 /*!
626 * \brief Free the memory used by a net list.
627 */
628 void
FreeNetListListMemory(NetListListType * Netlistlist)629 FreeNetListListMemory (NetListListType *Netlistlist)
630 {
631 if (Netlistlist)
632 {
633 NETLIST_LOOP (Netlistlist);
634 {
635 FreeNetListMemory (netlist);
636 }
637 END_LOOP;
638 free (Netlistlist->NetList);
639 memset (Netlistlist, 0, sizeof (NetListListType));
640 }
641 }
642
643 /*!
644 * \brief Free the memory used by a subnet.
645 */
646 void
FreeNetMemory(NetType * Net)647 FreeNetMemory (NetType *Net)
648 {
649 if (Net)
650 {
651 free (Net->Connection);
652 memset (Net, 0, sizeof (NetType));
653 }
654 }
655 /*!
656 * \brief Free the memory used by an attribute list.
657 */
658 static void
FreeAttributeListMemory(AttributeListType * list)659 FreeAttributeListMemory (AttributeListType *list)
660 {
661 int i;
662
663 for (i = 0; i < list->Number; i++)
664 {
665 free (list->List[i].name);
666 free (list->List[i].value);
667 }
668 free (list->List);
669 list->List = NULL;
670 list->Max = 0;
671 }
672
673 /*!
674 * \brief Free the memory used by an element.
675 */
676 void
FreeElementMemory(ElementType * element)677 FreeElementMemory (ElementType *element)
678 {
679 if (element == NULL)
680 return;
681
682 ELEMENTNAME_LOOP (element);
683 {
684 free (textstring);
685 }
686 END_LOOP;
687 PIN_LOOP (element);
688 {
689 free (pin->Name);
690 free (pin->Number);
691 }
692 END_LOOP;
693 PAD_LOOP (element);
694 {
695 free (pad->Name);
696 free (pad->Number);
697 }
698 END_LOOP;
699
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);
704
705 FreeAttributeListMemory (&element->Attributes);
706 memset (element, 0, sizeof (ElementType));
707 }
708
709 /*!
710 * \brief Free the memory used by PCB.
711 */
712 void
FreePCBMemory(PCBType * pcb)713 FreePCBMemory (PCBType *pcb)
714 {
715 int i;
716
717 if (pcb == NULL)
718 return;
719
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));
733 }
734
735 /*!
736 * \brief Free the memory used by data struct.
737 */
738 void
FreeDataMemory(DataType * data)739 FreeDataMemory (DataType *data)
740 {
741 LayerType *layer;
742 int i;
743
744 if (data == NULL)
745 return;
746
747 VIA_LOOP (data);
748 {
749 free (via->Name);
750 }
751 END_LOOP;
752 g_list_free_full (data->Via, (GDestroyNotify)FreeVia);
753 ELEMENT_LOOP (data);
754 {
755 FreeElementMemory (element);
756 }
757 END_LOOP;
758 g_list_free_full (data->Element, (GDestroyNotify)FreeElement);
759 g_list_free_full (data->Rat, (GDestroyNotify)FreeRat);
760
761 for (layer = data->Layer, i = 0; i < MAX_ALL_LAYER; layer++, i++)
762 {
763 FreeAttributeListMemory (&layer->Attributes);
764 TEXT_LOOP (layer);
765 {
766 free (text->TextString);
767 }
768 END_LOOP;
769 if (layer->Name)
770 free (layer->Name);
771 LINE_LOOP (layer);
772 {
773 if (line->Number)
774 free (line->Number);
775 }
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);
781 {
782 FreePolygonMemory (polygon);
783 }
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);
794 }
795
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));
811 }
812
813 /*!
814 * \brief Free the memory that's allocated by the library.
815 */
816 void
FreeLibraryMemory(LibraryType * lib)817 FreeLibraryMemory (LibraryType *lib)
818 {
819 MENU_LOOP (lib);
820 {
821 ENTRY_LOOP (menu);
822 {
823 free (entry->AllocatedMemory);
824 free (entry->ListEntry);
825 }
826 END_LOOP;
827 free (menu->Entry);
828 free (menu->Name);
829 }
830 END_LOOP;
831 free (lib->Menu);
832
833 /* clear struct */
834 memset (lib, 0, sizeof (LibraryType));
835 }
836
837 /*!
838 * \brief Reallocates memory for a dynamic length string if necessary.
839 */
840 static void
DSRealloc(DynamicStringType * Ptr,size_t Length)841 DSRealloc (DynamicStringType *Ptr, size_t Length)
842 {
843 int input_null = (Ptr->Data == NULL);
844 if (input_null || Length >= Ptr->MaxLength)
845 {
846 Ptr->MaxLength = Length + 512;
847 Ptr->Data = (char *)realloc (Ptr->Data, Ptr->MaxLength);
848 if (input_null)
849 Ptr->Data[0] = '\0';
850 }
851 }
852
853 /*!
854 * \brief Adds one character to a dynamic string.
855 */
856 void
DSAddCharacter(DynamicStringType * Ptr,char Char)857 DSAddCharacter (DynamicStringType *Ptr, char Char)
858 {
859 size_t position = Ptr->Data ? strlen (Ptr->Data) : 0;
860
861 DSRealloc (Ptr, position + 1);
862 Ptr->Data[position++] = Char;
863 Ptr->Data[position] = '\0';
864 }
865
866 /*!
867 * \brief Add a string to a dynamic string.
868 */
869 void
DSAddString(DynamicStringType * Ptr,const char * S)870 DSAddString (DynamicStringType *Ptr, const char *S)
871 {
872 size_t position = Ptr->Data ? strlen (Ptr->Data) : 0;
873
874 if (S && *S)
875 {
876 DSRealloc (Ptr, position + 1 + strlen (S));
877 strcat (&Ptr->Data[position], S);
878 }
879 }
880
881 /*!
882 * \brief Clear a dynamic string.
883 */
884 void
DSClearString(DynamicStringType * Ptr)885 DSClearString (DynamicStringType *Ptr)
886 {
887 if (Ptr->Data)
888 Ptr->Data[0] = '\0';
889 }
890
891 /*!
892 * \brief Strips leading and trailing blanks from the passed string.
893 *
894 * \return a pointer to the new 'duped' one or NULL if the old one
895 * holds only white space characters.
896 */
897 char *
StripWhiteSpaceAndDup(const char * S)898 StripWhiteSpaceAndDup (const char *S)
899 {
900 const char *p1, *p2;
901 char *copy;
902 size_t length;
903
904 if (!S || !*S)
905 return (NULL);
906
907 /* strip leading blanks */
908 for (p1 = S; *p1 && isspace ((int) *p1); p1++);
909
910 /* strip trailing blanks and get string length */
911 length = strlen (p1);
912 for (p2 = p1 + length - 1; length && isspace ((int) *p2); p2--, length--);
913
914 /* string is not empty -> allocate memory */
915 if (length)
916 {
917 copy = (char *)realloc (NULL, length + 1);
918 strncpy (copy, p1, length);
919 copy[length] = '\0';
920 return (copy);
921 }
922 else
923 return (NULL);
924 }
925