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