Formatted output conversion


Detailed Description

The functions in the printf() family produce output according to a format as described below.

The functions printf() and vprintf() write output to stdout, the standard output stream; dprintf() and vdprintf() write output to the file descriptor fd; asprintf() and vasprintf() allocate a string long enough to hold the output; snprintf() and vsnprintf() write to the character string str.

The functions vprintf(), vdprintf(), vasprintf() and vsnprintf() are equivalent to the functions printf(), dprintf(), asprintf() and snprintf(), respectively, except that they are called with a va_list instead of a variable number of arguments. These functions do not call the va_end macro. Consequently, the value of ap is undefined after the call. The application should call va_end(ap) itself afterwards.

Format of the format string

The format string is composed of zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments. Each conversion specification is introduced by the character %, and ends with a conversion specifier. In between there may be (in this order) zero or more flags, an optional minimum field width, an optional precision and an optional length modifier.

The flag characters

The character % is followed by zero or more of the following flags:

The field width

An optional decimal digit string (with non-zero first digit) specifying a minimum field width. If the converted value has fewer characters than the field width, it will be padded with spaces on the left (or right, if the left-adjustment flag has been given). Instead of a decimal digit string one may write `*' to specify that the field width is given in the next argument, which must be of type int. A negative field width is taken as a `-' flag followed by a positive field width. In no case does a non-existent or small field width cause truncation of a field; if the result of a conversion is wider than the field width, the field is expanded to contain the conversion result.

The length modifier

Here, `integer conversion' stands for d, i, o, u, or x conversion.

Note however that internally, hh, h, and l are handled as long int, ll as long long int, respectively.

The conversion specifier

A character that specifies the type of conversion to be applied. The conversion specifiers and their meanings are:

Note on conformance

This printf implementation is not fully C99 or SUS compliant, though most common features are implemented in a completely self-contained way, to make integration within other applications as easy as possible.

See also:
fmt


Functions

int _lucid_vsnprintf (char *str, int size, const char *fmt, va_list ap)
 write conversion to string using va_list
int _lucid_snprintf (char *str, int size, const char *fmt,...)
 write conversion to string using variable number of arguments
int _lucid_vasprintf (char **ptr, const char *fmt, va_list ap)
 write conversion to allocated string using va_list
int _lucid_asprintf (char **ptr, const char *fmt,...)
 write conversion to allocated string using variable number of arguments
int _lucid_vdprintf (int fd, const char *fmt, va_list ap)
 write conversion to file descriptor using va_list
int _lucid_dprintf (int fd, const char *fmt,...)
 write conversion to file descriptor using variable number of arguments
int _lucid_vprintf (const char *fmt, va_list ap)
 write conversion to stdout using va_list
int _lucid_printf (const char *fmt,...)
 write conversion to stdout using variable number of arguments


Function Documentation

int _lucid_vsnprintf ( char *  str,
int  size,
const char *  fmt,
va_list  ap 
)

write conversion to string using va_list

Parameters:
[out] str buffer to store conversion
[in] size size of str
[in] fmt format string
[in] ap variable number of arguments
Returns:
number of bytes (that would have been) written
Note:
Every conversion happens in this functions. All other printf functions are just convenient wrappers.

Definition at line 178 of file vsnprintf.c.

References EMIT, __printf_t::f, __printf_t::l, __printf_t::p, PFL_ALT, PFL_BLANK, PFL_LEFT, PFL_SIGN, PFL_SIGNED, PFL_UPPER, PFL_ZERO, PFR_CHAR, PFR_INT, PFR_LLONG, PFR_LONG, PFR_MAX, PFR_MIN, PFR_SHORT, PFS_CONV, PFS_FLAGS, PFS_MOD, PFS_NORMAL, PFS_PREC, PFS_WIDTH, __printf_t::s, str_index(), str_len(), and __printf_t::w.

Referenced by _lucid_snprintf(), and _lucid_vasprintf().

00179 {
00180         /* generic counter */
00181         int i;
00182         
00183         /* generic pointer */
00184         const char *p;
00185         
00186         /* keep track of string length */
00187         int idx = 0;
00188         
00189         /* save pointer to start of current conversion */
00190         const char *ccp = fmt;
00191         
00192         /* current character in format */
00193         char c;
00194         
00195         /* current conversion data */
00196         __printf_t f;
00197         
00198         /* arguments */
00199         union {
00200                 /* signed argument */
00201                 signed long long int d;
00202                 
00203                 /* unsigned argument */
00204                 unsigned long long int u;
00205                 
00206                 /* float argument */
00207                 double f;
00208                 
00209                 /* character argument */
00210                 int c;
00211                 
00212                 /* string argument */
00213                 const char *s;
00214                 
00215                 /* pointer argument */
00216                 void *p;
00217                 
00218                 /* number argument */
00219                 int *n;
00220         } arg;
00221         
00222         /* base used for integer conversions */
00223         int base;
00224         
00225         /* number of consumed bytes in conversions */
00226         int len;
00227         
00228         /* don't consume original ap */
00229         va_list ap;
00230         va_copy(ap, _ap);
00231         
00232         /* initialize conversion data */
00233         f.f = 0;
00234         f.l = PFR_INT;
00235         f.p = -1;
00236         f.s = PFS_NORMAL;
00237         f.w = 0;
00238         
00239         while ((c = *fmt++)) {
00240                 switch (f.s) {
00241                 case PFS_NORMAL:
00242                         if (c == '%') {
00243                                 f.f = 0;
00244                                 f.l = PFR_INT;
00245                                 f.p = -1;
00246                                 f.s = PFS_FLAGS;
00247                                 f.w = 0;
00248                                 ccp = &c;
00249                         }
00250                         
00251                         else
00252                                 EMIT(c)
00253                         
00254                         break;
00255                 
00256                 case PFS_FLAGS:
00257                         switch (c) {
00258                         case '#':
00259                                 f.f |= PFL_ALT;
00260                                 break;
00261                         
00262                         case '0':
00263                                 f.f |= PFL_ZERO;
00264                                 break;
00265                         
00266                         case '-':
00267                                 f.f &= ~PFL_ZERO; /* left overrides zero */
00268                                 f.f |=  PFL_LEFT;
00269                                 break;
00270                         
00271                         case ' ':
00272                                 f.f |= PFL_BLANK;
00273                                 break;
00274                         
00275                         case '+':
00276                                 f.f &= ~PFL_BLANK; /* sign overrides blank */
00277                                 f.f |=  PFL_SIGN;
00278                                 break;
00279                         
00280                         default:
00281                                 f.s = PFS_WIDTH;
00282                                 fmt--;
00283                                 break;
00284                         }
00285                         
00286                         break;
00287                 
00288                 case PFS_WIDTH:
00289                         if (c == '-') {
00290                                         f.f &= PFL_ZERO; /* left overrides zero */
00291                                         f.f |= PFL_LEFT;
00292                         }
00293                         
00294                         else if (c >= '0' && c <= '9')
00295                                 f.w = f.w * 10  + (c - '0');
00296                         
00297                         else if (c == '*') {
00298                                 f.w = va_arg(ap, int);
00299                                 
00300                                 if (f.w < 0) {
00301                                         f.w = -f.w;
00302                                         f.f &= PFL_ZERO; /* left overrides zero */
00303                                         f.f |= PFL_LEFT;
00304                                 }
00305                         }
00306                         
00307                         else if (c == '.') {
00308                                 f.p = 0;
00309                                 f.s = PFS_PREC;
00310                         }
00311                         
00312                         else {
00313                                 f.s = PFS_MOD;
00314                                 fmt--;
00315                         }
00316                         
00317                         break;
00318                 
00319                 case PFS_PREC:
00320                         if (c >= '0' && c <= '9')
00321                                 f.p = f.p * 10  + (c - '0');
00322                         
00323                         else if (c == '*') {
00324                                 f.p = va_arg(ap, int);
00325                                 
00326                                 if (f.p < 0)
00327                                         f.p = 0;
00328                         }
00329                         
00330                         else {
00331                                 f.s = PFS_MOD;
00332                                 fmt--;
00333                         }
00334                         
00335                         break;
00336                 
00337                 case PFS_MOD:
00338                         switch (c) {
00339                         case 'h':
00340                                 f.l--;
00341                                 break;
00342                         
00343                         case 'l':
00344                                 f.l++;
00345                                 break;
00346                         
00347                         default:
00348                                 f.s = PFS_CONV;
00349                                 fmt--;
00350                                 break;
00351                         }
00352                         
00353                         break;
00354                 
00355                 case PFS_CONV:
00356                         f.s = PFS_NORMAL;
00357                         
00358                         if (f.l > PFR_MAX)
00359                                 f.l = PFR_MAX;
00360                         
00361                         if (f.l < PFR_MIN)
00362                                 f.l = PFR_MIN;
00363                         
00364                         switch (c) {
00365                         case 'P':
00366                                 f.f |= PFL_UPPER;
00367                         
00368                         case 'p':
00369                                 base = 16;
00370                                 f.p  = (8 * sizeof(void *) + 3)/4;
00371                                 f.f |= PFL_ALT;
00372                                 
00373                                 arg.u = (unsigned long long int) (unsigned long int) va_arg(ap, void *);
00374                                 
00375                                 goto is_integer;
00376                         
00377                         case 'd':
00378                         case 'i': /* signed conversion */
00379                                 base = 10;
00380                                 f.f |= PFL_SIGNED;
00381                                 
00382                                 switch (f.l) {
00383                                 case PFR_CHAR:
00384                                         arg.d = (signed char) va_arg(ap, signed int);
00385                                         break;
00386                                 
00387                                 case PFR_SHORT:
00388                                         arg.d = (signed short int) va_arg(ap, signed int);
00389                                         break;
00390                                 
00391                                 case PFR_INT:
00392                                         arg.d = (signed int) va_arg(ap, signed int);
00393                                         break;
00394                                 
00395                                 case PFR_LONG:
00396                                         arg.d = (signed long int) va_arg(ap, signed long int);
00397                                         break;
00398                                 
00399                                 case PFR_LLONG:
00400                                         arg.d = (signed long long int) va_arg(ap, signed long long int);
00401                                         break;
00402                                 
00403                                 default:
00404                                         arg.d = (signed long long int) va_arg(ap, signed int);
00405                                         break;
00406                                 }
00407                                 
00408                                 arg.u = (unsigned long long int) arg.d;
00409                                 
00410                                 goto is_integer;
00411                         
00412                         case 'o':
00413                                 base = 8;
00414                                 goto is_unsigned;
00415                                 
00416                         case 'u':
00417                                 base = 10;
00418                                 goto is_unsigned;
00419                                 
00420                         case 'X':
00421                                 f.f |= PFL_UPPER;
00422                         
00423                         case 'x':
00424                                 base = 16;
00425                                 goto is_unsigned;
00426                                 
00427                         is_unsigned:
00428                                 switch (f.l) {
00429                                 case PFR_CHAR:
00430                                         arg.u = (unsigned char) va_arg(ap, unsigned int);
00431                                         break;
00432                                 
00433                                 case PFR_SHORT:
00434                                         arg.u = (unsigned short int) va_arg(ap, unsigned int);
00435                                         break;
00436                                 
00437                                 case PFR_INT:
00438                                         arg.u = (unsigned int) va_arg(ap, unsigned int);
00439                                         break;
00440                                 
00441                                 case PFR_LONG:
00442                                         arg.u = (unsigned long int) va_arg(ap, unsigned long int);
00443                                         break;
00444                                 
00445                                 case PFR_LLONG:
00446                                         arg.u = (unsigned long long int) va_arg(ap, unsigned long long int);
00447                                         break;
00448                                 
00449                                 default:
00450                                         arg.u = (unsigned long long int) va_arg(ap, unsigned int);
00451                                         break;
00452                                 }
00453                                 
00454                         is_integer:
00455                                 len = __printf_int(str, size, arg.u, base, f);
00456                                 
00457                                 str += len;
00458                                 idx += len;
00459                                 break;
00460                         
00461                         case 'c': /* character conversion */
00462                                 arg.c = (char) va_arg(ap, int);
00463                                 EMIT(arg.c)
00464                                 break;
00465                         
00466                         case 's': /* string conversion */
00467                                 arg.s = va_arg(ap, const char *);
00468                                 arg.s = arg.s ? arg.s : "(null)";
00469                                 len   = str_len(arg.s);
00470                                 
00471                         is_string:
00472                                 if (f.p != -1 && len > f.p)
00473                                         len = f.p;
00474                                 
00475                                 while (f.w-- > len && !(f.f & PFL_LEFT)) {
00476                                         if (f.f & PFL_ZERO)
00477                                                 EMIT('0')
00478                                         else
00479                                                 EMIT(' ')
00480                                 }
00481                                 
00482                                 for (i = len; i; i--)
00483                                         EMIT(*arg.s++)
00484                                 
00485                                 while (f.w-- > len && (f.f & PFL_LEFT))
00486                                         EMIT(' ')
00487                                 
00488                                 break;
00489                                 
00490                         case 'n':
00491                                 arg.n  = va_arg(ap, int *);
00492                                 *arg.n = idx;
00493                                 
00494                                 break;
00495                         
00496                         case '%':
00497                                 EMIT(c)
00498                                 break;
00499                         
00500                         default:
00501                                 /* no padding for unknown conversion */
00502                                 f.w =  0;
00503                                 f.p = -1;
00504                                 
00505                                 arg.s = ccp;
00506                                 len   = str_len(arg.s);
00507                                 fmt   = ccp + len;
00508                                 
00509                                 p = str_index(arg.s + 1, '%', len - 1);
00510                                 
00511                                 if (p != 0) {
00512                                         len = p - arg.s - 1;
00513                                         fmt = p - 1;
00514                                 }
00515                                 
00516                                 goto is_string;
00517                         }
00518                         
00519                         break;
00520                 }
00521         }
00522         
00523         va_end(ap);
00524         
00525         return idx;
00526 }

int _lucid_snprintf ( char *  str,
int  size,
const char *  fmt,
  ... 
)

write conversion to string using variable number of arguments

Parameters:
[out] str buffer to store conversion
[in] size size of str
[in] fmt format string
[in] ... variable number of arguments
Returns:
number of bytes (that would have been) written

Definition at line 20 of file snprintf.c.

References _lucid_vsnprintf().

00021 {
00022         va_list ap;
00023         va_start(ap, fmt);
00024         
00025         return _lucid_vsnprintf(str, size, fmt, ap);
00026 }

int _lucid_vasprintf ( char **  ptr,
const char *  fmt,
va_list  ap 
)

write conversion to allocated string using va_list

Parameters:
[out] ptr pointer to string to store conversion
[in] fmt format string
[in] ap variable number of arguments
Returns:
number of bytes (that would have been) written
See also:
malloc(3)

free(3)

Definition at line 22 of file vasprintf.c.

References _lucid_vsnprintf().

Referenced by _lucid_asprintf(), _lucid_vdprintf(), exec_fork(), exec_fork_background(), exec_fork_pipe(), exec_replace(), log_internal(), and stralloc_catf().

00023 {
00024         va_list ap2;
00025         int len;
00026         char *buf;
00027         
00028         /* don't consume the original ap, we'll need it again */
00029         va_copy(ap2, ap);
00030         
00031         /* get required size */
00032         len = _lucid_vsnprintf(0, 0, fmt, ap2);
00033         
00034         va_end(ap2);
00035         
00036         /* if size is 0, no buffer is allocated
00037         ** just set *ptr to NULL and return size */
00038         if (len > 0) {
00039                 if (!(buf = calloc(len + 1, sizeof(char))))
00040                         return -1;
00041                 
00042                 _lucid_vsnprintf(buf, len, fmt, ap);
00043                 
00044                 *ptr = buf;
00045         }
00046         
00047         return len;
00048 }

int _lucid_asprintf ( char **  ptr,
const char *  fmt,
  ... 
)

write conversion to allocated string using variable number of arguments

Parameters:
[out] ptr pointer to string to store conversion
[in] fmt format string
[in] ... variable number of arguments
Returns:
number of bytes (that would have been) written
See also:
malloc(3)

free(3)

Definition at line 20 of file asprintf.c.

References _lucid_vasprintf().

Referenced by addr_to_str(), log_internal(), runlink(), and str_path_concat().

00021 {
00022         va_list ap;
00023         va_start(ap, fmt);
00024         
00025         return _lucid_vasprintf(ptr, fmt, ap);
00026 }

int _lucid_vdprintf ( int  fd,
const char *  fmt,
va_list  ap 
)

write conversion to file descriptor using va_list

Parameters:
[in] fd open file descriptor
[in] fmt format string
[in] ap variable number of arguments
Returns:
number of bytes (that would have been) written

Definition at line 23 of file vdprintf.c.

References _lucid_vasprintf().

Referenced by _lucid_dprintf(), and _lucid_vprintf().

00024 {
00025         char *buf;
00026         int buflen, len;
00027         
00028         buflen = _lucid_vasprintf(&buf, fmt, ap);
00029         len = write(fd, buf, buflen);
00030         free(buf);
00031         
00032         return len;
00033 }

int _lucid_dprintf ( int  fd,
const char *  fmt,
  ... 
)

write conversion to file descriptor using variable number of arguments

Parameters:
[in] fd open file descriptor
[in] fmt format string
[in] ... variable number of arguments
Returns:
number of bytes (that would have been) written

Definition at line 20 of file dprintf.c.

References _lucid_vdprintf().

00021 {
00022         va_list ap;
00023         va_start(ap, fmt);
00024         
00025         return _lucid_vdprintf(fd, fmt, ap);
00026 }

int _lucid_vprintf ( const char *  fmt,
va_list  ap 
)

write conversion to stdout using va_list

Parameters:
[in] fmt format string
[in] ap variable number of arguments
Returns:
number of bytes (that would have been) written

Definition at line 20 of file vprintf.c.

References _lucid_vdprintf().

Referenced by _lucid_printf().

00021 {
00022         return _lucid_vdprintf(1, fmt, ap);
00023 }

int _lucid_printf ( const char *  fmt,
  ... 
)

write conversion to stdout using variable number of arguments

Parameters:
[in] fmt format string
[in] ... variable number of arguments
Returns:
number of bytes (that would have been) written

Definition at line 20 of file printf.c.

References _lucid_vprintf().

00021 {
00022         va_list ap;
00023         va_start(ap, fmt);
00024         
00025         return _lucid_vprintf(fmt, ap);
00026 }


Generated on Sun Dec 3 17:46:16 2006 for lucid by  doxygen 1.5.1