Back to index

nagios-nrpe  2.13
Classes | Defines | Functions
snprintf.c File Reference
#include "../include/config.h"
#include <sys/types.h>
#include <stdarg.h>

Go to the source code of this file.

Classes

struct  pr_chunk
struct  pr_chunk_x

Defines

#define LDOUBLE   double
#define LLONG   long
#define VA_COPY(dest, src)   (dest) = (src)
#define DP_S_DEFAULT   0
#define DP_S_FLAGS   1
#define DP_S_MIN   2
#define DP_S_DOT   3
#define DP_S_MAX   4
#define DP_S_MOD   5
#define DP_S_CONV   6
#define DP_S_DONE   7
#define DP_F_MINUS   (1 << 0)
#define DP_F_PLUS   (1 << 1)
#define DP_F_SPACE   (1 << 2)
#define DP_F_NUM   (1 << 3)
#define DP_F_ZERO   (1 << 4)
#define DP_F_UP   (1 << 5)
#define DP_F_UNSIGNED   (1 << 6)
#define DP_C_CHAR   1
#define DP_C_SHORT   2
#define DP_C_LONG   3
#define DP_C_LDOUBLE   4
#define DP_C_LLONG   5
#define CNK_FMT_STR   0
#define CNK_INT   1
#define CNK_OCTAL   2
#define CNK_UINT   3
#define CNK_HEX   4
#define CNK_FLOAT   5
#define CNK_CHAR   6
#define CNK_STRING   7
#define CNK_PTR   8
#define CNK_NUM   9
#define CNK_PRCNT   10
#define char_to_int(p)   ((p)- '0')
#define MAX(p, q)   (((p) >= (q)) ? (p) : (q))
#define vsnprintf   smb_vsnprintf
#define snprintf   smb_snprintf

Functions

static size_t dopr (char *buffer, size_t maxlen, const char *format, va_list args_in)
static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, int min, int max)
static void fmtint (char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags)
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue, int min, int max, int flags)
static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
static struct pr_chunknew_chunk (void)
static int add_cnk_list_entry (struct pr_chunk_x **list, int max_num, struct pr_chunk *chunk)
static LDOUBLE abs_val (LDOUBLE value)
static LDOUBLE POW10 (int exp)
static LLONG ROUND (LDOUBLE value)
static double my_modf (double x0, double *iptr)
int smb_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
int smb_snprintf (char *str, size_t count, const char *fmt,...)
int vasprintf (char **ptr, const char *format, va_list ap)
int asprintf (char **ptr, const char *format,...)

Class Documentation

struct pr_chunk

Definition at line 223 of file snprintf.c.

Collaboration diagram for pr_chunk:
Class Members
int cflags
int flags
LDOUBLE fvalue
int len
int max
struct pr_chunk * max_star
int min
struct pr_chunk * min_star
struct pr_chunk * next
int num
void * pnum
int start
char * strvalue
int type
LLONG value
struct pr_chunk_x

Definition at line 241 of file snprintf.c.

Collaboration diagram for pr_chunk_x:
Class Members
struct pr_chunk ** chunks
int num

Define Documentation

#define char_to_int (   p)    ((p)- '0')

Definition at line 215 of file snprintf.c.

#define CNK_CHAR   6

Definition at line 209 of file snprintf.c.

#define CNK_FLOAT   5

Definition at line 208 of file snprintf.c.

#define CNK_FMT_STR   0

Definition at line 203 of file snprintf.c.

#define CNK_HEX   4

Definition at line 207 of file snprintf.c.

#define CNK_INT   1

Definition at line 204 of file snprintf.c.

#define CNK_NUM   9

Definition at line 212 of file snprintf.c.

#define CNK_OCTAL   2

Definition at line 205 of file snprintf.c.

#define CNK_PRCNT   10

Definition at line 213 of file snprintf.c.

#define CNK_PTR   8

Definition at line 211 of file snprintf.c.

#define CNK_STRING   7

Definition at line 210 of file snprintf.c.

#define CNK_UINT   3

Definition at line 206 of file snprintf.c.

#define DP_C_CHAR   1

Definition at line 196 of file snprintf.c.

#define DP_C_LDOUBLE   4

Definition at line 199 of file snprintf.c.

#define DP_C_LLONG   5

Definition at line 200 of file snprintf.c.

#define DP_C_LONG   3

Definition at line 198 of file snprintf.c.

#define DP_C_SHORT   2

Definition at line 197 of file snprintf.c.

#define DP_F_MINUS   (1 << 0)

Definition at line 187 of file snprintf.c.

#define DP_F_NUM   (1 << 3)

Definition at line 190 of file snprintf.c.

#define DP_F_PLUS   (1 << 1)

Definition at line 188 of file snprintf.c.

#define DP_F_SPACE   (1 << 2)

Definition at line 189 of file snprintf.c.

#define DP_F_UNSIGNED   (1 << 6)

Definition at line 193 of file snprintf.c.

#define DP_F_UP   (1 << 5)

Definition at line 192 of file snprintf.c.

#define DP_F_ZERO   (1 << 4)

Definition at line 191 of file snprintf.c.

#define DP_S_CONV   6

Definition at line 183 of file snprintf.c.

#define DP_S_DEFAULT   0

Definition at line 177 of file snprintf.c.

#define DP_S_DONE   7

Definition at line 184 of file snprintf.c.

#define DP_S_DOT   3

Definition at line 180 of file snprintf.c.

#define DP_S_FLAGS   1

Definition at line 178 of file snprintf.c.

#define DP_S_MAX   4

Definition at line 181 of file snprintf.c.

#define DP_S_MIN   2

Definition at line 179 of file snprintf.c.

#define DP_S_MOD   5

Definition at line 182 of file snprintf.c.

#define LDOUBLE   double

Definition at line 152 of file snprintf.c.

#define LLONG   long

Definition at line 158 of file snprintf.c.

#define MAX (   p,
 
)    (((p) >= (q)) ? (p) : (q))

Definition at line 217 of file snprintf.c.

#define snprintf   smb_snprintf

Definition at line 1218 of file snprintf.c.

#define VA_COPY (   dest,
  src 
)    (dest) = (src)

Definition at line 168 of file snprintf.c.

#define vsnprintf   smb_vsnprintf

Definition at line 1198 of file snprintf.c.


Function Documentation

static LDOUBLE abs_val ( LDOUBLE  value) [static]

Definition at line 886 of file snprintf.c.

{
       LDOUBLE result = value;

       if (value < 0)
              result = -value;
       
       return result;
}

Here is the caller graph for this function:

static int add_cnk_list_entry ( struct pr_chunk_x **  list,
int  max_num,
struct pr_chunk chunk 
) [static]

Definition at line 1140 of file snprintf.c.

                                                                 {
       struct pr_chunk_x *l;
       struct pr_chunk **c;
       int max;
       int cnum;
       int i, pos;

       if (chunk->num > max_num) {
              max = chunk->num;
       
              if (*list == NULL) {
                     l = (struct pr_chunk_x *)malloc(sizeof(struct pr_chunk_x) * max);
                     pos = 0;
              } else {
                     l = (struct pr_chunk_x *)realloc(*list, sizeof(struct pr_chunk_x) * max);
                     pos = max_num;
              }
              if (l == NULL) {
                     for (i = 0; i < max; i++) {
                            if ((*list)[i].chunks) free((*list)[i].chunks);
                     }
                     return 0;
              }
              for (i = pos; i < max; i++) {
                     l[i].chunks = NULL;
                     l[i].num = 0;
              }
       } else {
              l = *list;
              max = max_num;
       }

       i = chunk->num - 1;
       cnum = l[i].num + 1;
       if (l[i].chunks == NULL) {
              c = (struct pr_chunk **)malloc(sizeof(struct pr_chunk *) * cnum); 
       } else {
              c = (struct pr_chunk **)realloc(l[i].chunks, sizeof(struct pr_chunk *) * cnum);
       }
       if (c == NULL) {
              for (i = 0; i < max; i++) {
                     if (l[i].chunks) free(l[i].chunks);
              }
              return 0;
       }
       c[l[i].num] = chunk;
       l[i].chunks = c;
       l[i].num = cnum;

       *list = l;
       return max;
}

Here is the caller graph for this function:

int asprintf ( char **  ptr,
const char *  format,
  ... 
)

Definition at line 1247 of file snprintf.c.

{
       va_list ap;
       int ret;
       
       *ptr = NULL;
       va_start(ap, format);
       ret = vasprintf(ptr, format, ap);
       va_end(ap);

       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static size_t dopr ( char *  buffer,
size_t  maxlen,
const char *  format,
va_list  args_in 
) [static]

Definition at line 259 of file snprintf.c.

{
       char ch;
       int state;
       int pflag;
       int pnum;
       int pfirst;
       size_t currlen;
       va_list args;
       const char *base;
       struct pr_chunk *chunks = NULL;
       struct pr_chunk *cnk = NULL;
       struct pr_chunk_x *clist = NULL;
       int max_pos;
       size_t ret = -1;

       VA_COPY(args, args_in);

       state = DP_S_DEFAULT;
       pfirst = 1;
       pflag = 0;
       pnum = 0;

       max_pos = 0;
       base = format;
       ch = *format++;
       
       /* retrieve the string structure as chunks */
       while (state != DP_S_DONE) {
              if (ch == '\0') 
                     state = DP_S_DONE;

              switch(state) {
              case DP_S_DEFAULT:
                     
                     if (cnk) {
                            cnk->next = new_chunk();
                            cnk = cnk->next;
                     } else {
                            cnk = new_chunk();
                     }
                     if (!cnk) goto done;
                     if (!chunks) chunks = cnk;
                     
                     if (ch == '%') {
                            state = DP_S_FLAGS;
                            ch = *format++;
                     } else {
                            cnk->type = CNK_FMT_STR;
                            cnk->start = format - base -1;
                            while ((ch != '\0') && (ch != '%')) ch = *format++;
                            cnk->len = format - base - cnk->start -1;
                     }
                     break;
              case DP_S_FLAGS:
                     switch (ch) {
                     case '-':
                            cnk->flags |= DP_F_MINUS;
                            ch = *format++;
                            break;
                     case '+':
                            cnk->flags |= DP_F_PLUS;
                            ch = *format++;
                            break;
                     case ' ':
                            cnk->flags |= DP_F_SPACE;
                            ch = *format++;
                            break;
                     case '#':
                            cnk->flags |= DP_F_NUM;
                            ch = *format++;
                            break;
                     case '0':
                            cnk->flags |= DP_F_ZERO;
                            ch = *format++;
                            break;
                     case 'I':
                            /* internationalization not supported yet */
                            ch = *format++;
                            break;
                     default:
                            state = DP_S_MIN;
                            break;
                     }
                     break;
              case DP_S_MIN:
                     if (isdigit((unsigned char)ch)) {
                            cnk->min = 10 * cnk->min + char_to_int (ch);
                            ch = *format++;
                     } else if (ch == '$') {
                            if (!pfirst && !pflag) {
                                   /* parameters must be all positioned or none */
                                   goto done;
                            }
                            if (pfirst) {
                                   pfirst = 0;
                                   pflag = 1;
                            }
                            if (cnk->min == 0) /* what ?? */
                                   goto done;
                            cnk->num = cnk->min;
                            cnk->min = 0;
                            ch = *format++;
                     } else if (ch == '*') {
                            if (pfirst) pfirst = 0;
                            cnk->min_star = new_chunk();
                            if (!cnk->min_star) /* out of memory :-( */
                                   goto done;
                            cnk->min_star->type = CNK_INT;
                            if (pflag) {
                                   int num;
                                   ch = *format++;
                                   if (!isdigit((unsigned char)ch)) {
                                          /* parameters must be all positioned or none */
                                          goto done;
                                   }
                                   for (num = 0; isdigit((unsigned char)ch); ch = *format++) {
                                          num = 10 * num + char_to_int(ch);
                                   }
                                   cnk->min_star->num = num;
                                   if (ch != '$') /* what ?? */
                                          goto done;
                            } else {
                                   cnk->min_star->num = ++pnum;
                            }
                            max_pos = add_cnk_list_entry(&clist, max_pos, cnk->min_star);
                            if (max_pos == 0) /* out of memory :-( */
                                   goto done;
                            ch = *format++;
                            state = DP_S_DOT;
                     } else {
                            if (pfirst) pfirst = 0;
                            state = DP_S_DOT;
                     }
                     break;
              case DP_S_DOT:
                     if (ch == '.') {
                            state = DP_S_MAX;
                            ch = *format++;
                     } else { 
                            state = DP_S_MOD;
                     }
                     break;
              case DP_S_MAX:
                     if (isdigit((unsigned char)ch)) {
                            if (cnk->max < 0)
                                   cnk->max = 0;
                            cnk->max = 10 * cnk->max + char_to_int (ch);
                            ch = *format++;
                     } else if (ch == '$') {
                            if (!pfirst && !pflag) {
                                   /* parameters must be all positioned or none */
                                   goto done;
                            }
                            if (cnk->max <= 0) /* what ?? */
                                   goto done;
                            cnk->num = cnk->max;
                            cnk->max = -1;
                            ch = *format++;
                     } else if (ch == '*') {
                            cnk->max_star = new_chunk();
                            if (!cnk->max_star) /* out of memory :-( */
                                   goto done;
                            cnk->max_star->type = CNK_INT;
                            if (pflag) {
                                   int num;
                                   ch = *format++;
                                   if (!isdigit((unsigned char)ch)) {
                                          /* parameters must be all positioned or none */
                                          goto done;
                                   }
                                   for (num = 0; isdigit((unsigned char)ch); ch = *format++) {
                                          num = 10 * num + char_to_int(ch);
                                   }
                                   cnk->max_star->num = num;
                                   if (ch != '$') /* what ?? */
                                          goto done;
                            } else {
                                   cnk->max_star->num = ++pnum;
                            }
                            max_pos = add_cnk_list_entry(&clist, max_pos, cnk->max_star);
                            if (max_pos == 0) /* out of memory :-( */
                                   goto done;

                            ch = *format++;
                            state = DP_S_MOD;
                     } else {
                            state = DP_S_MOD;
                     }
                     break;
              case DP_S_MOD:
                     switch (ch) {
                     case 'h':
                            cnk->cflags = DP_C_SHORT;
                            ch = *format++;
                            if (ch == 'h') {
                                   cnk->cflags = DP_C_CHAR;
                                   ch = *format++;
                            }
                            break;
                     case 'l':
                            cnk->cflags = DP_C_LONG;
                            ch = *format++;
                            if (ch == 'l') {     /* It's a long long */
                                   cnk->cflags = DP_C_LLONG;
                                   ch = *format++;
                            }
                            break;
                     case 'L':
                            cnk->cflags = DP_C_LDOUBLE;
                            ch = *format++;
                            break;
                     default:
                            break;
                     }
                     state = DP_S_CONV;
                     break;
              case DP_S_CONV:
                     if (cnk->num == 0) cnk->num = ++pnum;
                     max_pos = add_cnk_list_entry(&clist, max_pos, cnk);
                     if (max_pos == 0) /* out of memory :-( */
                            goto done;
                     
                     switch (ch) {
                     case 'd':
                     case 'i':
                            cnk->type = CNK_INT;
                            break;
                     case 'o':
                            cnk->type = CNK_OCTAL;
                            cnk->flags |= DP_F_UNSIGNED;
                            break;
                     case 'u':
                            cnk->type = CNK_UINT;
                            cnk->flags |= DP_F_UNSIGNED;
                            break;
                     case 'X':
                            cnk->flags |= DP_F_UP;
                     case 'x':
                            cnk->type = CNK_HEX;
                            cnk->flags |= DP_F_UNSIGNED;
                            break;
                     case 'A':
                            /* hex float not supported yet */
                     case 'E':
                     case 'G':
                     case 'F':
                            cnk->flags |= DP_F_UP;
                     case 'a':
                            /* hex float not supported yet */
                     case 'e':
                     case 'f':
                     case 'g':
                            cnk->type = CNK_FLOAT;
                            break;
                     case 'c':
                            cnk->type = CNK_CHAR;
                            break;
                     case 's':
                            cnk->type = CNK_STRING;
                            break;
                     case 'p':
                            cnk->type = CNK_PTR;
                            break;
                     case 'n':
                            cnk->type = CNK_NUM;
                            break;
                     case '%':
                            cnk->type = CNK_PRCNT;
                            break;
                     default:
                            /* Unknown, bail out*/
                            goto done;
                     }
                     ch = *format++;
                     state = DP_S_DEFAULT;
                     break;
              case DP_S_DONE:
                     break;
              default:
                     /* hmm? */
                     break; /* some picky compilers need this */
              }
       }

       /* retieve the format arguments */
       for (pnum = 0; pnum < max_pos; pnum++) {
              int i;

              if (clist[pnum].num == 0) {
                     /* ignoring a parameter should not be permitted
                      * all parameters must be matched at least once
                      * BUT seem some system ignore this rule ...
                      * at least my glibc based system does --SSS
                      */
#ifdef DEBUG_SNPRINTF
                     printf("parameter at position %d not used\n", pnum+1);
#endif
                     /* eat the parameter */
                     va_arg (args, int);
                     continue;
              }
              for (i = 1; i < clist[pnum].num; i++) {
                     if (clist[pnum].chunks[0]->type != clist[pnum].chunks[i]->type) {
                            /* nooo noo no!
                             * all the references to a parameter
                             * must be of the same type
                             */
                            goto done;
                     }
              }
              cnk = clist[pnum].chunks[0];
              switch (cnk->type) {
              case CNK_INT:
                     if (cnk->cflags == DP_C_SHORT) 
                            cnk->value = va_arg (args, int);
                     else if (cnk->cflags == DP_C_LONG)
                            cnk->value = va_arg (args, long int);
                     else if (cnk->cflags == DP_C_LLONG)
                            cnk->value = va_arg (args, LLONG);
                     else
                            cnk->value = va_arg (args, int);

                     for (i = 1; i < clist[pnum].num; i++) {
                            clist[pnum].chunks[i]->value = cnk->value;
                     }
                     break;

              case CNK_OCTAL:
              case CNK_UINT:
              case CNK_HEX:
                     if (cnk->cflags == DP_C_SHORT)
                            cnk->value = va_arg (args, unsigned int);
                     else if (cnk->cflags == DP_C_LONG)
                            cnk->value = (long)va_arg (args, unsigned long int);
                     else if (cnk->cflags == DP_C_LLONG)
                            cnk->value = (LLONG)va_arg (args, unsigned LLONG);
                     else
                            cnk->value = (long)va_arg (args, unsigned int);

                     for (i = 1; i < clist[pnum].num; i++) {
                            clist[pnum].chunks[i]->value = cnk->value;
                     }
                     break;

              case CNK_FLOAT:
                     if (cnk->cflags == DP_C_LDOUBLE)
                            cnk->fvalue = va_arg (args, LDOUBLE);
                     else
                            cnk->fvalue = va_arg (args, double);

                     for (i = 1; i < clist[pnum].num; i++) {
                            clist[pnum].chunks[i]->fvalue = cnk->fvalue;
                     }
                     break;

              case CNK_CHAR:
                     cnk->value = va_arg (args, int);

                     for (i = 1; i < clist[pnum].num; i++) {
                            clist[pnum].chunks[i]->value = cnk->value;
                     }
                     break;

              case CNK_STRING:
                     cnk->strvalue = va_arg (args, char *);
                     if (!cnk->strvalue) cnk->strvalue = "(NULL)";

                     for (i = 1; i < clist[pnum].num; i++) {
                            clist[pnum].chunks[i]->strvalue = cnk->strvalue;
                     }
                     break;

              case CNK_PTR:
                     cnk->strvalue = va_arg (args, void *);
                     for (i = 1; i < clist[pnum].num; i++) {
                            clist[pnum].chunks[i]->strvalue = cnk->strvalue;
                     }
                     break;

              case CNK_NUM:
                     if (cnk->cflags == DP_C_CHAR)
                            cnk->pnum = va_arg (args, char *);
                     else if (cnk->cflags == DP_C_SHORT)
                            cnk->pnum = va_arg (args, short int *);
                     else if (cnk->cflags == DP_C_LONG)
                            cnk->pnum = va_arg (args, long int *);
                     else if (cnk->cflags == DP_C_LLONG)
                            cnk->pnum = va_arg (args, LLONG *);
                     else
                            cnk->pnum = va_arg (args, int *);

                     for (i = 1; i < clist[pnum].num; i++) {
                            clist[pnum].chunks[i]->pnum = cnk->pnum;
                     }
                     break;

              case CNK_PRCNT:
                     break;

              default:
                     /* what ?? */
                     goto done;
              }
       }
       /* print out the actual string from chunks */
       currlen = 0;
       cnk = chunks;
       while (cnk) {
              int len, min, max;

              if (cnk->min_star) min = cnk->min_star->value;
              else min = cnk->min;
              if (cnk->max_star) max = cnk->max_star->value;
              else max = cnk->max;

              switch (cnk->type) {

              case CNK_FMT_STR:
                     if (maxlen != 0 && maxlen > currlen) {
                            if (maxlen > (currlen + cnk->len)) len = cnk->len;
                            else len = maxlen - currlen;

                            memcpy(&(buffer[currlen]), &(base[cnk->start]), len);
                     }
                     currlen += cnk->len;
                            
                     break;

              case CNK_INT:
              case CNK_UINT:
                     fmtint (buffer, &currlen, maxlen, cnk->value, 10, min, max, cnk->flags);
                     break;

              case CNK_OCTAL:
                     fmtint (buffer, &currlen, maxlen, cnk->value, 8, min, max, cnk->flags);
                     break;

              case CNK_HEX:
                     fmtint (buffer, &currlen, maxlen, cnk->value, 16, min, max, cnk->flags);
                     break;

              case CNK_FLOAT:
                     fmtfp (buffer, &currlen, maxlen, cnk->fvalue, min, max, cnk->flags);
                     break;

              case CNK_CHAR:
                     dopr_outch (buffer, &currlen, maxlen, cnk->value);
                     break;

              case CNK_STRING:
                     if (max == -1) {
                            max = strlen(cnk->strvalue);
                     }
                     fmtstr (buffer, &currlen, maxlen, cnk->strvalue, cnk->flags, min, max);
                     break;

              case CNK_PTR:
                     fmtint (buffer, &currlen, maxlen, (long)(cnk->strvalue), 16, min, max, cnk->flags);
                     break;

              case CNK_NUM:
                     if (cnk->cflags == DP_C_CHAR)
                            *((char *)(cnk->pnum)) = (char)currlen;
                     else if (cnk->cflags == DP_C_SHORT)
                            *((short int *)(cnk->pnum)) = (short int)currlen;
                     else if (cnk->cflags == DP_C_LONG)
                            *((long int *)(cnk->pnum)) = (long int)currlen;
                     else if (cnk->cflags == DP_C_LLONG)
                            *((LLONG *)(cnk->pnum)) = (LLONG)currlen;
                     else
                            *((int *)(cnk->pnum)) = (int)currlen;
                     break;

              case CNK_PRCNT:
                     dopr_outch (buffer, &currlen, maxlen, '%');
                     break;

              default:
                     /* what ?? */
                     goto done;
              }
              cnk = cnk->next;
       }
       if (maxlen != 0) {
              if (currlen < maxlen - 1) 
                     buffer[currlen] = '\0';
              else if (maxlen > 0) 
                     buffer[maxlen - 1] = '\0';
       }
       ret = currlen;

done:
       while (chunks) {
              cnk = chunks->next;
              free(chunks);
              chunks = cnk;
       }
       if (clist) {
              for (pnum = 0; pnum < max_pos; pnum++) {
                     if (clist[pnum].chunks) free(clist[pnum].chunks);
              }
              free(clist);
       }
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dopr_outch ( char *  buffer,
size_t *  currlen,
size_t  maxlen,
char  c 
) [static]

Definition at line 1107 of file snprintf.c.

{
       if (*currlen < maxlen) {
              buffer[(*currlen)] = c;
       }
       (*currlen)++;
}

Here is the caller graph for this function:

static void fmtfp ( char *  buffer,
size_t *  currlen,
size_t  maxlen,
LDOUBLE  fvalue,
int  min,
int  max,
int  flags 
) [static]

Definition at line 955 of file snprintf.c.

{
       int signvalue = 0;
       double ufvalue;
       char iconvert[311];
       char fconvert[311];
       int iplace = 0;
       int fplace = 0;
       int padlen = 0; /* amount to pad */
       int zpadlen = 0; 
       int caps = 0;
       int idx;
       double intpart;
       double fracpart;
       double temp;
  
       /* 
        * AIX manpage says the default is 0, but Solaris says the default
        * is 6, and sprintf on AIX defaults to 6
        */
       if (max < 0)
              max = 6;

       ufvalue = abs_val (fvalue);

       if (fvalue < 0) {
              signvalue = '-';
       } else {
              if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
                     signvalue = '+';
              } else {
                     if (flags & DP_F_SPACE)
                            signvalue = ' ';
              }
       }

#if 0
       if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
#endif

#if 0
        if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
#endif

       /* 
        * Sorry, we only support 9 digits past the decimal because of our 
        * conversion method
        */
       if (max > 9)
              max = 9;

       /* We "cheat" by converting the fractional part to integer by
        * multiplying by a factor of 10
        */

       temp = ufvalue;
       my_modf(temp, &intpart);

       fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
       
       if (fracpart >= POW10(max)) {
              intpart++;
              fracpart -= POW10(max);
       }


       /* Convert integer part */
       do {
              temp = intpart*0.1;
              my_modf(temp, &intpart);
              idx = (int) ((temp -intpart +0.05)* 10.0);
              /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
              /* printf ("%llf, %f, %x\n", temp, intpart, idx); */
              iconvert[iplace++] =
                     (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
       } while (intpart && (iplace < 311));
       if (iplace == 311) iplace--;
       iconvert[iplace] = 0;

       /* Convert fractional part */
       if (fracpart)
       {
              do {
                     temp = fracpart*0.1;
                     my_modf(temp, &fracpart);
                     idx = (int) ((temp -fracpart +0.05)* 10.0);
                     /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
                     /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
                     fconvert[fplace++] =
                     (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
              } while(fracpart && (fplace < 311));
              if (fplace == 311) fplace--;
       }
       fconvert[fplace] = 0;
  
       /* -1 for decimal point, another -1 if we are printing a sign */
       padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 
       zpadlen = max - fplace;
       if (zpadlen < 0) zpadlen = 0;
       if (padlen < 0) 
              padlen = 0;
       if (flags & DP_F_MINUS) 
              padlen = -padlen; /* Left Justifty */
       
       if ((flags & DP_F_ZERO) && (padlen > 0)) {
              if (signvalue) {
                     dopr_outch (buffer, currlen, maxlen, signvalue);
                     --padlen;
                     signvalue = 0;
              }
              while (padlen > 0) {
                     dopr_outch (buffer, currlen, maxlen, '0');
                     --padlen;
              }
       }
       while (padlen > 0) {
              dopr_outch (buffer, currlen, maxlen, ' ');
              --padlen;
       }
       if (signvalue) 
              dopr_outch (buffer, currlen, maxlen, signvalue);
       
       while (iplace > 0) 
              dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);

#ifdef DEBUG_SNPRINTF
       printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
#endif

       /*
        * Decimal point.  This should probably use locale to find the correct
        * char to print out.
        */
       if (max > 0) {
              dopr_outch (buffer, currlen, maxlen, '.');
              
              while (zpadlen > 0) {
                     dopr_outch (buffer, currlen, maxlen, '0');
                     --zpadlen;
              }

              while (fplace > 0) 
                     dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
       }

       while (padlen < 0) {
              dopr_outch (buffer, currlen, maxlen, ' ');
              ++padlen;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fmtint ( char *  buffer,
size_t *  currlen,
size_t  maxlen,
long  value,
int  base,
int  min,
int  max,
int  flags 
) [static]

Definition at line 802 of file snprintf.c.

{
       int signvalue = 0;
       unsigned long uvalue;
       char convert[20];
       int place = 0;
       int spadlen = 0; /* amount to space pad */
       int zpadlen = 0; /* amount to zero pad */
       int caps = 0;
       
       if (max < 0)
              max = 0;
       
       uvalue = value;
       
       if(!(flags & DP_F_UNSIGNED)) {
              if( value < 0 ) {
                     signvalue = '-';
                     uvalue = -value;
              } else {
                     if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
                            signvalue = '+';
                     else if (flags & DP_F_SPACE)
                            signvalue = ' ';
              }
       }
  
       if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */

       do {
              convert[place++] =
                     (caps? "0123456789ABCDEF":"0123456789abcdef")
                     [uvalue % (unsigned)base  ];
              uvalue = (uvalue / (unsigned)base );
       } while(uvalue && (place < 20));
       if (place == 20) place--;
       convert[place] = 0;

       zpadlen = max - place;
       spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
       if (zpadlen < 0) zpadlen = 0;
       if (spadlen < 0) spadlen = 0;
       if (flags & DP_F_ZERO) {
              zpadlen = MAX(zpadlen, spadlen);
              spadlen = 0;
       }
       if (flags & DP_F_MINUS) 
              spadlen = -spadlen; /* Left Justifty */

#ifdef DEBUG_SNPRINTF
       printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
              zpadlen, spadlen, min, max, place);
#endif

       /* Spaces */
       while (spadlen > 0) {
              dopr_outch (buffer, currlen, maxlen, ' ');
              --spadlen;
       }

       /* Sign */
       if (signvalue) 
              dopr_outch (buffer, currlen, maxlen, signvalue);

       /* Zeros */
       if (zpadlen > 0) {
              while (zpadlen > 0) {
                     dopr_outch (buffer, currlen, maxlen, '0');
                     --zpadlen;
              }
       }

       /* Digits */
       while (place > 0) 
              dopr_outch (buffer, currlen, maxlen, convert[--place]);
  
       /* Left Justified spaces */
       while (spadlen < 0) {
              dopr_outch (buffer, currlen, maxlen, ' ');
              ++spadlen;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fmtstr ( char *  buffer,
size_t *  currlen,
size_t  maxlen,
char *  value,
int  flags,
int  min,
int  max 
) [static]

Definition at line 766 of file snprintf.c.

{
       int padlen, strln;     /* amount to pad */
       int cnt = 0;

#ifdef DEBUG_SNPRINTF
       printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
#endif
       if (value == 0) {
              value = "<NULL>";
       }

       for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */
       padlen = min - strln;
       if (padlen < 0) 
              padlen = 0;
       if (flags & DP_F_MINUS) 
              padlen = -padlen; /* Left Justify */
       
       while (padlen > 0) {
              dopr_outch (buffer, currlen, maxlen, ' ');
              --padlen;
       }
       while (*value && (cnt < max)) {
              dopr_outch (buffer, currlen, maxlen, *value++);
              ++cnt;
       }
       while (padlen < 0) {
              dopr_outch (buffer, currlen, maxlen, ' ');
              ++padlen;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static double my_modf ( double  x0,
double *  iptr 
) [static]

Definition at line 921 of file snprintf.c.

{
       int i;
       long l;
       double x = x0;
       double f = 1.0;

       for (i=0;i<100;i++) {
              l = (long)x;
              if (l <= (x+1) && l >= (x-1)) break;
              x *= 0.1;
              f *= 10.0;
       }

       if (i == 100) {
              /* yikes! the number is beyond what we can handle. What do we do? */
              (*iptr) = 0;
              return 0;
       }

       if (i != 0) {
              double i2;
              double ret;

              ret = my_modf(x0-l*f, &i2);
              (*iptr) = l*f + i2;
              return ret;
       } 

       (*iptr) = l;
       return x - (*iptr);
}

Here is the caller graph for this function:

static struct pr_chunk * new_chunk ( void  ) [static, read]

Definition at line 1115 of file snprintf.c.

                                        {
       struct pr_chunk *new_c = (struct pr_chunk *)malloc(sizeof(struct pr_chunk));

       if ( !new_c ) 
              return NULL;

       new_c->type = 0;
       new_c->num = 0;
       new_c->min = 0;
       new_c->min_star = NULL;
       new_c->max = -1;
       new_c->max_star = NULL;
       new_c->flags = 0;
       new_c->cflags = 0;
       new_c->start = 0;
       new_c->len = 0;
       new_c->value = 0;
       new_c->fvalue = 0;
       new_c->strvalue = NULL;
       new_c->pnum = NULL;
       new_c->next = NULL;

       return new_c;
}

Here is the caller graph for this function:

static LDOUBLE POW10 ( int  exp) [static]

Definition at line 896 of file snprintf.c.

{
       LDOUBLE result = 1;
       
       while (exp) {
              result *= 10;
              exp--;
       }
  
       return result;
}

Here is the caller graph for this function:

static LLONG ROUND ( LDOUBLE  value) [static]

Definition at line 908 of file snprintf.c.

{
       LLONG intpart;

       intpart = (LLONG)value;
       value = value - intpart;
       if (value >= 0.5) intpart++;
       
       return intpart;
}

Here is the caller graph for this function:

int smb_snprintf ( char *  str,
size_t  count,
const char *  fmt,
  ... 
)

Definition at line 1208 of file snprintf.c.

{
       size_t ret;
       va_list ap;
    
       va_start(ap, fmt);
       ret = vsnprintf(str, count, fmt, ap);
       va_end(ap);
       return ret;
}
int smb_vsnprintf ( char *  str,
size_t  count,
const char *  fmt,
va_list  args 
)

Definition at line 1194 of file snprintf.c.

{
       return dopr(str, count, fmt, args);
}

Here is the call graph for this function:

int vasprintf ( char **  ptr,
const char *  format,
va_list  ap 
)

Definition at line 1224 of file snprintf.c.

{
       int ret;
       va_list ap2;

       VA_COPY(ap2, ap);
       
       ret = vsnprintf(NULL, 0, format, ap2);
       if (ret <= 0) return ret;

       (*ptr) = (char *)malloc(ret+1);
       if (!*ptr) return -1;

       VA_COPY(ap2, ap);

       ret = vsnprintf(*ptr, ret+1, format, ap2);

       return ret;
}

Here is the caller graph for this function: