7ba146796a56340935839a1f0b3e0d3071641f90
[scilab.git] / scilab / modules / spreadsheet / src / c / ripole / pldstr.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5 #include <stddef.h>
6 #include <stdio.h>
7 #include <stdarg.h>
8
9 #include "logger.h"
10 #include "pldstr.h"
11 #include "sci_malloc.h"
12 #include "localization.h"
13
14 #include "os_string.h"
15
16 #ifdef _MSC_VER
17 #define vsnprintf _vsnprintf
18 #endif
19
20 /*-----------------------------------------------------------------\
21  Function Name  : *PLD_strstr
22  Returns Type   : char
23         ----Parameter List
24         1. char *haystack,
25         2.  char *needle,
26         3.  int insensitive,
27         ------------------
28  Exit Codes     :
29  Side Effects   :
30 --------------------------------------------------------------------
31  Comments:
32
33 --------------------------------------------------------------------
34  Changes:
35
36 \------------------------------------------------------------------*/
37 char *PLD_strstr(char *haystack, char *needle, int insensitive)
38 {
39     char *hs;
40     char *ne;
41     char *result;
42
43     /*  LOGGER_log("%s:%d:\nHS=%s\nNE=%s\nIS=%d\n",FL, haystack, needle, insensitive );*/
44
45     if (insensitive > 0)
46     {
47         hs = os_strdup(haystack);
48         PLD_strlower((unsigned char*) hs);
49         ne = os_strdup(needle);
50         PLD_strlower((unsigned char*) ne);
51     }
52     else
53     {
54         hs = haystack;
55         ne = needle;
56     }
57
58     result = strstr(hs, ne);
59     /*  if (result) LOGGER_log("%s:%d:HIT: %s",FL, result);*/
60     /*  else LOGGER_log("%s:%d:MISS (looking for %s|%s)",FL, needle,ne);*/
61
62     if ((result != NULL) && (insensitive > 0))
63     {
64         result = result - hs + haystack;
65         FREE(hs);
66         FREE(ne);
67
68         /*              LOGGER_log("%s:%d:HIT - %s",FL, result );*/
69     }
70
71     return result;
72 }
73
74 /*------------------------------------------------------------------------
75 Procedure:     PLD_strncpy ID:1
76 Purpose:       Copy characters from 'src' to 'dst', writing not more than 'len'
77 characters to the destination, including the terminating \0.
78 Thus, for any effective copying, len must be > 1.
79 Input:         char *dst: Destination string
80 char *src: Source string
81 size_t len: length of string
82 Output:        Returns a pointer to the destination string.
83 Errors:
84 ------------------------------------------------------------------------*/
85 char *PLD_strncpy (char *dst, const char *src, size_t len)
86 {
87
88     /* Thanks go to 'defrost' of #c for providing the replacement*/
89     /*          code which you now see here.  It covers the errors better*/
90     /*          than my own previous code.*/
91
92     /* If we have no buffer space, then it's futile attempting*/
93     /*          to copy anything, just return NULL*/
94     if (len == 0)
95     {
96         return NULL;
97     }
98
99     /* Providing our destination pointer isn't NULL, we can*/
100     /*          commence copying data across*/
101
102     if (dst)
103     {
104         char *dp = dst;
105
106         /* If our source string exists, start moving it to the*/
107         /*              destination string character at a time.*/
108         if (src)
109         {
110             char *sp = (char *)src;
111             while ((--len) && (*sp))
112             {
113                 *dp = *sp;
114                 dp++;
115                 sp++;
116             }
117         }
118
119         *dp = '\0';
120     }
121
122     return dst;
123 }
124
125
126
127 /*------------------------------------------------------------------------
128 Procedure:     PLD_strncat ID:1
129 Purpose:       Buffer size limited string concat function for two strings.
130 Input:         char *dst: Destination string
131 char *src: Source string
132 size_t len: Destination string buffer size - total string size cannot exceed this
133 Output:
134 Errors:        If the length of both strings in total is greater than the available buffer space
135 in *dst, we copy the maximum possible amount of chars from *src such that
136 buffer does not overflow.  A suffixed '\0' will always be appended.
137 ------------------------------------------------------------------------*/
138 char *PLD_strncat( char *dst, const char *src, size_t len )
139 {
140     char *dp = dst;
141     const char *sp = src;
142     size_t cc;
143
144     if (len == 0)
145     {
146         return dst;
147     }
148
149     len--;
150
151     /* Locate the end of the current string.*/
152     cc = 0;
153     while ((*dp) && (cc < len))
154     {
155         dp++;
156         cc++;
157     }
158
159     /* If we have no more buffer space, then return the destination*/
160
161     if (cc >= len)
162     {
163         return dst;
164     }
165
166     /* While we have more source, and there's more char space left in the buffer*/
167
168     while ((*sp) && (cc < len))
169     {
170         cc++;
171         *dp = *sp;
172         dp++;
173         sp++;
174     }
175
176     /* Terminate dst, as a gaurantee of string ending.*/
177
178     *dp = '\0';
179
180     return dst;
181 }
182
183
184 /*------------------------------------------------------------------------
185 Procedure:     PLD_strncate ID:1
186 Purpose:       Catencates a source string to the destination string starting from a given
187 endpoint.  This allows for faster catencation of strings by avoiding the
188 computation required to locate the endpoint of the destination string.
189 Input:         char *dst: Destination string
190 char *src: Source string
191 size_t len: Destination buffer size
192 char *endpoint: Endpoint of destination string, location from where new
193 string will be appended
194 Output:
195 Errors:
196 ------------------------------------------------------------------------*/
197 char *PLD_strncate( char *dst, const char *src, size_t len, char *endpoint )
198 {
199     char *dp = dst;
200     const char *sp = src;
201     size_t cc = 0;
202
203     if (len == 0)
204     {
205         return dst;
206     }
207
208     len--;
209
210     /* If endpoint does not relate correctly, then force manual detection*/
211     /* of the endpoint.*/
212
213     if ((!endpoint) || (endpoint == dst) || ((endpoint - dst + 1) > (int)len))
214     {
215         /* Locate the end of the current string.*/
216         cc = 0;
217         while ((*dp != '\0') && (cc < len))
218         {
219             dp++;
220             cc++;
221         }
222     }
223     else
224     {
225         cc = endpoint - dst + 1;
226         dp = endpoint;
227     }
228
229     /* If we have no more buffer space, then return the destination*/
230
231     if (cc >= len)
232     {
233         return dst;
234     }
235
236     /* While we have more source, and there's more char space left in the buffer*/
237
238     while ((*sp) && (cc < len))
239     {
240         cc++;
241         *dp = *sp;
242         dp++;
243         sp++;
244     }
245
246     /* Terminate dst, as a gaurantee of string ending.*/
247
248     *dp = '\0';
249
250     return dst;
251 }
252
253
254
255
256
257 /*------------------------------------------------------------------------
258 Procedure:     XAM_strncasecmp ID:1
259 Purpose:       Portable version of strncasecmp(), this may be removed in later
260 versions as the strncase* type functions are more widely
261 implemented
262 Input:
263 Output:
264 Errors:
265 ------------------------------------------------------------------------*/
266 int PLD_strncasecmp( char *s1, char *s2, int n )
267 {
268     char *ds1 = s1, *ds2 = s2;
269     char c1, c2;
270     int result = 0;
271
272     while (n > 0)
273     {
274         c1 = (char)tolower(*ds1);
275         c2 = (char)tolower(*ds2);
276
277         if (c1 == c2)
278         {
279             n--;
280             ds1++;
281             ds2++;
282         }
283         else
284         {
285             result = c2 - c1;
286             n = 0;
287         }
288
289     }
290
291     return result;
292
293 }
294
295
296
297
298
299 /*------------------------------------------------------------------------
300 Procedure:     XAM_strtok ID:1
301 Purpose:       A thread safe version of strtok()
302 Input:
303 Output:
304 Errors:
305 ------------------------------------------------------------------------*/
306 char *PLD_strtok( struct PLD_strtok *st, char *line, char *delimeters )
307 {
308     char *stop;
309     char *dc;
310     char *result = NULL;
311
312     if ( line )
313     {
314         st->start = line;
315     }
316
317     /*Strip off any leading delimeters*/
318
319     dc = delimeters;
320     while ((st->start) && (*dc != '\0'))
321     {
322         if (*dc == *(st->start))
323         {
324             st->start++;
325             dc = delimeters;
326         }
327         else
328         {
329             dc++;
330         }
331     }
332
333     /* Where we are left, is the start of our token.*/
334
335     result = st->start;
336
337     if ((st->start) && (st->start != '\0'))
338     {
339         stop = strpbrk( st->start, delimeters ); /* locate our next delimeter */
340
341         /* If we found a delimeter, then that is good.  We must now break the string here*/
342         /* and don't forget to store the character which we stopped on.  Very useful bit*/
343         /* of information for programs which process expressions.*/
344
345         if (stop)
346         {
347
348             /* Store our delimeter.*/
349
350             st->delimeter = *stop;
351
352             /* Terminate our token.*/
353
354             *stop = '\0';
355
356
357             /* Because we're emulating strtok() behaviour here, we have to*/
358             /* absorb all the concurrent delimeters, that is, unless we*/
359             /* reach the end of the string, we cannot return a string with*/
360             /* no chars.*/
361
362             stop++;
363             dc = delimeters;
364             while (*dc != '\0')
365             {
366                 if (*dc == *stop)
367                 {
368                     stop++;
369                     dc = delimeters;
370                 }
371                 else
372                 {
373                     dc++;
374                 }
375             } /* While*/
376
377             if (*stop == '\0')
378             {
379                 st->start = NULL;
380             }
381             else
382             {
383                 st->start = stop;
384             }
385
386         }
387         else
388         {
389             st->start = NULL;
390             st->delimeter = '\0';
391         }
392     }
393     else
394     {
395         st->start = NULL;
396         result = NULL;
397     }
398
399
400     return result;
401 }
402
403
404
405 /*------------------------------------------------------------------------
406 Procedure:     PLD_strlower ID:1
407 Purpose:       Converts a string to lowercase
408 Input:         char *convertme : string to convert
409 Output:
410 Errors:
411 ------------------------------------------------------------------------*/
412 int PLD_strlower( unsigned char *convertme )
413 {
414
415     /* Updates:*/
416     /*  09-11-2002 - changed from 'char *' to 'unsigned char *' to deal with*/
417     /*          non-ASCII characters ( ie, french ).  Pointed out by Emmanuel Collignon*/
418
419     unsigned char *c = convertme;
420
421     while ( *c != '\0')
422     {
423         *c = (unsigned char)tolower((int) * c);
424         c++;
425     }
426
427     return 0;
428 }
429
430
431 /*-----------------------------------------------------------------\
432   Function Name : *PLD_strreplace
433   Returns Type  : char
434   ----Parameter List
435   1. char *source,              Original buffer, \0 terminated
436   2.  char *searchfor, String sequence to search for
437   3.  char *replacewith, String sequence to replace 'searchfor' with
438   4.  int replacenumber , How many times to replace 'searchfor', 0 == unlimited
439   ------------------
440   Exit Codes    : Returns a pointer to the new buffer space.  The original
441   buffer will still remain intact - ensure that the calling
442   program FREE()'s the original buffer if it's no longer
443   needed
444   Side Effects  :
445   --------------------------------------------------------------------
446 Comments:
447 Start out with static text matching - upgrade to regex later.
448
449 --------------------------------------------------------------------
450 Changes:
451
452 \------------------------------------------------------------------*/
453 char *PLD_strreplace_general( struct PLD_strreplace *replace_details )
454 {
455     char *new_buffer = NULL;
456     char *source_end;
457     char *segment_start, *segment_end, *segment_p;
458     char *new_p;
459     char *preexist_location = NULL;
460     char *postexist_location = NULL;
461     int replace_count = 0;
462     int size_required;
463     int size_difference;
464     int source_length;
465     int searchfor_length;
466     int replacewith_length;
467     int segment_ok;
468
469     if (replace_details->source == NULL)
470     {
471         return NULL;
472     }
473
474     source_length = (int)strlen( replace_details->source );
475     source_end = replace_details->source + source_length;
476     searchfor_length = (int)strlen(replace_details->searchfor);
477     replacewith_length = (int)strlen(replace_details->replacewith);
478     size_difference = replacewith_length - searchfor_length;
479     size_required = source_length;
480     replace_count = replace_details->replacenumber;
481
482     if ((replace_details->preexist != NULL) && (strlen(replace_details->preexist) < 1))
483     {
484         replace_details->preexist = NULL;
485     }
486     if ((replace_details->postexist != NULL) && (strlen(replace_details->postexist) < 1))
487     {
488         replace_details->postexist = NULL;
489     }
490
491     /* If we have a 'pre-exist' request, then we need to check this out first*/
492     /*          because if the pre-exist string cannot be found, then there's very*/
493     /*          little point us continuing on in our search ( because without the*/
494     /*          preexist string existing, we are thus not qualified to replace anything )*/
495     if (replace_details->preexist != NULL)
496     {
497         preexist_location = PLD_strstr(replace_details->source, replace_details->preexist, replace_details->insensitive);
498         if (preexist_location == NULL)
499         {
500             return replace_details->source;
501         }
502     }
503
504     /* Determine if initial POSTexist tests will pass, if we don't pick up*/
505     /*          anything here, then there's no point in continuing either*/
506     if (replace_details->postexist != NULL)
507     {
508         char *p = replace_details->source;
509         postexist_location = NULL;
510         do
511         {
512             p = PLD_strstr(p, replace_details->postexist, replace_details->insensitive);
513             if (p != NULL)
514             {
515                 postexist_location = p;
516                 p = p + strlen(replace_details->postexist);
517             }
518         }
519         while (p != NULL);
520
521         if (postexist_location == NULL)
522         {
523             return replace_details->source;
524         }
525     }
526
527
528     /* Step 1 - determine the MAXIMUM number of times we might have to replace this string ( or the limit*/
529     /*          set by replacenumber*/
530     /**/
531     /*  Note - we only need this number if the string we're going to be inserting into the */
532     /*  source is larger than the one we're replacing - this is so that we can ensure that*/
533     /*  we have sufficient memory available in the buffer.*/
534     if (size_difference > 0)
535     {
536         if (replace_count == 0)
537         {
538             char *p, *q;
539
540             p = replace_details->source;
541             q = PLD_strstr(p, replace_details->searchfor, replace_details->insensitive);
542             while (q != NULL)
543             {
544                 replace_count++;
545                 /*size_required += size_difference;*/
546                 p = q + searchfor_length;
547                 q = PLD_strstr(p, replace_details->searchfor, replace_details->insensitive);
548             }
549
550         }
551         size_required = source_length + (size_difference * replace_count) + 1;
552     }
553     else
554     {
555         size_required = source_length + 1;
556     }
557
558
559     /* Allocate the memory required to hold the new string [at least], check to see that*/
560     /*          all went well, if not, then return an error*/
561     new_buffer = MALLOC( sizeof(char) * size_required);
562     if (new_buffer == NULL)
563     {
564         LOGGER_log(_("%s:%d:PLD_strreplace:ERROR: Cannot allocate %d bytes of memory to perform replacement operation"), FL, size_required);
565         return replace_details->source;
566     }
567
568     /* Our segment must always start at the beginning of the source, */
569     /*          on the other hand, the segment_end can be anything from the*/
570     /*          next byte to NULL ( which is specially treated to mean to */
571     /*          the end of the source )*/
572     segment_start = replace_details->source;
573
574
575     /* Locate the first segment */
576     segment_ok = 0;
577     segment_end = PLD_strstr(replace_details->source, replace_details->searchfor, replace_details->insensitive);
578
579     /* Determine if the first segment is valid in the presence of the */
580     /*  pre-exist and post-exist requirements*/
581     while ((segment_end != NULL) && (segment_ok == 0)\
582             && ((replace_details->preexist != NULL) || (replace_details->postexist != NULL)))
583     {
584         int pre_ok = 0;
585         int post_ok = 0;
586
587         /* The PREexist test assumes a couple of factors - please ensure these are*/
588         /*              relevant if you change any code prior to this point.*/
589         /*      */
590         /*      1. preexist_location has already been computed and is not NULL*/
591         /**/
592         /*      2. By relative position, the first preexist_location will be a valid location*/
593         /*                      on which to validate for ALL replacements beyond that point, thus, we*/
594         /*                      never actually have to recompute preexist_location again.*/
595         /**/
596         /* 3. Conversely, the last computed postexist_location is valid for all */
597         /*                      matches before it*/
598         /**/
599         if (preexist_location == NULL)
600         {
601             pre_ok = 1;
602         }
603         else if (preexist_location < segment_end)
604         {
605             pre_ok = 1;
606         }
607
608         if (postexist_location == NULL)
609         {
610             post_ok = 1;
611         }
612         else if (postexist_location > segment_end)
613         {
614             post_ok = 1;
615         }
616
617         if ((pre_ok == 0) || (post_ok == 0))
618         {
619             segment_end = PLD_strstr(segment_end + searchfor_length, replace_details->searchfor, replace_details->insensitive);
620         }
621         else
622         {
623             segment_ok = 1;
624         }
625     }
626
627     segment_p = segment_start;
628     new_p = new_buffer;
629     while (segment_start != NULL)
630     {
631         int replacewith_count;
632         char *replacewith_p;
633
634         if (segment_end == NULL)
635         {
636             segment_end = source_end;
637         }
638
639         replace_count--;
640
641         /* Perform the segment copy*/
642         segment_p = segment_start;
643         while ((segment_p < segment_end) && (size_required > 0))
644         {
645             *new_p = *segment_p;
646             new_p++;
647             segment_p++;
648             size_required--;
649         }
650
651         /* Perform the string replacement*/
652         if (segment_end < source_end)
653         {
654             replacewith_count = replacewith_length;
655             replacewith_p = replace_details->replacewith;
656             while ((replacewith_count--) && (size_required > 0))
657             {
658                 *new_p = *replacewith_p;
659                 new_p++;
660                 replacewith_p++;
661                 size_required--;
662             }
663         }
664
665         if (size_required < 1 )
666         {
667             LOGGER_log(_("%s:%d:PLD_strreplace_general: Allocated memory ran out while replacing '%s' with '%s'"), FL, replace_details->searchfor, replace_details->replacewith);
668             *new_p = '\0';
669             break;
670         }
671
672         /* Find the next segment*/
673         segment_start = segment_end + searchfor_length;
674
675         /* If we've reached the end of the number of replacements we're supposed*/
676         /*              to do, then we prepare the termination of the while loop by setting*/
677         /*              our segment end to the end of the source.*/
678         /**/
679         /* NOTE: Remember that the replace_count is pre-decremented at the start*/
680         /*              of the while loop, so, if the caller requested '0' replacements*/
681         /*              this will now be -1, thus, it won't get terminated from this == 0*/
682         /*              match.  Just thought you'd like to be reminded of that incase you*/
683         /*              were wondering "Huh? this would terminate an unlimited replacement"*/
684         if (replace_count == 0)
685         {
686             segment_end = NULL;
687         }
688         else
689         {
690             /* If our new segment to copy starts after the*/
691             /*          end of the source, then we actually have */
692             /*          nothing else to copy, thus, we prepare the*/
693             /*          segment_start varible to cause the while loop */
694             /*          to terminate.*/
695             /**/
696             /* Otherwise, we try and locate the next segment*/
697             /*          ending point, and set the starting point to*/
698             /*          be on the 'other side' of the 'searchfor' string*/
699             /*          which we found in the last search.*/
700             /**/
701             if (segment_start > source_end)
702             {
703                 segment_start = NULL;
704             }
705             else
706             {
707
708                 /* Try find the next segment*/
709                 segment_ok = 0;
710                 segment_end = PLD_strstr(segment_end + searchfor_length, replace_details->searchfor, replace_details->insensitive);
711
712                 /* If we have a pre/post-exist requirement, then enter into this*/
713                 /*              series of tests.  NOTE - at least one of the pre or post tests*/
714                 /*              must fire to give an meaningful result - else we'll end up with */
715                 /*              a loop which simply goes to the end of the searchspace buffer*/
716                 while ((segment_end != NULL) && (segment_ok == 0)\
717                         && ((replace_details->preexist != NULL) || (replace_details->postexist != NULL)))
718                 {
719                     int pre_ok = 0;
720                     int post_ok = 0;
721
722                     /* The PREexist test assumes a couple of factors - please ensure these are*/
723                     /*          relevant if you change any code prior to this point.*/
724                     /*  */
725                     /*  1. preexist_location has already been computed and is not NULL*/
726                     /**/
727                     /*  2. By relative position, the first preexist_location will be a valid location*/
728                     /*                  on which to validate for ALL replacements beyond that point, thus, we*/
729                     /*                  never actually have to recompute preexist_location again.*/
730                     /**/
731                     /* 3. Conversely, the last computed postexist_location is valid for all */
732                     /*                  matches before it*/
733                     /**/
734                     if (preexist_location == NULL)
735                     {
736                         pre_ok = 1;
737                     }
738                     else if (preexist_location < segment_end)
739                     {
740                         pre_ok = 1;
741                     }
742
743                     if (postexist_location == NULL)
744                     {
745                         post_ok = 1;
746                     }
747                     else if (postexist_location > segment_end)
748                     {
749                         post_ok = 1;
750                     }
751
752                     if ((pre_ok == 0) || (post_ok == 0))
753                     {
754                         segment_end = PLD_strstr(segment_end + searchfor_length, replace_details->searchfor, replace_details->insensitive);
755                     }
756                     else
757                     {
758                         segment_ok = 1;
759                     }
760                 }
761
762             } /* If-else segment_start > source_end*/
763
764         }
765
766     }
767
768     *new_p = '\0';
769
770     if (replace_details->source != NULL)
771     {
772         FREE (replace_details->source);
773     }
774     replace_details->source = new_buffer;
775     return new_buffer;
776 }
777
778 /*-----------------------------------------------------------------\
779   Function Name : *PLD_strreplace
780   Returns Type  : char
781   ----Parameter List
782   1. char **source,
783   2.  char *searchfor,
784   3.  char *replacewith,
785   4.  int replacenumber ,
786   ------------------
787   Exit Codes    :
788   Side Effects  :
789   --------------------------------------------------------------------
790 Comments:
791
792 --------------------------------------------------------------------
793 Changes:
794
795 \------------------------------------------------------------------*/
796 char *PLD_strreplace( char **source, char *searchfor, char *replacewith, int replacenumber )
797 {
798     struct PLD_strreplace replace_details;
799     char *tmp_source;
800
801     replace_details.source = *source;
802     replace_details.searchfor = searchfor;
803     replace_details.replacewith = replacewith;
804     replace_details.replacenumber = replacenumber;
805     replace_details.preexist = NULL;
806     replace_details.postexist = NULL;
807     replace_details.insensitive = 0;
808
809     tmp_source = PLD_strreplace_general( &replace_details );
810
811     if (tmp_source != *source)
812     {
813         *source = tmp_source;
814     }
815
816     return *source;
817 }
818
819
820 /*-----------------------------------------------------------------\
821  Function Name  : *PLD_dprintf
822  Returns Type   : char
823         ----Parameter List
824         1. const char *format,
825         2.  ...,
826         ------------------
827  Exit Codes     :
828  Side Effects   :
829 --------------------------------------------------------------------
830  Comments:
831         This is a dynamic string allocation function, not as fast as some
832         other methods, but it works across the board with both glibc 2.0
833         and 2.1 series.
834
835 --------------------------------------------------------------------
836  Changes:
837
838 \------------------------------------------------------------------*/
839 char *PLD_dprintf(const char *format, ...)
840 {
841     int n, size = 1024; /* Assume we don't need more than 1K to start with*/
842     char *p;
843     va_list ap;
844
845     /* Attempt to allocate and then check */
846     p = MALLOC(size * sizeof(char));
847     if (p == NULL)
848     {
849         return NULL;
850     }
851
852     while (1)
853     {
854         /* Attempt to print out string out into the allocated space*/
855         va_start(ap, format);
856
857         n = vsnprintf (p, size, format, ap);
858         va_end(ap);
859
860         /* If things went well, then return the new string*/
861         if ((n > -1) && (n < size))
862         {
863             return p;
864         }
865
866         /* If things didn't go well, then we have to allocate more space*/
867         /*      based on which glibc we're using ( fortunately, the return codes*/
868         /*      tell us which glibc is being used! *phew**/
869         /**/
870         /* If n > -1, then we're being told precisely how much space we need*/
871         /* else (older glibc) we have to just guess again ...*/
872
873         if (n > -1)
874         {
875             size = n + 1;    /* Allocate precisely what is needed*/
876         }
877         else
878         {
879             size *= 2;    /* Double the amount allocated, note, we could just increase by 1K, but if we have a long string, we'd end up using a lot of realloc's*/
880         }
881
882         /* We could just realloc 'blind', but that'd be wrong and potentially cause a DoS, so*/
883         /*      instead, we'll be good and first attempt to realloc to a temp variable then, if all*/
884         /*      is well, we go ahead and update*/
885         if (1)
886         {
887             char *tmp_p;
888
889             tmp_p = REALLOC(p, size);
890             if (tmp_p == NULL)
891             {
892                 if (p != NULL)
893                 {
894                     FREE(p);
895                 }
896                 return NULL;
897             }
898             else
899             {
900                 p = tmp_p;
901             }
902         }
903     }
904
905 }
906
907
908 /*-----------------END.*/