Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions
cordprnt.c File Reference
#include "cord.h"
#include "ec.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "gc.h"

Go to the source code of this file.

Defines

#define CONV_SPEC_LEN   50 /* Maximum length of a single */
#define CONV_RESULT_LEN   50 /* Maximum length of any */
#define NONE   -1
#define VARIABLE   -2

Functions

static int ec_len (CORD_ec x)
static int extract_conv_spec (CORD_pos source, char *buf, int *width, int *prec, int *left, int *long_arg)
int CORD_vsprintf (CORD *out, CORD format, va_list args)
int CORD_sprintf (CORD *out, CORD format,...)
int CORD_fprintf (FILE *f, CORD format,...)
int CORD_vfprintf (FILE *f, CORD format, va_list args)
int CORD_printf (CORD format,...)
int CORD_vprintf (CORD format, va_list args)

Define Documentation

#define CONV_RESULT_LEN   50 /* Maximum length of any */

Definition at line 34 of file cordprnt.c.

#define CONV_SPEC_LEN   50 /* Maximum length of a single */

Definition at line 32 of file cordprnt.c.

#define NONE   -1

Definition at line 45 of file cordprnt.c.

#define VARIABLE   -2

Definition at line 46 of file cordprnt.c.


Function Documentation

int CORD_fprintf ( FILE f,
CORD  format,
  ... 
)

Definition at line 346 of file cordprnt.c.

{
    va_list args;
    int result;
    CORD out;
    
    va_start(args, format);
    result = CORD_vsprintf(&out, format, args);
    va_end(args);
    if (result > 0) CORD_put(out, f);
    return(result);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int CORD_printf ( CORD  format,
  ... 
)

Definition at line 369 of file cordprnt.c.

{
    va_list args;
    int result;
    CORD out;
    
    va_start(args, format);
    result = CORD_vsprintf(&out, format, args);
    va_end(args);
    if (result > 0) CORD_put(out, stdout);
    return(result);
}

Here is the call graph for this function:

int CORD_sprintf ( CORD out,
CORD  format,
  ... 
)

Definition at line 335 of file cordprnt.c.

{
    va_list args;
    int result;
    
    va_start(args, format);
    result = CORD_vsprintf(out, format, args);
    va_end(args);
    return(result);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int CORD_vfprintf ( FILE f,
CORD  format,
va_list  args 
)

Definition at line 359 of file cordprnt.c.

{
    int result;
    CORD out;
    
    result = CORD_vsprintf(&out, format, args);
    if (result > 0) CORD_put(out, f);
    return(result);
}

Here is the call graph for this function:

int CORD_vprintf ( CORD  format,
va_list  args 
)

Definition at line 382 of file cordprnt.c.

{
    int result;
    CORD out;
    
    result = CORD_vsprintf(&out, format, args);
    if (result > 0) CORD_put(out, stdout);
    return(result);
}

Here is the call graph for this function:

int CORD_vsprintf ( CORD out,
CORD  format,
va_list  args 
)

Definition at line 161 of file cordprnt.c.

{
    CORD_ec result;
    register int count;
    register char current;
    CORD_pos pos;
    char conv_spec[CONV_SPEC_LEN + 1];
    
    CORD_ec_init(result);
    for (CORD_set_pos(pos, format, 0); CORD_pos_valid(pos); CORD_next(pos)) {
              current = CORD_pos_fetch(pos);
              if (current == '%') {
            CORD_next(pos);
            if (!CORD_pos_valid(pos)) return(-1);
            current = CORD_pos_fetch(pos);
            if (current == '%') {
                     CORD_ec_append(result, current);
            } else {
              int width, prec;
              int left_adj = 0;
              int long_arg = 0;
              CORD arg;
              size_t len;
               
                     if (extract_conv_spec(pos, conv_spec,
                                         &width, &prec,
                                         &left_adj, &long_arg) < 0) {
                         return(-1);
                     }
                     current = CORD_pos_fetch(pos);
              switch(current) {
                  case 'n':
                     /* Assign length to next arg */
                     if (long_arg == 0) {
                         int * pos_ptr;
                         pos_ptr = va_arg(args, int *);
                         *pos_ptr = ec_len(result);
                     } else if (long_arg > 0) {
                         long * pos_ptr;
                         pos_ptr = va_arg(args, long *);
                         *pos_ptr = ec_len(result);
                     } else {
                         short * pos_ptr;
                         pos_ptr = va_arg(args, short *);
                         *pos_ptr = ec_len(result);
                     }
                     goto done;
                  case 'r':
                     /* Append cord and any padding     */
                     if (width == VARIABLE) width = va_arg(args, int);
                     if (prec == VARIABLE) prec = va_arg(args, int);
                     arg = va_arg(args, CORD);
                     len = CORD_len(arg);
                     if (prec != NONE && len > prec) {
                       if (prec < 0) return(-1);
                       arg = CORD_substr(arg, 0, prec);
                       len = prec;
                     }
                     if (width != NONE && len < width) {
                       char * blanks = GC_MALLOC_ATOMIC(width-len+1);

                       memset(blanks, ' ', width-len);
                       blanks[width-len] = '\0';
                       if (left_adj) {
                         arg = CORD_cat(arg, blanks);
                       } else {
                         arg = CORD_cat(blanks, arg);
                       }
                     }
                     CORD_ec_append_cord(result, arg);
                     goto done;
                  case 'c':
                     if (width == NONE && prec == NONE) {
                         register char c;

                         c = va_arg(args, char);
                         CORD_ec_append(result, c);
                         goto done;
                     }
                     break;
                  case 's':
                      if (width == NONE && prec == NONE) {
                         char * str = va_arg(args, char *);
                         register char c;

                         while (c = *str++) {
                             CORD_ec_append(result, c);
                         }
                         goto done;
                     }
                     break;
                  default:
                      break;
              }
              /* Use standard sprintf to perform conversion */
              {
                  register char * buf;
                  va_list vsprintf_args = args;
                     /* The above does not appear to be sanctioned    */
                     /* by the ANSI C standard.                */
                  int max_size = 0;
                  int res;
                     
                  if (width == VARIABLE) width = va_arg(args, int);
                  if (prec == VARIABLE) prec = va_arg(args, int);
                  if (width != NONE) max_size = width;
                  if (prec != NONE && prec > max_size) max_size = prec;
                  max_size += CONV_RESULT_LEN;
                  if (max_size >= CORD_BUFSZ) {
                      buf = GC_MALLOC_ATOMIC(max_size + 1);
                  } else {
                      if (CORD_BUFSZ - (result[0].ec_bufptr-result[0].ec_buf)
                          < max_size) {
                          CORD_ec_flush_buf(result);
                      }
                      buf = result[0].ec_bufptr;
                  }
                  switch(current) {
                      case 'd':
                      case 'i':
                      case 'o':
                      case 'u':
                      case 'x':
                      case 'X':
                      case 'c':
                          if (long_arg <= 0) {
                            (void) va_arg(args, int);
                          } else if (long_arg > 0) {
                            (void) va_arg(args, long);
                          }
                          break;
                      case 's':
                      case 'p':
                          (void) va_arg(args, char *);
                          break;
                      case 'f':
                      case 'e':
                      case 'E':
                      case 'g':
                      case 'G':
                          (void) va_arg(args, double);
                          break;
                      default:
                          return(-1);
                  }
                  res = vsprintf(buf, conv_spec, vsprintf_args);
                  len = (size_t)res;
                  if ((char *)(GC_word)res == buf) {
                     /* old style vsprintf */
                     len = strlen(buf);
                  } else if (res < 0) {
                      return(-1);
                  }
                  if (buf != result[0].ec_bufptr) {
                      register char c;

                     while (c = *buf++) {
                         CORD_ec_append(result, c);
                      }
                  } else {
                      result[0].ec_bufptr = buf + len;
                  }
              }
              done:;
            }
        } else {
            CORD_ec_append(result, current);
        }
    }
    count = ec_len(result);
    *out = CORD_balance(CORD_ec_to_cord(result));
    return(count);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ec_len ( CORD_ec  x) [static]

Definition at line 39 of file cordprnt.c.

{
    return(CORD_len(x[0].ec_cord) + (x[0].ec_bufptr - x[0].ec_buf));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int extract_conv_spec ( CORD_pos  source,
char *  buf,
int width,
int prec,
int left,
int long_arg 
) [static]

Definition at line 56 of file cordprnt.c.

{
    register int result = 0;
    register int current_number = 0;
    register int saw_period = 0;
    register int saw_number;
    register int chars_so_far = 0;
    register char current;
    
    *width = NONE;
    buf[chars_so_far++] = '%';
    while(CORD_pos_valid(source)) {
        if (chars_so_far >= CONV_SPEC_LEN) return(-1);
        current = CORD_pos_fetch(source);
        buf[chars_so_far++] = current;
        switch(current) {
         case '*':
           saw_number = 1;
           current_number = VARIABLE;
           break;
          case '0':
            if (!saw_number) {
                /* Zero fill flag; ignore */
                break;
            } /* otherwise fall through: */
          case '1':
         case '2':
         case '3':
         case '4':
         case '5':
          case '6':
         case '7':
         case '8':
         case '9':
           saw_number = 1;
           current_number *= 10;
           current_number += current - '0';
           break;
         case '.':
           saw_period = 1;
           if(saw_number) {
               *width = current_number;
               saw_number = 0;
           }
           current_number = 0;
           break;
         case 'l':
         case 'L':
           *long_arg = 1;
           current_number = 0;
           break;
         case 'h':
           *long_arg = -1;
           current_number = 0;
           break;
         case ' ':
         case '+':
         case '#':
           current_number = 0;
           break;
         case '-':
           *left = 1;
           current_number = 0;
           break;
         case 'd':
         case 'i':
         case 'o':
         case 'u':
         case 'x':
         case 'X':
         case 'f':
         case 'e':
         case 'E':
         case 'g':
         case 'G':
         case 'c':
         case 'C':
         case 's':
         case 'S':
         case 'p':
         case 'n':
         case 'r':
           goto done;          
          default:
            return(-1);
        }
        CORD_next(source);
    }
    return(-1);
  done:
    if (saw_number) {
       if (saw_period) {
           *prec = current_number;
       } else {
           *prec = NONE;
           *width = current_number;
       }
    } else {
       *prec = NONE;
    }
    buf[chars_so_far] = '\0';
    return(result);
}

Here is the call graph for this function:

Here is the caller graph for this function: