/* * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. * * Permission is hereby granted to use or copy this program * for any purpose, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice.
*/
/* An sprintf implementation that understands cords. This is probably */ /* not terribly portable. It assumes an ANSI stdarg.h. It further */ /* assumes that I can make copies of va_list variables, and read */ /* arguments repeatedly by applying va_arg to the copies. This */ /* could be avoided at some performance cost. */ /* We also assume that unsigned and signed integers of various kinds */ /* have the same sizes, and can be cast back and forth. */ /* We assume that void * and char * have the same size. */ /* All this cruft is needed because we want to rely on the underlying */ /* sprintf implementation whenever possible. */
#define CONV_SPEC_LEN 50 /* Maximum length of a single */ /* conversion specification. */ #define CONV_RESULT_LEN 50 /* Maximum length of any */ /* conversion with default */ /* width and prec. */ #ifdefined(CPPCHECK) # define MACRO_BLKSTMT_BEGIN { # define MACRO_BLKSTMT_END } #else # define MACRO_BLKSTMT_BEGIN do { # define MACRO_BLKSTMT_END } while (0) #endif
#define OUT_OF_MEMORY MACRO_BLKSTMT_BEGIN \ if (CORD_oom_fn != 0) (*CORD_oom_fn)(); \
fprintf(stderr, "Out of memory\n"); \
abort(); \
MACRO_BLKSTMT_END
/* Possible non-numeric precision values. */ # define NONE -1 # define VARIABLE -2 /* Copy the conversion specification from CORD_pos into the buffer buf */ /* Return negative on error. */ /* Source initially points one past the leading %. */ /* It is left pointing at the conversion type. */ /* Assign field width and precision to *width and *prec. */ /* If width or prec is *, VARIABLE is assigned. */ /* Set *left to 1 if left adjustment flag is present. */ /* Set *long_arg to 1 if long flag ('l' or 'L') is present, or to */ /* -1 if 'h' is present, or to 2 if 'z' is present. */ staticint extract_conv_spec(CORD_pos source, char *buf, int * width, int *prec, int *left, int * long_arg)
{ int result = 0; int current_number = 0; int saw_period = 0; int saw_number = 0; int chars_so_far = 0; char current;
#ifdefined(__DJGPP__) || defined(__STRICT_ANSI__) /* vsnprintf is missing in DJGPP (v2.0.3) */ # define GC_VSNPRINTF(buf, bufsz, format, args) vsprintf(buf, format, args) #elifdefined(_MSC_VER) # ifdefined(_WIN32_WCE) /* _vsnprintf is deprecated in WinCE */ # define GC_VSNPRINTF StringCchVPrintfA # else # define GC_VSNPRINTF _vsnprintf # endif #else # define GC_VSNPRINTF vsnprintf #endif
int CORD_vsprintf(CORD * out, CORD format, va_list args)
{
CORD_ec result; int count; 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);
} elseif (long_arg == 2) {
size_t * pos_ptr = va_arg(args, size_t *);
*pos_ptr = (size_t)(unsigned)ec_len(result);
} elseif (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 = (short)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 > (unsigned)prec) { if (prec < 0) return(-1);
arg = CORD_substr(arg, 0, (unsigned)prec);
len = (unsigned)prec;
} if (width != NONE && len < (unsigned)width) { char * blanks = (char *)GC_MALLOC_ATOMIC(
(unsigned)width - len + 1);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.