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 179 of file vsnprintf.c.

References EMIT, __printf_t::f, __printf_t::l, mem_set(), __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_chr(), str_len(), and __printf_t::w.

Referenced by _lucid_snprintf(), and _lucid_vasprintf().

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

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 19 of file snprintf.c.

References _lucid_vsnprintf().

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

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 20 of file vasprintf.c.

References _lucid_vsnprintf(), and mem_alloc().

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

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

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 19 of file asprintf.c.

References _lucid_vasprintf().

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

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

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 22 of file vdprintf.c.

References _lucid_vasprintf(), and mem_free().

Referenced by _lucid_dprintf(), and _lucid_vprintf().

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

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 19 of file dprintf.c.

References _lucid_vdprintf().

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

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 19 of file vprintf.c.

References _lucid_vdprintf().

Referenced by _lucid_printf().

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

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 19 of file printf.c.

References _lucid_vprintf().

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


Generated on Tue Jun 19 20:38:45 2007 for lucid by  doxygen 1.5.2