Repopulate route style selector on PCBChanged action
[geda-pcb/whiteaudio.git] / src / mymem.c
blob73b3ef72f35873bd39a582bbb316632dedd443c6
1 /* $Id$ */
3 /*
4 * COPYRIGHT
6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
30 /* memory management functions
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
37 #include "global.h"
39 #include <memory.h>
41 #include "data.h"
42 #include "error.h"
43 #include "mymem.h"
44 #include "misc.h"
45 #include "rats.h"
46 #include "rtree.h"
48 #ifdef HAVE_LIBDMALLOC
49 #include <dmalloc.h>
50 #endif
52 RCSID ("$Id$");
54 /* ---------------------------------------------------------------------------
55 * local prototypes
57 static void DSRealloc (DynamicStringTypePtr, 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 * get next slot for a rubberband connection, allocates memory if necessary
73 RubberbandTypePtr
74 GetRubberbandMemory (void)
76 RubberbandTypePtr ptr = Crosshair.AttachedObject.Rubberband;
78 /* realloc new memory if necessary and clear it */
79 if (Crosshair.AttachedObject.RubberbandN >=
80 Crosshair.AttachedObject.RubberbandMax)
82 Crosshair.AttachedObject.RubberbandMax += STEP_RUBBERBAND;
83 ptr = (RubberbandTypePtr)realloc (ptr, Crosshair.AttachedObject.RubberbandMax *
84 sizeof (RubberbandType));
85 Crosshair.AttachedObject.Rubberband = ptr;
86 memset (ptr + Crosshair.AttachedObject.RubberbandN, 0,
87 STEP_RUBBERBAND * sizeof (RubberbandType));
89 return (ptr + Crosshair.AttachedObject.RubberbandN++);
92 void **
93 GetPointerMemory (PointerListTypePtr list)
95 void **ptr = list->Ptr;
97 /* realloc new memory if necessary and clear it */
98 if (list->PtrN >= list->PtrMax)
100 list->PtrMax = STEP_POINT + (2 * list->PtrMax);
101 ptr = (void **)realloc (ptr, list->PtrMax * sizeof (void *));
102 list->Ptr = ptr;
103 memset (ptr + list->PtrN, 0,
104 (list->PtrMax - list->PtrN) * sizeof (void *));
106 return (ptr + list->PtrN++);
109 void
110 FreePointerListMemory (PointerListTypePtr list)
112 free (list->Ptr);
113 memset (list, 0, sizeof (PointerListType));
116 /* ---------------------------------------------------------------------------
117 * get next slot for a box, allocates memory if necessary
119 BoxTypePtr
120 GetBoxMemory (BoxListTypePtr Boxes)
122 BoxTypePtr box = Boxes->Box;
124 /* realloc new memory if necessary and clear it */
125 if (Boxes->BoxN >= Boxes->BoxMax)
127 Boxes->BoxMax = STEP_POINT + (2 * Boxes->BoxMax);
128 box = (BoxTypePtr)realloc (box, Boxes->BoxMax * sizeof (BoxType));
129 Boxes->Box = box;
130 memset (box + Boxes->BoxN, 0,
131 (Boxes->BoxMax - Boxes->BoxN) * sizeof (BoxType));
133 return (box + Boxes->BoxN++);
137 /* ---------------------------------------------------------------------------
138 * get next slot for a connection, allocates memory if necessary
140 ConnectionTypePtr
141 GetConnectionMemory (NetTypePtr Net)
143 ConnectionTypePtr con = Net->Connection;
145 /* realloc new memory if necessary and clear it */
146 if (Net->ConnectionN >= Net->ConnectionMax)
148 Net->ConnectionMax += STEP_POINT;
149 con = (ConnectionTypePtr)realloc (con, Net->ConnectionMax * sizeof (ConnectionType));
150 Net->Connection = con;
151 memset (con + Net->ConnectionN, 0,
152 STEP_POINT * sizeof (ConnectionType));
154 return (con + Net->ConnectionN++);
157 /* ---------------------------------------------------------------------------
158 * get next slot for a subnet, allocates memory if necessary
160 NetTypePtr
161 GetNetMemory (NetListTypePtr Netlist)
163 NetTypePtr net = Netlist->Net;
165 /* realloc new memory if necessary and clear it */
166 if (Netlist->NetN >= Netlist->NetMax)
168 Netlist->NetMax += STEP_POINT;
169 net = (NetTypePtr)realloc (net, Netlist->NetMax * sizeof (NetType));
170 Netlist->Net = net;
171 memset (net + Netlist->NetN, 0, STEP_POINT * sizeof (NetType));
173 return (net + Netlist->NetN++);
176 /* ---------------------------------------------------------------------------
177 * get next slot for a net list, allocates memory if necessary
179 NetListTypePtr
180 GetNetListMemory (NetListListTypePtr Netlistlist)
182 NetListTypePtr netlist = Netlistlist->NetList;
184 /* realloc new memory if necessary and clear it */
185 if (Netlistlist->NetListN >= Netlistlist->NetListMax)
187 Netlistlist->NetListMax += STEP_POINT;
188 netlist = (NetListTypePtr)realloc (netlist,
189 Netlistlist->NetListMax * sizeof (NetListType));
190 Netlistlist->NetList = netlist;
191 memset (netlist + Netlistlist->NetListN, 0,
192 STEP_POINT * sizeof (NetListType));
194 return (netlist + Netlistlist->NetListN++);
196 /* ---------------------------------------------------------------------------
197 * get next slot for a pin, allocates memory if necessary
199 PinType *
200 GetPinMemory (ElementType *element)
202 PinType *new_obj;
204 new_obj = g_slice_new0 (PinType);
205 element->Pin = g_list_append (element->Pin, new_obj);
206 element->PinN ++;
208 return new_obj;
211 static void
212 FreePin (PinType *data)
214 g_slice_free (PinType, data);
217 /* ---------------------------------------------------------------------------
218 * get next slot for a pad, allocates memory if necessary
220 PadType *
221 GetPadMemory (ElementType *element)
223 PadType *new_obj;
225 new_obj = g_slice_new0 (PadType);
226 element->Pad = g_list_append (element->Pad, new_obj);
227 element->PadN ++;
229 return new_obj;
232 static void
233 FreePad (PadType *data)
235 g_slice_free (PadType, data);
238 /* ---------------------------------------------------------------------------
239 * get next slot for a via, allocates memory if necessary
241 PinType *
242 GetViaMemory (DataType *data)
244 PinType *new_obj;
246 new_obj = g_slice_new0 (PinType);
247 data->Via = g_list_append (data->Via, new_obj);
248 data->ViaN ++;
250 return new_obj;
253 static void
254 FreeVia (PinType *data)
256 g_slice_free (PinType, data);
259 /* ---------------------------------------------------------------------------
260 * get next slot for a Rat, allocates memory if necessary
262 RatType *
263 GetRatMemory (DataType *data)
265 RatType *new_obj;
267 new_obj = g_slice_new0 (RatType);
268 data->Rat = g_list_append (data->Rat, new_obj);
269 data->RatN ++;
271 return new_obj;
274 static void
275 FreeRat (RatType *data)
277 g_slice_free (RatType, data);
280 /* ---------------------------------------------------------------------------
281 * get next slot for a line, allocates memory if necessary
283 LineType *
284 GetLineMemory (LayerType *layer)
286 LineType *new_obj;
288 new_obj = g_slice_new0 (LineType);
289 layer->Line = g_list_append (layer->Line, new_obj);
290 layer->LineN ++;
292 return new_obj;
295 static void
296 FreeLine (LineType *data)
298 g_slice_free (LineType, data);
301 /* ---------------------------------------------------------------------------
302 * get next slot for an arc, allocates memory if necessary
304 ArcTypePtr
305 GetArcMemory (LayerType *layer)
307 ArcType *new_obj;
309 new_obj = g_slice_new0 (ArcType);
310 layer->Arc = g_list_append (layer->Arc, new_obj);
311 layer->ArcN ++;
313 return new_obj;
316 static void
317 FreeArc (ArcType *data)
319 g_slice_free (ArcType, data);
322 /* ---------------------------------------------------------------------------
323 * get next slot for a text object, allocates memory if necessary
325 TextTypePtr
326 GetTextMemory (LayerType *layer)
328 TextType *new_obj;
330 new_obj = g_slice_new0 (TextType);
331 layer->Text = g_list_append (layer->Text, new_obj);
332 layer->TextN ++;
334 return new_obj;
337 static void
338 FreeText (TextType *data)
340 g_slice_free (TextType, data);
343 /* ---------------------------------------------------------------------------
344 * get next slot for a polygon object, allocates memory if necessary
346 PolygonType *
347 GetPolygonMemory (LayerType *layer)
349 PolygonType *new_obj;
351 new_obj = g_slice_new0 (PolygonType);
352 layer->Polygon = g_list_append (layer->Polygon, new_obj);
353 layer->PolygonN ++;
355 return new_obj;
358 static void
359 FreePolygon (PolygonType *data)
361 g_slice_free (PolygonType, data);
364 /* ---------------------------------------------------------------------------
365 * gets the next slot for a point in a polygon struct, allocates memory
366 * if necessary
368 PointTypePtr
369 GetPointMemoryInPolygon (PolygonTypePtr Polygon)
371 PointTypePtr points = Polygon->Points;
373 /* realloc new memory if necessary and clear it */
374 if (Polygon->PointN >= Polygon->PointMax)
376 Polygon->PointMax += STEP_POLYGONPOINT;
377 points = (PointTypePtr)realloc (points, Polygon->PointMax * sizeof (PointType));
378 Polygon->Points = points;
379 memset (points + Polygon->PointN, 0,
380 STEP_POLYGONPOINT * sizeof (PointType));
382 return (points + Polygon->PointN++);
385 /* ---------------------------------------------------------------------------
386 * gets the next slot for a point in a polygon struct, allocates memory
387 * if necessary
389 Cardinal *
390 GetHoleIndexMemoryInPolygon (PolygonTypePtr Polygon)
392 Cardinal *holeindex = Polygon->HoleIndex;
394 /* realloc new memory if necessary and clear it */
395 if (Polygon->HoleIndexN >= Polygon->HoleIndexMax)
397 Polygon->HoleIndexMax += STEP_POLYGONHOLEINDEX;
398 holeindex = (Cardinal *)realloc (holeindex, Polygon->HoleIndexMax * sizeof (int));
399 Polygon->HoleIndex = holeindex;
400 memset (holeindex + Polygon->HoleIndexN, 0,
401 STEP_POLYGONHOLEINDEX * sizeof (int));
403 return (holeindex + Polygon->HoleIndexN++);
406 /* ---------------------------------------------------------------------------
407 * get next slot for an element, allocates memory if necessary
409 ElementType *
410 GetElementMemory (DataType *data)
412 ElementType *new_obj;
414 new_obj = g_slice_new0 (ElementType);
415 data->Element = g_list_append (data->Element, new_obj);
416 data->ElementN ++;
418 return new_obj;
421 static void
422 FreeElement (ElementType *data)
424 g_slice_free (ElementType, data);
427 /* ---------------------------------------------------------------------------
428 * get next slot for a library menu, allocates memory if necessary
430 LibraryMenuTypePtr
431 GetLibraryMenuMemory (LibraryTypePtr lib)
433 LibraryMenuTypePtr menu = lib->Menu;
435 /* realloc new memory if necessary and clear it */
436 if (lib->MenuN >= lib->MenuMax)
438 lib->MenuMax += STEP_LIBRARYMENU;
439 menu = (LibraryMenuTypePtr)realloc (menu, lib->MenuMax * sizeof (LibraryMenuType));
440 lib->Menu = menu;
441 memset (menu + lib->MenuN, 0,
442 STEP_LIBRARYMENU * sizeof (LibraryMenuType));
444 return (menu + lib->MenuN++);
447 /* ---------------------------------------------------------------------------
448 * get next slot for a library entry, allocates memory if necessary
450 LibraryEntryTypePtr
451 GetLibraryEntryMemory (LibraryMenuTypePtr Menu)
453 LibraryEntryTypePtr entry = Menu->Entry;
455 /* realloc new memory if necessary and clear it */
456 if (Menu->EntryN >= Menu->EntryMax)
458 Menu->EntryMax += STEP_LIBRARYENTRY;
459 entry = (LibraryEntryTypePtr)realloc (entry, Menu->EntryMax * sizeof (LibraryEntryType));
460 Menu->Entry = entry;
461 memset (entry + Menu->EntryN, 0,
462 STEP_LIBRARYENTRY * sizeof (LibraryEntryType));
464 return (entry + Menu->EntryN++);
467 /* ---------------------------------------------------------------------------
468 * get next slot for a DrillElement, allocates memory if necessary
470 ElementTypeHandle
471 GetDrillElementMemory (DrillTypePtr Drill)
473 ElementTypePtr *element;
475 element = Drill->Element;
477 /* realloc new memory if necessary and clear it */
478 if (Drill->ElementN >= Drill->ElementMax)
480 Drill->ElementMax += STEP_ELEMENT;
481 element = (ElementTypePtr *)realloc (element,
482 Drill->ElementMax * sizeof (ElementTypeHandle));
483 Drill->Element = element;
484 memset (element + Drill->ElementN, 0,
485 STEP_ELEMENT * sizeof (ElementTypeHandle));
487 return (element + Drill->ElementN++);
490 /* ---------------------------------------------------------------------------
491 * get next slot for a DrillPoint, allocates memory if necessary
493 PinTypeHandle
494 GetDrillPinMemory (DrillTypePtr Drill)
496 PinTypePtr *pin;
498 pin = Drill->Pin;
500 /* realloc new memory if necessary and clear it */
501 if (Drill->PinN >= Drill->PinMax)
503 Drill->PinMax += STEP_POINT;
504 pin = (PinTypePtr *)realloc (pin, Drill->PinMax * sizeof (PinTypeHandle));
505 Drill->Pin = pin;
506 memset (pin + Drill->PinN, 0, STEP_POINT * sizeof (PinTypeHandle));
508 return (pin + Drill->PinN++);
511 /* ---------------------------------------------------------------------------
512 * get next slot for a Drill, allocates memory if necessary
514 DrillTypePtr
515 GetDrillInfoDrillMemory (DrillInfoTypePtr DrillInfo)
517 DrillTypePtr drill = DrillInfo->Drill;
519 /* realloc new memory if necessary and clear it */
520 if (DrillInfo->DrillN >= DrillInfo->DrillMax)
522 DrillInfo->DrillMax += STEP_DRILL;
523 drill = (DrillTypePtr)realloc (drill, DrillInfo->DrillMax * sizeof (DrillType));
524 DrillInfo->Drill = drill;
525 memset (drill + DrillInfo->DrillN, 0, STEP_DRILL * sizeof (DrillType));
527 return (drill + DrillInfo->DrillN++);
530 /* ---------------------------------------------------------------------------
531 * frees memory used by a polygon
533 void
534 FreePolygonMemory (PolygonType *polygon)
536 if (polygon == NULL)
537 return;
539 free (polygon->Points);
540 free (polygon->HoleIndex);
542 if (polygon->Clipped)
543 poly_Free (&polygon->Clipped);
544 poly_FreeContours (&polygon->NoHoles);
546 memset (polygon, 0, sizeof (PolygonType));
549 /* ---------------------------------------------------------------------------
550 * frees memory used by a box list
552 void
553 FreeBoxListMemory (BoxListTypePtr Boxlist)
555 if (Boxlist)
557 free (Boxlist->Box);
558 memset (Boxlist, 0, sizeof (BoxListType));
562 /* ---------------------------------------------------------------------------
563 * frees memory used by a net
565 void
566 FreeNetListMemory (NetListTypePtr Netlist)
568 if (Netlist)
570 NET_LOOP (Netlist);
572 FreeNetMemory (net);
574 END_LOOP;
575 free (Netlist->Net);
576 memset (Netlist, 0, sizeof (NetListType));
580 /* ---------------------------------------------------------------------------
581 * frees memory used by a net list
583 void
584 FreeNetListListMemory (NetListListTypePtr Netlistlist)
586 if (Netlistlist)
588 NETLIST_LOOP (Netlistlist);
590 FreeNetListMemory (netlist);
592 END_LOOP;
593 free (Netlistlist->NetList);
594 memset (Netlistlist, 0, sizeof (NetListListType));
598 /* ---------------------------------------------------------------------------
599 * frees memory used by a subnet
601 void
602 FreeNetMemory (NetTypePtr Net)
604 if (Net)
606 free (Net->Connection);
607 memset (Net, 0, sizeof (NetType));
610 /* ---------------------------------------------------------------------------
611 * frees memory used by an attribute list
613 static void
614 FreeAttributeListMemory (AttributeListTypePtr list)
616 int i;
618 for (i = 0; i < list->Number; i++)
620 free (list->List[i].name);
621 free (list->List[i].value);
623 free (list->List);
624 list->List = NULL;
625 list->Max = 0;
628 /* ---------------------------------------------------------------------------
629 * frees memory used by an element
631 void
632 FreeElementMemory (ElementType *element)
634 if (element == NULL)
635 return;
637 ELEMENTNAME_LOOP (element);
639 free (textstring);
641 END_LOOP;
642 PIN_LOOP (element);
644 free (pin->Name);
645 free (pin->Number);
647 END_LOOP;
648 PAD_LOOP (element);
650 free (pad->Name);
651 free (pad->Number);
653 END_LOOP;
655 g_list_free_full (element->Pin, (GDestroyNotify)FreePin);
656 g_list_free_full (element->Pad, (GDestroyNotify)FreePad);
657 g_list_free_full (element->Line, (GDestroyNotify)FreeLine);
658 g_list_free_full (element->Arc, (GDestroyNotify)FreeArc);
660 FreeAttributeListMemory (&element->Attributes);
661 memset (element, 0, sizeof (ElementType));
664 /* ---------------------------------------------------------------------------
665 * free memory used by PCB
667 void
668 FreePCBMemory (PCBType *pcb)
670 int i;
672 if (pcb == NULL)
673 return;
675 free (pcb->Name);
676 free (pcb->Filename);
677 free (pcb->PrintFilename);
678 FreeDataMemory (pcb->Data);
679 free (pcb->Data);
680 /* release font symbols */
681 for (i = 0; i <= MAX_FONTPOSITION; i++)
682 free (pcb->Font.Symbol[i].Line);
683 FreeLibraryMemory (&pcb->NetlistLib);
684 FreeAttributeListMemory (&pcb->Attributes);
685 /* clear struct */
686 memset (pcb, 0, sizeof (PCBType));
689 /* ---------------------------------------------------------------------------
690 * free memory used by data struct
692 void
693 FreeDataMemory (DataType *data)
695 LayerTypePtr layer;
696 int i;
698 if (data == NULL)
699 return;
701 VIA_LOOP (data);
703 free (via->Name);
705 END_LOOP;
706 g_list_free_full (data->Via, (GDestroyNotify)FreeVia);
707 ELEMENT_LOOP (data);
709 FreeElementMemory (element);
711 END_LOOP;
712 g_list_free_full (data->Element, (GDestroyNotify)FreeElement);
713 g_list_free_full (data->Rat, (GDestroyNotify)FreeRat);
715 for (layer = data->Layer, i = 0; i < MAX_LAYER + 2; layer++, i++)
717 FreeAttributeListMemory (&layer->Attributes);
718 TEXT_LOOP (layer);
720 free (text->TextString);
722 END_LOOP;
723 if (layer->Name)
724 free (layer->Name);
725 LINE_LOOP (layer);
727 if (line->Number)
728 free (line->Number);
730 END_LOOP;
731 g_list_free_full (layer->Line, (GDestroyNotify)FreeLine);
732 g_list_free_full (layer->Arc, (GDestroyNotify)FreeArc);
733 g_list_free_full (layer->Text, (GDestroyNotify)FreeText);
734 POLYGON_LOOP (layer);
736 FreePolygonMemory (polygon);
738 END_LOOP;
739 g_list_free_full (layer->Polygon, (GDestroyNotify)FreePolygon);
740 if (layer->line_tree)
741 r_destroy_tree (&layer->line_tree);
742 if (layer->arc_tree)
743 r_destroy_tree (&layer->arc_tree);
744 if (layer->text_tree)
745 r_destroy_tree (&layer->text_tree);
746 if (layer->polygon_tree)
747 r_destroy_tree (&layer->polygon_tree);
750 if (data->element_tree)
751 r_destroy_tree (&data->element_tree);
752 for (i = 0; i < MAX_ELEMENTNAMES; i++)
753 if (data->name_tree[i])
754 r_destroy_tree (&data->name_tree[i]);
755 if (data->via_tree)
756 r_destroy_tree (&data->via_tree);
757 if (data->pin_tree)
758 r_destroy_tree (&data->pin_tree);
759 if (data->pad_tree)
760 r_destroy_tree (&data->pad_tree);
761 if (data->rat_tree)
762 r_destroy_tree (&data->rat_tree);
763 /* clear struct */
764 memset (data, 0, sizeof (DataType));
767 /* ---------------------------------------------------------------------------
768 * releases the memory that's allocated by the library
770 void
771 FreeLibraryMemory (LibraryTypePtr lib)
773 MENU_LOOP (lib);
775 ENTRY_LOOP (menu);
777 free (entry->AllocatedMemory);
778 free (entry->ListEntry);
780 END_LOOP;
781 free (menu->Entry);
782 free (menu->Name);
784 END_LOOP;
785 free (lib->Menu);
787 /* clear struct */
788 memset (lib, 0, sizeof (LibraryType));
791 /* ---------------------------------------------------------------------------
792 * reallocates memory for a dynamic length string if necessary
794 static void
795 DSRealloc (DynamicStringTypePtr Ptr, size_t Length)
797 int input_null = (Ptr->Data == NULL);
798 if (input_null || Length >= Ptr->MaxLength)
800 Ptr->MaxLength = Length + 512;
801 Ptr->Data = (char *)realloc (Ptr->Data, Ptr->MaxLength);
802 if (input_null)
803 Ptr->Data[0] = '\0';
807 /* ---------------------------------------------------------------------------
808 * adds one character to a dynamic string
810 void
811 DSAddCharacter (DynamicStringTypePtr Ptr, char Char)
813 size_t position = Ptr->Data ? strlen (Ptr->Data) : 0;
815 DSRealloc (Ptr, position + 1);
816 Ptr->Data[position++] = Char;
817 Ptr->Data[position] = '\0';
820 /* ---------------------------------------------------------------------------
821 * add a string to a dynamic string
823 void
824 DSAddString (DynamicStringTypePtr Ptr, const char *S)
826 size_t position = Ptr->Data ? strlen (Ptr->Data) : 0;
828 if (S && *S)
830 DSRealloc (Ptr, position + 1 + strlen (S));
831 strcat (&Ptr->Data[position], S);
835 /* ----------------------------------------------------------------------
836 * clears a dynamic string
838 void
839 DSClearString (DynamicStringTypePtr Ptr)
841 if (Ptr->Data)
842 Ptr->Data[0] = '\0';
845 /* ---------------------------------------------------------------------------
846 * strips leading and trailing blanks from the passed string and
847 * returns a pointer to the new 'duped' one or NULL if the old one
848 * holds only white space characters
850 char *
851 StripWhiteSpaceAndDup (const char *S)
853 const char *p1, *p2;
854 char *copy;
855 size_t length;
857 if (!S || !*S)
858 return (NULL);
860 /* strip leading blanks */
861 for (p1 = S; *p1 && isspace ((int) *p1); p1++);
863 /* strip trailing blanks and get string length */
864 length = strlen (p1);
865 for (p2 = p1 + length - 1; length && isspace ((int) *p2); p2--, length--);
867 /* string is not empty -> allocate memory */
868 if (length)
870 copy = (char *)realloc (NULL, length + 1);
871 strncpy (copy, p1, length);
872 copy[length] = '\0';
873 return (copy);
875 else
876 return (NULL);