pldstr.c

Go to the documentation of this file.
00001 
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include <stdlib.h>
00005 #include <ctype.h>
00006 #include <stddef.h>
00007 #include <stdio.h>
00008 #include <stdarg.h>
00009 
00010 #include "logger.h"
00011 #include "pldstr.h"
00012 
00013 #include "MALLOC.h"
00014 
00015 #ifdef _MSC_VER
00016         #define vsnprintf _vsnprintf
00017         #define strdup _strdup
00018 #endif
00019 
00020 /*-----------------------------------------------------------------\
00021  Function Name  : *PLD_strstr
00022  Returns Type   : char
00023         ----Parameter List
00024         1. char *haystack, 
00025         2.  char *needle, 
00026         3.  int insensitive, 
00027         ------------------
00028  Exit Codes     : 
00029  Side Effects   : 
00030 --------------------------------------------------------------------
00031  Comments:
00032  
00033 --------------------------------------------------------------------
00034  Changes:
00035  
00036 \------------------------------------------------------------------*/
00037 char *PLD_strstr(char *haystack, char *needle, int insensitive)
00038 {
00039         char *hs, *ne;
00040         char *result;
00041 
00042         /*      LOGGER_log("%s:%d:\nHS=%s\nNE=%s\nIS=%d\n",FL, haystack, needle, insensitive );*/
00043 
00044         if (insensitive > 0)
00045         {
00046                 hs = strdup(haystack);
00047                 PLD_strlower(hs);
00048                 ne = strdup(needle);
00049                 PLD_strlower(ne);
00050         } else {
00051                 hs = haystack;
00052                 ne = needle;
00053         }
00054 
00055         result = strstr(hs, ne);
00056         /*      if (result) LOGGER_log("%s:%d:HIT: %s",FL, result);*/
00057         /*      else LOGGER_log("%s:%d:MISS (looking for %s|%s)",FL, needle,ne);*/
00058 
00059         if ((result != NULL)&&(insensitive > 0))
00060         {
00061                 result = result -hs +haystack;
00062                 FREE(hs);
00063                 FREE(ne);
00064 
00065                 /*              LOGGER_log("%s:%d:HIT - %s",FL, result );*/
00066         }
00067 
00068         return result;
00069 }
00070 
00071 /*------------------------------------------------------------------------
00072 Procedure:     PLD_strncpy ID:1
00073 Purpose:       Copy characters from 'src' to 'dst', writing not more than 'len'
00074 characters to the destination, including the terminating \0.
00075 Thus, for any effective copying, len must be > 1.
00076 Input:         char *dst: Destination string
00077 char *src: Source string
00078 size_t len: length of string
00079 Output:        Returns a pointer to the destination string.
00080 Errors:
00081 ------------------------------------------------------------------------*/
00082 char *PLD_strncpy (char *dst, const char *src, size_t len)
00083 {
00084 
00085   /* Thanks go to 'defrost' of #c for providing the replacement*/
00086   /*            code which you now see here.  It covers the errors better*/
00087   /*            than my own previous code.*/
00088 
00089   /* If we have no buffer space, then it's futile attempting*/
00090   /*            to copy anything, just return NULL*/
00091         if (len==0) return NULL;
00092 
00093         /* Providing our destination pointer isn't NULL, we can*/
00094         /*              commence copying data across*/
00095 
00096         if (dst)
00097         {
00098                 char *dp = dst;
00099 
00100                 /* If our source string exists, start moving it to the*/
00101                 /*              destination string character at a time.*/
00102                 if (src)
00103                 {
00104                         char *sp = (char *)src;
00105                         while ((--len)&&(*sp)) { *dp=*sp; dp++; sp++; }
00106                 }
00107 
00108                 *dp='\0';
00109         }
00110 
00111         return dst;
00112 }
00113 
00114 
00115 
00116 /*------------------------------------------------------------------------
00117 Procedure:     PLD_strncat ID:1
00118 Purpose:       Buffer size limited string concat function for two strings.
00119 Input:         char *dst: Destination string
00120 char *src: Source string
00121 size_t len: Destination string buffer size - total string size cannot exceed this
00122 Output:
00123 Errors:        If the length of both strings in total is greater than the available buffer space
00124 in *dst, we copy the maximum possible amount of chars from *src such that
00125 buffer does not overflow.  A suffixed '\0' will always be appended.
00126 ------------------------------------------------------------------------*/
00127 char *PLD_strncat( char *dst, const char *src, size_t len )
00128 {
00129         char *dp = dst;
00130         const char *sp = src;
00131         size_t cc;
00132 
00133         if (len == 0) return dst;
00134 
00135         len--;
00136 
00137         /* Locate the end of the current string.*/
00138         cc = 0;
00139         while ((*dp)&&(cc < len)) { dp++; cc++; }
00140 
00141         /* If we have no more buffer space, then return the destination*/
00142 
00143         if (cc >= len) return dst;
00144 
00145         /* While we have more source, and there's more char space left in the buffer*/
00146 
00147         while ((*sp)&&(cc < len))
00148         {
00149                 cc++;
00150                 *dp = *sp;
00151                 dp++;
00152                 sp++;
00153         }
00154 
00155         /* Terminate dst, as a gaurantee of string ending.*/
00156 
00157         *dp = '\0';
00158 
00159         return dst;
00160 }
00161 
00162 
00163 /*------------------------------------------------------------------------
00164 Procedure:     PLD_strncate ID:1
00165 Purpose:       Catencates a source string to the destination string starting from a given
00166 endpoint.  This allows for faster catencation of strings by avoiding the
00167 computation required to locate the endpoint of the destination string.
00168 Input:         char *dst: Destination string
00169 char *src: Source string
00170 size_t len: Destination buffer size
00171 char *endpoint: Endpoint of destination string, location from where new
00172 string will be appended
00173 Output:
00174 Errors:
00175 ------------------------------------------------------------------------*/
00176 char *PLD_strncate( char *dst, const char *src, size_t len, char *endpoint )
00177 {
00178         char *dp = dst;
00179         const char *sp = src;
00180         size_t cc = 0;
00181 
00182         if (len == 0) return dst;
00183 
00184         len--;
00185 
00186         /* If endpoint does not relate correctly, then force manual detection*/
00187         /* of the endpoint.*/
00188 
00189         if ((!endpoint)||(endpoint == dst)||((endpoint -dst +1)>(int)len))
00190         {
00191           /* Locate the end of the current string.*/
00192                 cc = 0;
00193                 while ((*dp != '\0')&&(cc < len)) { dp++; cc++; }
00194         }
00195         else {
00196                 cc = endpoint -dst +1;
00197                 dp = endpoint;
00198         }
00199 
00200         /* If we have no more buffer space, then return the destination*/
00201 
00202         if (cc >= len) return dst;
00203 
00204         /* While we have more source, and there's more char space left in the buffer*/
00205 
00206         while ((*sp)&&(cc < len))
00207         {
00208                 cc++;
00209                 *dp = *sp;
00210                 dp++;
00211                 sp++;
00212         }
00213 
00214         /* Terminate dst, as a gaurantee of string ending.*/
00215 
00216         *dp = '\0';
00217 
00218         return dst;
00219 }
00220 
00221 
00222 
00223 
00224 
00225 /*------------------------------------------------------------------------
00226 Procedure:     XAM_strncasecmp ID:1
00227 Purpose:       Portable version of strncasecmp(), this may be removed in later
00228 versions as the strncase* type functions are more widely
00229 implemented
00230 Input:
00231 Output:
00232 Errors:
00233 ------------------------------------------------------------------------*/
00234 int PLD_strncasecmp( char *s1, char *s2, int n )
00235 {
00236         char *ds1 = s1, *ds2 = s2;
00237         char c1, c2;
00238         int result = 0;
00239 
00240         while(n > 0)
00241         {
00242                 c1 = tolower(*ds1);
00243                 c2 = tolower(*ds2);
00244 
00245                 if (c1 == c2)
00246                 {
00247                         n--;
00248                         ds1++;
00249                         ds2++;
00250                 }
00251                 else
00252                 {
00253                         result = c2 - c1;
00254                         n = 0;
00255                 }
00256 
00257         }
00258 
00259         return result;
00260 
00261 }
00262 
00263 
00264 
00265 
00266 
00267 /*------------------------------------------------------------------------
00268 Procedure:     XAM_strtok ID:1
00269 Purpose:       A thread safe version of strtok()
00270 Input:
00271 Output:
00272 Errors:
00273 ------------------------------------------------------------------------*/
00274 char *PLD_strtok( struct PLD_strtok *st, char *line, char *delimeters )
00275 {
00276         char *stop;
00277         char *dc;
00278         char *result = NULL;
00279 
00280         if ( line )
00281         {
00282                 st->start = line;
00283         }
00284 
00285         /*Strip off any leading delimeters*/
00286 
00287         dc = delimeters;
00288         while ((st->start)&&(*dc != '\0'))
00289         {
00290                 if (*dc == *(st->start))
00291                 {
00292                         st->start++;
00293                         dc = delimeters;
00294                 }
00295                 else dc++;
00296         }
00297 
00298         /* Where we are left, is the start of our token.*/
00299 
00300         result = st->start;
00301 
00302         if ((st->start)&&(st->start != '\0'))
00303         {
00304                 stop = strpbrk( st->start, delimeters ); /* locate our next delimeter */
00305 
00306                 /* If we found a delimeter, then that is good.  We must now break the string here*/
00307                 /* and don't forget to store the character which we stopped on.  Very useful bit*/
00308                 /* of information for programs which process expressions.*/
00309 
00310                 if (stop)
00311                 {
00312 
00313                   /* Store our delimeter.*/
00314 
00315                         st->delimeter = *stop;
00316 
00317                         /* Terminate our token.*/
00318 
00319                         *stop = '\0';
00320 
00321 
00322                         /* Because we're emulating strtok() behaviour here, we have to*/
00323                         /* absorb all the concurrent delimeters, that is, unless we*/
00324                         /* reach the end of the string, we cannot return a string with*/
00325                         /* no chars.*/
00326 
00327                         stop++;
00328                         dc = delimeters;
00329                         while (*dc != '\0')
00330                         {
00331                                 if (*dc == *stop)
00332                                 {
00333                                         stop++;
00334                                         dc = delimeters;
00335                                 }
00336                                 else dc++;
00337                         } /* While*/
00338 
00339                         if (*stop == '\0') st->start = NULL;
00340                         else st->start = stop;
00341 
00342                 }
00343                 else {
00344                         st->start = NULL;
00345                         st->delimeter = '\0';
00346                 }
00347         }
00348         else  {
00349                 st->start = NULL;
00350                 result = NULL;
00351         }
00352 
00353 
00354         return result;
00355 }
00356 
00357 
00358 
00359 /*------------------------------------------------------------------------
00360 Procedure:     PLD_strlower ID:1
00361 Purpose:       Converts a string to lowercase
00362 Input:         char *convertme : string to convert
00363 Output:
00364 Errors:
00365 ------------------------------------------------------------------------*/
00366 int PLD_strlower( unsigned char *convertme )
00367 {
00368 
00369   /* Updates:*/
00370   /*    09-11-2002 - changed from 'char *' to 'unsigned char *' to deal with*/
00371   /*            non-ASCII characters ( ie, french ).  Pointed out by Emmanuel Collignon*/
00372 
00373         char *c = convertme;
00374 
00375         while ( *c != '\0') {*c = tolower((int)*c); c++;}
00376 
00377         return 0;
00378 }
00379 
00380 
00381 /*-----------------------------------------------------------------\
00382   Function Name : *PLD_strreplace
00383   Returns Type  : char
00384   ----Parameter List
00385   1. char *source,              Original buffer, \0 terminated
00386   2.  char *searchfor, String sequence to search for
00387   3.  char *replacewith, String sequence to replace 'searchfor' with
00388   4.  int replacenumber , How many times to replace 'searchfor', 0 == unlimited
00389   ------------------
00390   Exit Codes    : Returns a pointer to the new buffer space.  The original 
00391   buffer will still remain intact - ensure that the calling
00392   program FREE()'s the original buffer if it's no longer
00393   needed
00394   Side Effects  : 
00395   --------------------------------------------------------------------
00396 Comments:
00397 Start out with static text matching - upgrade to regex later.
00398 
00399 --------------------------------------------------------------------
00400 Changes:
00401 
00402 \------------------------------------------------------------------*/
00403 char *PLD_strreplace_general( struct PLD_strreplace *replace_details )
00404 {
00405         char *new_buffer=NULL;
00406         char *source_end;
00407         char *segment_start, *segment_end, *segment_p;
00408         char *new_p;
00409         char *preexist_location=NULL;
00410         char *postexist_location=NULL;
00411         int replace_count=0;
00412         int size_required;
00413         int size_difference;
00414         int source_length;
00415         int searchfor_length;
00416         int replacewith_length;
00417         int segment_ok;
00418 
00419         if (replace_details->source == NULL) return NULL;
00420 
00421         source_length = strlen( replace_details->source );
00422         source_end = replace_details->source +source_length;
00423         searchfor_length = strlen(replace_details->searchfor);
00424         replacewith_length = strlen(replace_details->replacewith);
00425         size_difference = replacewith_length -searchfor_length;
00426         size_required = source_length;
00427         replace_count = replace_details->replacenumber;
00428 
00429         if ((replace_details->preexist != NULL)&&(strlen(replace_details->preexist) < 1)) replace_details->preexist = NULL;
00430         if ((replace_details->postexist != NULL)&&(strlen(replace_details->postexist) < 1)) replace_details->postexist = NULL;
00431 
00432         /* If we have a 'pre-exist' request, then we need to check this out first*/
00433         /*              because if the pre-exist string cannot be found, then there's very*/
00434         /*              little point us continuing on in our search ( because without the*/
00435         /*              preexist string existing, we are thus not qualified to replace anything )*/
00436         if (replace_details->preexist != NULL)
00437         {
00438                 preexist_location = PLD_strstr(replace_details->source, replace_details->preexist, replace_details->insensitive);
00439                 if (preexist_location == NULL)
00440                 {
00441                         return replace_details->source;
00442                 }
00443         } 
00444 
00445         /* Determine if initial POSTexist tests will pass, if we don't pick up*/
00446         /*              anything here, then there's no point in continuing either*/
00447         if (replace_details->postexist != NULL)
00448         {
00449                 char *p = replace_details->source;
00450                 postexist_location = NULL;
00451                 do {
00452                         p = PLD_strstr(p, replace_details->postexist, replace_details->insensitive);
00453                         if (p != NULL)
00454                         {
00455                                 postexist_location = p;
00456                                 p = p +strlen(replace_details->postexist);
00457                         } 
00458                 } while (p != NULL);
00459 
00460                 if (postexist_location == NULL)
00461                 {
00462                         return replace_details->source;
00463                 }
00464         } 
00465 
00466 
00467         /* Step 1 - determine the MAXIMUM number of times we might have to replace this string ( or the limit*/
00468         /*              set by replacenumber*/
00469         
00470         /*      Note - we only need this number if the string we're going to be inserting into the */
00471         /*      source is larger than the one we're replacing - this is so that we can ensure that*/
00472         /*      we have sufficient memory available in the buffer.*/
00473         if (size_difference > 0)
00474         {
00475                 if (replace_count == 0)
00476                 {
00477                         char *p, *q;
00478 
00479                         p = replace_details->source;
00480                         q = PLD_strstr(p, replace_details->searchfor, replace_details->insensitive);
00481                         while (q != NULL)
00482                         {
00483                                 replace_count++;
00484                                 /*size_required += size_difference;*/
00485                                 p = q +searchfor_length;
00486                                 q = PLD_strstr(p, replace_details->searchfor, replace_details->insensitive);
00487                         }
00488 
00489                 }
00490                 size_required = source_length +(size_difference *replace_count) +1;
00491         } else size_required = source_length +1;
00492 
00493         
00494         /* Allocate the memory required to hold the new string [at least], check to see that*/
00495         /*              all went well, if not, then return an error*/
00496         new_buffer = MALLOC( sizeof(char) *size_required);
00497         if (new_buffer == NULL)
00498         {
00499                 LOGGER_log("%s:%d:PLD_strreplace:ERROR: Cannot allocate %d bytes of memory to perform replacement operation", FL, size_required);
00500                 return replace_details->source;
00501         } 
00502 
00503         /* Our segment must always start at the beginning of the source, */
00504         /*              on the other hand, the segment_end can be anything from the*/
00505         /*              next byte to NULL ( which is specially treated to mean to */
00506         /*              the end of the source )*/
00507         segment_start = replace_details->source;
00508 
00509 
00510         /* Locate the first segment */
00511         segment_ok = 0;
00512         segment_end = PLD_strstr(replace_details->source, replace_details->searchfor, replace_details->insensitive);
00513 
00514         /* Determine if the first segment is valid in the presence of the */
00515         /*      pre-exist and post-exist requirements*/
00516         while ((segment_end != NULL)&&(segment_ok == 0)\
00517                         &&((replace_details->preexist != NULL)||(replace_details->postexist != NULL)))
00518         {
00519                 int pre_ok = 0;
00520                 int post_ok = 0;
00521 
00522                 /* The PREexist test assumes a couple of factors - please ensure these are*/
00523                 /*              relevant if you change any code prior to this point.*/
00524                 /*      */
00525                 /*      1. preexist_location has already been computed and is not NULL*/
00526                 
00527                 /*      2. By relative position, the first preexist_location will be a valid location*/
00528                 /*                      on which to validate for ALL replacements beyond that point, thus, we*/
00529                 /*                      never actually have to recompute preexist_location again.*/
00530                 
00531                 /* 3. Conversely, the last computed postexist_location is valid for all */
00532                 /*                      matches before it*/
00533                 
00534                 if (preexist_location == NULL) pre_ok = 1;
00535                 else if (preexist_location < segment_end){ pre_ok = 1;}
00536 
00537                 if (postexist_location == NULL) post_ok = 1;
00538                 else if (postexist_location > segment_end){ post_ok = 1;}
00539 
00540                 if ((pre_ok == 0)||(post_ok == 0)) { segment_end = PLD_strstr(segment_end +searchfor_length, replace_details->searchfor, replace_details->insensitive); }
00541                 else segment_ok = 1;
00542         } 
00543 
00544         segment_p = segment_start;
00545         new_p = new_buffer;
00546         while (segment_start != NULL)
00547         {       
00548                 int replacewith_count;
00549                 char *replacewith_p;
00550 
00551                 if (segment_end == NULL) segment_end = source_end;
00552 
00553                 replace_count--;
00554 
00555                 /* Perform the segment copy*/
00556                 segment_p = segment_start;
00557                 while ((segment_p < segment_end)&&(size_required > 0))
00558                 {
00559                         *new_p = *segment_p;
00560                         new_p++;
00561                         segment_p++;
00562                         size_required--;
00563                 }
00564 
00565                 /* Perform the string replacement*/
00566                 if (segment_end < source_end)
00567                 {
00568                         replacewith_count = replacewith_length;
00569                         replacewith_p = replace_details->replacewith;
00570                         while ((replacewith_count--)&&(size_required > 0))
00571                         {
00572                                 *new_p = *replacewith_p;
00573                                 new_p++;
00574                                 replacewith_p++;
00575                                 size_required--;
00576                         }
00577                 }
00578 
00579                 if (size_required < 1 )
00580                 {
00581                         LOGGER_log("%s:%d:PLD_strreplace_general: Allocated memory ran out while replacing '%s' with '%s'",FL, replace_details->searchfor, replace_details->replacewith);
00582                         *new_p='\0';
00583                         break;
00584                 }
00585 
00586                 /* Find the next segment*/
00587                 segment_start = segment_end +searchfor_length;
00588 
00589                 /* If we've reached the end of the number of replacements we're supposed*/
00590                 /*              to do, then we prepare the termination of the while loop by setting*/
00591                 /*              our segment end to the end of the source.*/
00592                 
00593                 /* NOTE: Remember that the replace_count is pre-decremented at the start*/
00594                 /*              of the while loop, so, if the caller requested '0' replacements*/
00595                 /*              this will now be -1, thus, it won't get terminated from this == 0*/
00596                 /*              match.  Just thought you'd like to be reminded of that incase you*/
00597                 /*              were wondering "Huh? this would terminate an unlimited replacement"*/
00598                 if (replace_count == 0)
00599                 {
00600                         segment_end = NULL;
00601                 } else {
00602                   /* If our new segment to copy starts after the*/
00603                   /*            end of the source, then we actually have */
00604                   /*            nothing else to copy, thus, we prepare the*/
00605                   /*            segment_start varible to cause the while loop */
00606                   /*            to terminate.*/
00607                   
00608                   /* Otherwise, we try and locate the next segment*/
00609                   /*            ending point, and set the starting point to*/
00610                   /*            be on the 'other side' of the 'searchfor' string*/
00611                   /*            which we found in the last search.*/
00612                   
00613                         if (segment_start > source_end) 
00614                         {
00615                                 segment_start = NULL;
00616                         } else {
00617 
00618                           /* Try find the next segment*/
00619                                 segment_ok = 0;
00620                                 segment_end = PLD_strstr(segment_end +searchfor_length, replace_details->searchfor, replace_details->insensitive);
00621 
00622                                 /* If we have a pre/post-exist requirement, then enter into this*/
00623                                 /*              series of tests.  NOTE - at least one of the pre or post tests*/
00624                                 /*              must fire to give an meaningful result - else we'll end up with */
00625                                 /*              a loop which simply goes to the end of the searchspace buffer*/
00626                                 while ((segment_end != NULL)&&(segment_ok == 0)\
00627                                                 &&((replace_details->preexist != NULL)||(replace_details->postexist != NULL)))
00628                                 {
00629                                         int pre_ok = 0;
00630                                         int post_ok = 0;
00631 
00632                                         /* The PREexist test assumes a couple of factors - please ensure these are*/
00633                                         /*              relevant if you change any code prior to this point.*/
00634                                         /*      */
00635                                         /*      1. preexist_location has already been computed and is not NULL*/
00636                                         
00637                                         /*      2. By relative position, the first preexist_location will be a valid location*/
00638                                         /*                      on which to validate for ALL replacements beyond that point, thus, we*/
00639                                         /*                      never actually have to recompute preexist_location again.*/
00640                                         
00641                                         /* 3. Conversely, the last computed postexist_location is valid for all */
00642                                         /*                      matches before it*/
00643                                         
00644                                         if (preexist_location == NULL) pre_ok = 1;
00645                                         else if (preexist_location < segment_end){ pre_ok = 1;}
00646 
00647                                         if (postexist_location == NULL) post_ok = 1;
00648                                         else if (postexist_location > segment_end){ post_ok = 1;}
00649 
00650                                         if ((pre_ok == 0)||(post_ok == 0)) { segment_end = PLD_strstr(segment_end +searchfor_length, replace_details->searchfor, replace_details->insensitive); }
00651                                         else segment_ok = 1;
00652                                 } 
00653 
00654                         } /* If-else segment_start > source_end*/
00655 
00656                 }
00657 
00658         }
00659 
00660         *new_p = '\0';
00661 
00662         if (replace_details->source != NULL) FREE (replace_details->source);
00663         replace_details->source = new_buffer;
00664         return new_buffer;
00665 }
00666 
00667 /*-----------------------------------------------------------------\
00668   Function Name : *PLD_strreplace
00669   Returns Type  : char
00670   ----Parameter List
00671   1. char **source, 
00672   2.  char *searchfor, 
00673   3.  char *replacewith, 
00674   4.  int replacenumber , 
00675   ------------------
00676   Exit Codes    : 
00677   Side Effects  : 
00678   --------------------------------------------------------------------
00679 Comments:
00680 
00681 --------------------------------------------------------------------
00682 Changes:
00683 
00684 \------------------------------------------------------------------*/
00685 char *PLD_strreplace( char **source, char *searchfor, char *replacewith, int replacenumber )
00686 {
00687         struct PLD_strreplace replace_details;
00688         char *tmp_source;
00689 
00690         replace_details.source = *source;
00691         replace_details.searchfor = searchfor;
00692         replace_details.replacewith = replacewith;
00693         replace_details.replacenumber = replacenumber;
00694         replace_details.preexist = NULL;
00695         replace_details.postexist = NULL;
00696         replace_details.insensitive = 0;
00697 
00698         tmp_source = PLD_strreplace_general( &replace_details );
00699 
00700         if (tmp_source != *source) *source = tmp_source;
00701 
00702         return *source;
00703 }
00704 
00705 
00706 /*-----------------------------------------------------------------\
00707  Function Name  : *PLD_dprintf
00708  Returns Type   : char
00709         ----Parameter List
00710         1. const char *format, 
00711         2.  ..., 
00712         ------------------
00713  Exit Codes     : 
00714  Side Effects   : 
00715 --------------------------------------------------------------------
00716  Comments:
00717         This is a dynamic string allocation function, not as fast as some
00718         other methods, but it works across the board with both glibc 2.0 
00719         and 2.1 series.  
00720  
00721 --------------------------------------------------------------------
00722  Changes:
00723  
00724 \------------------------------------------------------------------*/
00725 char *PLD_dprintf(const char *format, ...) 
00726 {
00727   int n, size = 1024; /* Assume we don't need more than 1K to start with*/
00728         char *p;
00729         va_list ap;
00730 
00731         /* Attempt to allocate and then check */
00732         p = MALLOC(size *sizeof(char));
00733         if (p == NULL) return NULL;
00734 
00735         while (1) 
00736         {
00737           /* Attempt to print out string out into the allocated space*/
00738                 va_start(ap, format);
00739 
00740                 n = vsnprintf (p, size, format, ap);
00741                 va_end(ap);
00742 
00743                 /* If things went well, then return the new string*/
00744                 if ((n > -1) && (n < size)) return p;
00745 
00746                 /* If things didn't go well, then we have to allocate more space*/
00747                 /*      based on which glibc we're using ( fortunately, the return codes*/
00748                 /*      tell us which glibc is being used! *phew**/
00749                 
00750                 /* If n > -1, then we're being told precisely how much space we need*/
00751                 /* else (older glibc) we have to just guess again ...*/
00752 
00753                 if (n > -1) size = n+1; /* Allocate precisely what is needed*/
00754                 else 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*/
00755 
00756                 /* We could just realloc 'blind', but that'd be wrong and potentially cause a DoS, so*/
00757                 /*      instead, we'll be good and first attempt to realloc to a temp variable then, if all*/
00758                 /*      is well, we go ahead and update*/
00759                 if (1)
00760                 {
00761                         char *tmp_p;
00762 
00763                         tmp_p = REALLOC(p, size);
00764                         if (tmp_p == NULL){ if (p != NULL) FREE(p); return NULL; }
00765                         else p = tmp_p;
00766                 }
00767         }
00768 
00769 }
00770 
00771 
00772 /*-----------------END.*/

Generated on Sun Mar 4 15:03:49 2007 for Scilab [trunk] by  doxygen 1.5.1