Classes | Defines | Functions

xnprintf.c File Reference

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <limits.h>
Include dependency graph for xnprintf.c:

Go to the source code of this file.

Classes

struct  xprintf_struct

Defines

#define va_copy(dst, src)   memcpy (&dst, &src, sizeof(va_list))
#define ALLOC_CHUNK   2048
#define ALLOC_SECURITY_MARGIN   1024
#define SRCTXT   (s->src_string)
#define DESTTXT   (s->dest_string)
#define INCOHERENT()   do {SRCTXT=initial_ptr; if (1) return 0;} while (0)
#define INCOHERENT_TEST()   do {if(*SRCTXT==0) INCOHERENT();} while (0)

Functions

static int realloc_buff (xprintf_struct *s, size_t len)
static int usual_char (xprintf_struct *s)
static int print_it (xprintf_struct *s, size_t approx_len, const char *format_string,...)
static int type_s (xprintf_struct *s, int width, int prec, const char *format_string, const char *arg_string)
static int getint (const char **string)
static int dispatch (xprintf_struct *s)
static int core (xprintf_struct *s)
int _xn_nprintf (int maxlen, const char *format_string,...)
int _xn_vnprintf (int maxlen, const char *format_string, va_list vargs)
int _xn_snprintf (char *dest_string, int maxlen, const char *format_string,...)
int _xn_vsnprintf (char *dest_string, int maxlen, const char *format_string, va_list vargs)
int _xn_fnprintf (FILE *file, int maxlen, const char *format_string,...)
int _xn_vfnprintf (FILE *file, int maxlen, const char *format_string, va_list vargs)
int _xn_asprintf (char **ptr, const char *format_string,...)
int _xn_vasprintf (char **ptr, const char *format_string, va_list vargs)
int _xn_asnprintf (char **ptr, int maxlen, const char *format_string,...)
int _xn_vasnprintf (char **ptr, int maxlen, const char *format_string, va_list vargs)

Detailed Description

This file contains an implementation of xnprintf. See the original copyright notice below.

Definition in file xnprintf.c.


Define Documentation

#define ALLOC_CHUNK   2048

Definition at line 182 of file xnprintf.c.

#define ALLOC_SECURITY_MARGIN   1024

Definition at line 183 of file xnprintf.c.

#define DESTTXT   (s->dest_string)
 
#define INCOHERENT (  )     do {SRCTXT=initial_ptr; if (1) return 0;} while (0)
 
#define INCOHERENT_TEST (  )     do {if(*SRCTXT==0) INCOHERENT();} while (0)
#define SRCTXT   (s->src_string)
#define va_copy ( dst,
src   )     memcpy (&dst, &src, sizeof(va_list))

Definition at line 169 of file xnprintf.c.


Function Documentation

int _xn_asnprintf ( char **  ptr,
int  maxlen,
const char *  format_string,
  ... 
)

Definition at line 1012 of file xnprintf.c.

{
     xprintf_struct s;
     va_list        vargs;
     int            retval;

     va_start( vargs, format_string );

     s.src_string = format_string;
     /* s.vargs = vargs; */
     va_copy(s.vargs, vargs);
     s.flavour = 'a';
     s.maxlen = (size_t)maxlen;

     retval = core( &s );
     va_end( vargs );
     if ( retval != EOF )
       {
          *ptr = NULL;
          return EOF;
       }

     *ptr = s.buffer_base;
     return retval;
}

Here is the call graph for this function:

int _xn_asprintf ( char **  ptr,
const char *  format_string,
  ... 
)

Definition at line 951 of file xnprintf.c.

{
     xprintf_struct s;
     va_list        vargs;
     int            retval;

     va_start( vargs, format_string );

     s.src_string = format_string;
     /* s.vargs = vargs; */
     va_copy(s.vargs, vargs);
     s.flavour = 'a';
     s.maxlen = (size_t)INT_MAX;

     retval = core( &s );
     va_end( vargs );
     if ( retval != EOF )
       {
          *ptr = NULL;
          return EOF;
       }

     *ptr = s.buffer_base;
     return retval;
}

Here is the call graph for this function:

int _xn_fnprintf ( FILE *  file,
int  maxlen,
const char *  format_string,
  ... 
)

Definition at line 905 of file xnprintf.c.

{
     xprintf_struct s;
     va_list        vargs;
     int            retval;

     va_start( vargs, format_string );

     s.src_string = format_string;
     s.maxlen = (size_t)maxlen;
     /* s.vargs = vargs; */
     va_copy(s.vargs, vargs);
     s.fprintf_file = file;
     s.flavour = 'f';

     retval = core( &s );
     va_end( vargs );
     return retval;
}

Here is the call graph for this function:

int _xn_nprintf ( int  maxlen,
const char *  format_string,
  ... 
)

Definition at line 798 of file xnprintf.c.

{
     xprintf_struct s;
     va_list        vargs;
     int            retval;

     va_start( vargs, format_string );

     s.src_string = format_string;
     s.maxlen = (size_t)maxlen;
     /* s.vargs = vargs; */
     va_copy(s.vargs, vargs);
     s.flavour = 'p';

     retval = core( &s );
     va_end( vargs );
     return retval;
}

Here is the call graph for this function:

int _xn_snprintf ( char *  dest_string,
int  maxlen,
const char *  format_string,
  ... 
)

Definition at line 840 of file xnprintf.c.

{
     xprintf_struct s;
     va_list        vargs;
     int            retval;

     if ( dest_string == NULL )
          return EOF;

     va_start( vargs, format_string );

     /* memset to avoid purify UMR errors */
     memset(&s, 0, sizeof(s));

     s.src_string = format_string;
     s.maxlen = (size_t)maxlen;
     /* s.vargs = vargs; */
     va_copy(s.vargs, vargs);
     s.sprintf_string = dest_string;
     s.flavour = 's';

     retval = core( &s );
     va_end( vargs );
     if ( retval == EOF )
          if ( maxlen > 0 )
               dest_string[0] = 0;

     return retval;
}

Here is the call graph for this function:

int _xn_vasnprintf ( char **  ptr,
int  maxlen,
const char *  format_string,
va_list  vargs 
)

Definition at line 1044 of file xnprintf.c.

{
     xprintf_struct s;
     int            retval;

     s.src_string = format_string;
     /* s.vargs = vargs; */
     va_copy(s.vargs, vargs);
     s.flavour = 'a';
     s.maxlen = (size_t)maxlen;

     retval = core( &s );
     if ( retval == EOF )
       {
          *ptr = NULL;
          return EOF;
       }

     *ptr = s.buffer_base;
     return retval;
}

Here is the call graph for this function:

int _xn_vasprintf ( char **  ptr,
const char *  format_string,
va_list  vargs 
)

Definition at line 982 of file xnprintf.c.

{
     xprintf_struct s;
     int            retval;

     /* to shut up purify */
     memset(&s, 0x0, sizeof(s));

     s.src_string = format_string;
     /* s.vargs = vargs; */
     va_copy(s.vargs, vargs);
     s.flavour = 'a';
     s.maxlen = (size_t)INT_MAX;

     retval = core( &s );
     if ( retval == EOF )
       {
          *ptr = NULL;
          return EOF;
       }

     *ptr = s.buffer_base;
     return retval;
}

Here is the call graph for this function:

int _xn_vfnprintf ( FILE *  file,
int  maxlen,
const char *  format_string,
va_list  vargs 
)

Definition at line 931 of file xnprintf.c.

{
     xprintf_struct s;

     s.src_string = format_string;
     s.maxlen = (size_t)maxlen;
     /* s.vargs = vargs; */
     va_copy(s.vargs, vargs);
     s.fprintf_file = file;
     s.flavour = 'f';

     return core( &s );
}

Here is the call graph for this function:

int _xn_vnprintf ( int  maxlen,
const char *  format_string,
va_list  vargs 
)

Definition at line 822 of file xnprintf.c.

{
     xprintf_struct s;

     s.src_string = format_string;
     s.maxlen = (size_t)maxlen;
     /* s.vargs = vargs; */
     va_copy(s.vargs, vargs);
     s.flavour = 'p';

     return core( &s );
}

Here is the call graph for this function:

int _xn_vsnprintf ( char *  dest_string,
int  maxlen,
const char *  format_string,
va_list  vargs 
)

Definition at line 876 of file xnprintf.c.

{
     xprintf_struct s;
     int            retval;

     if ( dest_string == NULL )
          return EOF;

     s.src_string = format_string;
     s.maxlen = (size_t)maxlen;
     /* s.vargs = vargs; */
     va_copy(s.vargs, vargs);
     s.sprintf_string = dest_string;
     s.flavour = 's';

     retval = core( &s );
     if ( retval == EOF )
          if ( maxlen > 0 )
               dest_string[0] = 0;

     return retval;
}

Here is the call graph for this function:

static int core ( xprintf_struct s  )  [static]

Definition at line 694 of file xnprintf.c.

{
     size_t len, save_len;
     char * dummy_base;

     /* basic checks */
     if ( (int)(s->maxlen) <= 0 )       /* 'int' to check against some convertion */
          return EOF;                   /* error for example if value is (int)-10 */
     s->maxlen--;      /* because initial maxlen counts final 0 */
     /* note: now 'maxlen' _can_ be zero */

     if ( s->src_string == NULL )
          s->src_string = "(null)";

     /* struct init and memory allocation */
     s->buffer_base = NULL;
     s->buffer_len = 0;
     s->real_len = 0;
     s->pseudo_len = 0;
     if ( realloc_buff(s,0) == EOF )
          return EOF;
     s->dest_string = s->buffer_base;

     /* process source string */
     for (;;)
       {
          /* up to end of source string */
          if ( *(s->src_string) == 0 )
            {
               *(s->dest_string) = 0;              /* final 0 */
               len = s->real_len + 1;
               break;
            }

          if ( dispatch(s) == EOF )
               goto free_EOF;

          /* up to end of dest string */
          if ( s->real_len >= s->maxlen )
            {
               (s->buffer_base)[s->maxlen] = 0;    /* final 0 */
               len = s->maxlen + 1;
               break;
            }
       }

     /* for (v)asnprintf */
     dummy_base = s->buffer_base;
     save_len = 0;                     /* just to avoid a compiler warning */

     /*---*/
     switch ( s->flavour )
       {
          /* (v)snprintf() */
          case 's':   memcpy( s->sprintf_string, s->buffer_base, len );
                      break;

          /* (v)nprintf() */
          case 'p':   if ( puts(s->buffer_base) == EOF )
                           goto free_EOF;
                      break;

          /* (v)fnprintf() */
          case 'f' :  if ( fwrite(s->buffer_base,1,len-1,s->fprintf_file) != len-1 )      /* -1 because we don't write the final zero */
                           goto free_EOF;
                      break;

          /* (v)as(n)printf() */
          default  :  dummy_base = (s->buffer_base) + (s->real_len);
                      save_len = s->real_len;
       }

     /*
      * process the remaining of source string to compute 'pseudo_len'. We
      * overwrite again and again, starting at 'dummy_base' because we don't
      * need the text, only char count.
      */
     while( *(s->src_string) != 0 )     /* up to end of source string */
       {
          s->real_len = 0;
          s->dest_string = dummy_base;
          if ( dispatch(s) == EOF )
               goto free_EOF;
       }

     if ( s->flavour == 'a' )      /* (v)as(n)printf    reduce buffer size */
       {
          s->buffer_base = (char *)realloc( (void *)(s->buffer_base), save_len+1 );
          if ( s->buffer_base == NULL )
               return EOF;     /* should rarely happen because we shrink the buffer */
          return s->pseudo_len;
       }

     free( s->buffer_base );
     return s->pseudo_len;

free_EOF:
     if ( s->buffer_base != NULL )
          free( s->buffer_base );
     return EOF;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dispatch ( xprintf_struct s  )  [static]

Definition at line 407 of file xnprintf.c.

{
     const char * initial_ptr;
     char   format_string[24];        /* max length may be something like  "% +-#032768.32768Ld" */
     char * format_ptr;
     int    flag_plus, flag_minus, flag_space, flag_sharp, flag_zero;
     int    width;
     int    prec;
     int   modifier;
     char   type;
     int    approx_width;
     /* most of those variables are here to rewrite the format string */

#define SRCTXT  (s->src_string)
#define DESTTXT (s->dest_string)

/* incoherent format string. Characters after the '%' will be printed with the next call */
#define INCOHERENT()         do {SRCTXT=initial_ptr; if (1) return 0;} while (0)     /* do/while to avoid */
#define INCOHERENT_TEST()    do {if(*SRCTXT==0)   INCOHERENT();} while (0)    /* a null statement  */

/* 'normal' text */
     if ( *SRCTXT != '%' )
          return usual_char( s );

/* we then have a '%' */
     SRCTXT++;
     /* don't check for end-of-string ; this is done later */

/* '%%' escape sequence */
     if ( *SRCTXT == '%' )
       {
          if ( realloc_buff(s,1) == EOF )   /* because we can have "%%%%%%%%..." */
               return EOF;
          *DESTTXT = '%';
          DESTTXT++;
          SRCTXT++;
          (s->real_len)++;
          (s->pseudo_len)++;
          return 0;
       }

/* '%' managing */
     initial_ptr = SRCTXT;   /* save current pointer in case of incorrect        */
                             /* 'decoding'. Points just after the '%' so the '%' */
                             /* won't be printed in any case, as required.       */
     /* flag */
     flag_plus  = 0;     flag_minus = 0;     flag_space = 0;
     flag_sharp = 0;     flag_zero  = 0;

     for ( /*none*/; /*none*/; SRCTXT++ )
       {
          if ( *SRCTXT == ' ' ) { flag_space = 1;  continue; }
          if ( *SRCTXT == '+' ) { flag_plus  = 1;  continue; }
          if ( *SRCTXT == '-' ) { flag_minus = 1;  continue; }
          if ( *SRCTXT == '#' ) { flag_sharp = 1;  continue; }
          if ( *SRCTXT == '0' ) { flag_zero  = 1;  continue; }
          break;
       }

     INCOHERENT_TEST();     /* here is the first test for end of string */

     /* width */
     if ( *SRCTXT == '*' )      /* width given by next argument */
       {
          SRCTXT++;
          width = va_arg( s->vargs, int );
          if ( (unsigned int)width > 0x3fffU )    /* 'unsigned' to check against negative values too */
               width = 0x3fff;
       }
     else if ( isdigit(*SRCTXT) != 0 )      /* width given as ASCII number */
       {
          width = getint( &SRCTXT );
       }
     else
          width = -1;       /* no width specified */

     INCOHERENT_TEST();

     /* .prec */
     if ( *SRCTXT == '.' )
       {
          SRCTXT++;
          if ( *SRCTXT == '*' )     /* .prec given by next argument */
            {
               prec = va_arg( s->vargs, int );
               if ( (unsigned int)prec >= 0x3fffU )    /* 'unsigned' to check against negative values too */
                    prec = 0x3fff;
            }
          else
            {       /* .prec given as ASCII number */
               if ( isdigit(*SRCTXT) == 0 )
                    INCOHERENT();
               prec = getint( &SRCTXT );
            }
          INCOHERENT_TEST();
       }
     else
          prec = -1;        /* no .prec specified */

     /* modifier */
     if ( *SRCTXT == 'L' || *SRCTXT == 'h' || *SRCTXT == 'l'
#ifdef __DOS_16BIT__
          || *SRCTXT == 'F' || *SRCTXT == 'N'
#endif
        )
       {
          modifier = *SRCTXT;
          SRCTXT++;
          if ( modifier=='l' && *SRCTXT=='l' )
            {
               SRCTXT++;
               modifier = 'L';      /* 'll' == 'L'      long long == long double */
            }                       /* only for compatibility ; not portable     */
          INCOHERENT_TEST();
       }
     else
       {
          modifier = -1;    /* no modifier specified */
       }

     /* type */
     type = *SRCTXT;
     if ( strchr("diouxXfegEGcspn",type) == NULL )
          INCOHERENT();    /* unknown type */
     SRCTXT++;

     /* rewrite format-string */
     format_string[0] = '%';
     format_ptr = &(format_string[1]);

     if ( flag_plus  != 0 )    {   *format_ptr = '+';    format_ptr++;   }
     if ( flag_minus != 0 )    {   *format_ptr = '-';    format_ptr++;   }
     if ( flag_space != 0 )    {   *format_ptr = ' ';    format_ptr++;   }
     if ( flag_sharp != 0 )    {   *format_ptr = '#';    format_ptr++;   }
     if ( flag_zero  != 0 )    {   *format_ptr = '0';    format_ptr++;   }    /* '0' *must* be the last one */

     if ( width != -1 )
       {
          sprintf( format_ptr, "%i", width );   /* itoa() may be better but not ANSI nor POSIX */
          format_ptr += strlen( format_ptr );
       }

     if ( prec != -1 )
       {
          *format_ptr = '.';
          format_ptr++;
          sprintf( format_ptr, "%i", prec );
          format_ptr += strlen( format_ptr );
       }

     if ( modifier != -1 )
       {
          *format_ptr = modifier;
          format_ptr++;
       }

     *format_ptr = type;
     format_ptr++;
     *format_ptr = 0;

     /* vague approximation of minimal length if width or prec are specified */
     approx_width = width + prec;
     if ( approx_width < 0 )    /* because  width == -1   and/or   prec == -1 */
          approx_width = 0;

     switch ( type )
       {
          /* int */
          case 'd':
          case 'i':
          case 'o':
          case 'u':
          case 'x':
          case 'X':   switch ( modifier )
                        {
                           case -1 :   return print_it( s, approx_width, format_string, va_arg(s->vargs,int) );
                           case 'l':   return print_it( s, approx_width, format_string, va_arg(s->vargs,long int) );
                           case 'h':   return print_it( s, approx_width, format_string, va_arg(s->vargs, /*short*/ int) );
                           default :   INCOHERENT();                             /* 'int' instead of 'short int' because  */
                        }                                                        /* of default promotion is 'int'         */

          /* char */
          case 'c':   if ( modifier != -1 )
                           if ( print_it(s,approx_width,format_string,va_arg(s->vargs,int)) != EOF )
                      INCOHERENT();                         /* note: because of default promotion */
                                                            /* 'int' is used instead of 'char'    */
          /* math */
          case 'e':
          case 'f':
          case 'g':
          case 'E':
          case 'G':   switch ( modifier )
                        {
                           case -1 :   /* because of default promotion, no modifier means 'l' */
                           case 'l':   return print_it( s, approx_width, format_string, va_arg(s->vargs,double) );
                           case 'L':   return print_it( s, approx_width, format_string, va_arg(s->vargs,long double) );
                           default:    INCOHERENT();
                        }

#ifdef __DOS_16BIT__
          /* string */
          case 's':   switch ( modifier )
                        {
                           case -1 :   return type_s( s, width, prec, format_string, (const char far*)va_arg(s->vargs,const char*), modifier );
                           case 'N':   return type_s( s, width, prec, format_string, (const char far*)va_arg(s->vargs,const char near*), modifier );
                           case 'F':   return type_s( s, width, prec, format_string, (const char far*)va_arg(s->vargs,const char far*), modifier );
                           default :   INCOHERENT();
                        }

          /* pointer */
          case 'p':   switch ( modifier )
                        {
                           case -1 :   return print_it( s, approx_width, format_string, va_arg(s->vargs,void*) );
                           case 'N':   return print_it( s, approx_width, format_string, va_arg(s->vargs,void near*) );
                           case 'F':   return print_it( s, approx_width, format_string, va_arg(s->vargs,void far*) );
                           default:    INCOHERENT();
                        }

          /* store */
          case 'n':   {   
                         int far * p;

                         switch ( modifier )
                           {
                              case -1 :   p = (int far*)va_arg( s->vargs, int* );
                                          break;
                              case 'N':   p = (int far*)va_arg( s->vargs, int near* );
                                          break;
                              case 'F':   p = (int far*)va_arg( s->vargs, int far* );
                                          break;
                              default :   INCOHERENT();
                           }

                         if ( p != NULL )
                           {
                              *p = s->pseudo_len;
                              return 0;
                           }
                         return EOF;
                      }

#else   /* end of ms-dos/16-bit section */
          /* string */
          case 's':   return type_s( s, width, prec, format_string, va_arg(s->vargs,const char*) );

          /* pointer */
          case 'p':   if ( modifier == -1 )
                           return print_it( s, approx_width, format_string, va_arg(s->vargs,void *) );
                      INCOHERENT();

          /* store */
          case 'n':   if ( modifier == -1 )
                        {
                           int * p;
                           p = va_arg( s->vargs, int * );
                           if ( p != NULL )
                             {
                                *p = s->pseudo_len;
                                return 0;
                             }
                           return EOF;
                        }
                      INCOHERENT();

#endif
       }  /* switch */

     INCOHERENT();  /* unknown type */

#undef INCOHERENT
#undef INCOHERENT_TEST
#undef SRCTXT
#undef DESTTXT
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int getint ( const char **  string  )  [static]

Definition at line 374 of file xnprintf.c.

{
     int i;

     i = 0;

     while ( isdigit(**string) != 0 )
       {
          i = (i*10) + (**string-'0');
          (*string)++;
       }

     if ( i<0 || i>32767 )
          i = 32767;      /* if we have i==-10 this is not because the number is */
                          /* negative ; This is because the number is biiiig     */
     return i;
}

Here is the caller graph for this function:

static int print_it ( xprintf_struct s,
size_t  approx_len,
const char *  format_string,
  ... 
) [static]

Definition at line 276 of file xnprintf.c.

{
     va_list varg;
     int     vsprintf_len;
     size_t  len;

     if ( realloc_buff(s,approx_len) == EOF )
          return EOF;

     va_start( varg, format_string );
     vsprintf_len = vsprintf( s->dest_string, format_string, varg );
     va_end( varg );

     if ( (s->buffer_base)[(s->buffer_len)-1] != 1 )     /* check for overflow */
       {
          fprintf( stderr, "ERROR in xnprintf library: overflow" );
          exit( -1 );            /* ... sorry ... what else to do ?    */
       }

     if ( vsprintf_len == EOF )    /* must be done *after* overflow-check */
          return EOF;

     s->pseudo_len  += vsprintf_len;
     len = strlen( s->dest_string );
     s->real_len    += len;
     s->dest_string += len;

     return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int realloc_buff ( xprintf_struct s,
size_t  len 
) [static]

Definition at line 216 of file xnprintf.c.

{
     char * ptr;

     if ( len + ALLOC_SECURITY_MARGIN + s->real_len   >   s->buffer_len )
       {
          len += s->real_len + ALLOC_CHUNK;
          ptr = (char *)realloc( (void *)(s->buffer_base), len );
          if ( ptr == NULL )
            {
               s->buffer_base = NULL;
               return EOF;
            }

          s->dest_string = ptr + (size_t)( s->dest_string - s->buffer_base );
          s->buffer_base = ptr;
          s->buffer_len = len;

          (s->buffer_base)[(s->buffer_len)-1] = 1;        /* overflow marquer */
       }

     return 0;
}

Here is the caller graph for this function:

static int type_s ( xprintf_struct s,
int  width,
int  prec,
const char *  format_string,
const char *  arg_string 
) [static]

Definition at line 324 of file xnprintf.c.

{
     size_t       string_len;

     if ( arg_string == NULL )
          return print_it( s, 6, "(null)", 0 );

     /* hand-made strlen() whitch stops when 'prec' is reached. */
     /* if 'prec' is -1 then it is never reached.               */
     string_len = 0;
     while ( arg_string[string_len]!=0 && (unsigned int)prec!=string_len )
          string_len++;

     if ( width != -1 )
          if ( string_len < (unsigned int)width )
               string_len = (unsigned int)width;

#ifdef __DOS_16BIT__
     switch( modifier )
       {
          case 'N':   return print_it( s, string_len, format_string, (const char near*)arg_string );
          case 'F':   return print_it( s, string_len, format_string, (const char far*)arg_string );
       }
     /* modifier == -1 */
     return print_it( s, string_len, format_string, (const char*)arg_string );
#else
     return print_it( s, string_len, format_string, arg_string );
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int usual_char ( xprintf_struct s  )  [static]

Definition at line 249 of file xnprintf.c.

{
     size_t len;

     len = strcspn( s->src_string, "%" );     /* reachs the next '%' or end of input string */
     /* note: 'len' is never 0 because the presence of '%' */
     /* or end-of-line is checked in the calling function  */

     if ( realloc_buff(s,len) == EOF )
          return EOF;

     memcpy( s->dest_string, s->src_string, len );
     s->src_string  += len;
     s->dest_string += len;
     s->real_len    += len;
     s->pseudo_len  += len;

     return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function: