diff --git a/.gitignore b/.gitignore index 0e014a5..642756c 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ libpipecolors.so libpipecolors.la libpipecolors.lo libpipecolors.pc +tests/ test/ timestamp # Ignore backup files diff --git a/Makefile.am b/Makefile.am index b500cd8..842f0ff 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,3 +31,16 @@ MAINTAINERCLEANFILES = \ -rf m4 \ configure \ Makefile.in + +install-man: install-man3 install-man7 install-man-gzip +uninstall-man: uninstall-man3 uninstall-man7 uninstall-man-gzip + +install-man-gzip: + test -f $(mandir)/man3/pcprintf.3 && gzip -qf /usr/share/man/man3/pcprintf.3 + test -f $(mandir)/man7/libpipecolors.7 && gzip -qf /usr/share/man/man7/libpipecolors.7 + test -f $(mandir)/man3/pcprintf.3.gz && ln -sf /usr/share/man/man3/pcprintf.3.gz /usr/share/man/man3/pcsprintf.3.gz + +uninstall-man-gzip: + test -f $(mandir)/man3/pcprintf.3.gz && rm -f /usr/share/man/man3/pcprintf.3.gz + test -h $(mandir)/man3/pcsprintf.3.gz && rm -f /usr/share/man/man3/pcsprintf.3.gz + test -f $(mandir)/man7/libpipecolors.7.gz && rm -f /usr/share/man/man7/libpipecolors.7.gz diff --git a/configure.ac b/configure.ac index f118746..0132f6a 100644 --- a/configure.ac +++ b/configure.ac @@ -34,7 +34,6 @@ AM_SILENT_RULES AC_GNU_SOURCE AC_CANONICAL_HOST AC_PROG_INSTALL -AC_PROG_MAKE_SET AC_PROG_CXXCPP AM_PROG_AR AC_PROG_LIBTOOL @@ -43,8 +42,7 @@ AC_PROG_LN_S LT_INIT AC_LANG_CPLUSPLUS AC_PREFIX_DEFAULT([/usr]) -#AC_CHECK_LIB([pipecolors], [cprintf]) -AC_CHECK_LIB([boost_regex], [main]) + # Checks for programs. AC_CONFIG_MACRO_DIR([m4]) @@ -55,9 +53,6 @@ gcc_major_vers=`echo ${gcc_full_vers} | cut -f1 -d.` gcc_minor_vers=`echo ${gcc_full_vers} | cut -f2 -d.` gcc_micro_vers=`echo ${gcc_full_vers} | cut -f3 -d.` -# Checks for functions - -#AC_CHECK_CXX_ARGUMENT([-std=c++11], [], [AC_MSG_ERROR([C++11 support is required.])]) AC_MSG_CHECKING([${CXX-c++} version]) if test "${gcc_minor_vers}" -lt 9; then @@ -65,13 +60,11 @@ if test "${gcc_minor_vers}" -lt 9; then else AC_MSG_RESULT([${gcc_full_vers} ... acceptable]) fi -#AC_HEADER_STDC - -# Checks for libraries. -AC_CHECK_HEADERS([stdarg.h stdlib.h unistd.h string iostream map],[],[AC_MSG_ERROR([We couldn't find some of the headers.])]) +AC_CHECK_HEADERS([stdarg.h stdlib.h unistd.h string iostream map],[],[AC_MSG_ERROR([We couldn't find one or more of the required headers.])]) AC_CHECK_HEADER([boost/regex.hpp],[],[AC_MSG_ERROR([Please install the libboost-regex header library.])]) -AC_CHECK_FUNCS([vprintf vsprintf vasprintf printf]) +AC_CHECK_LIB([boost_regex], [main]) +AC_CHECK_FUNCS([vasprintf]) AC_CHECK_TYPE([size_t]) AC_CHECK_TYPES([std::string], [], [], [[ diff --git a/examples/test.c b/examples/test.c deleted file mode 100644 index 914e7e0..0000000 --- a/examples/test.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include -#include - -main() { - int a,b; - const char* str = "|0101|0202|0303|0404|0505|0606|0707|0808|0909|1010|1111|1212|1313|1414|1515|07"; - const char* name = "|01P|02i|03p|04e|05c|06ol|07o|08r|09s |10l|11i|12b|13r|14a|15r|14y |130|12.|111|07"; - - a = pcprintf("\n%s\n\n", name); - b = pcprintf("%s\n", str); - - -} diff --git a/examples/test.cpp b/examples/test.cpp deleted file mode 100644 index 0d1cec4..0000000 --- a/examples/test.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include -#include - -using namespace pipecolors; - -int main(void) { - - const char* str = "|0101|0202|0303|0404|0505|0606|0707|0808|0909|1010|1111|1212|1313|1414|1515|07"; - const char* name = "|01P|02i|03p|04e|05c|06ol|07o|08r|09s |10l|11i|12b|13r|14a|15r|14y |130|12.|111|07"; - - pcprintf("\n%s\n\n", name); - pcprintf("%s\n", str); - int size = pcprintf("%s", str); - std::cout << std::endl << "Size : " << size << std::endl; - return 0; - -} diff --git a/libpipecolors.cpp b/libpipecolors.cpp index 0b749d6..5b785ca 100644 --- a/libpipecolors.cpp +++ b/libpipecolors.cpp @@ -26,8 +26,6 @@ #include #include "pipecolors.h" -using namespace boost; - namespace pipecolors { std::map colors; @@ -67,12 +65,50 @@ namespace pipecolors { return isatty(fileno(stdout)); } + std::string replace_colors( std::string s) { + + using namespace boost; + + std::size_t index; + + regex re( "(\\|\\d\\d)" ); + match_results match; + match_flag_type flags = boost::match_default; + + std::string::const_iterator start, end; + start = s.begin(); + end = s.end(); + + colors = getColors(); + + while(regex_search(start, end, match, re, flags)) + { + if(colors[match[0]].empty()) continue; + + + //while ((index = s.find(match[0])) != std::string::npos) + //{ + if(has_colors()) { + s.replace(s.find(match[0]), match[0].length(), colors[match[0]]); + } else { + s.erase(s.find(match[0]), match[0].length()); + } + //} + + start = match[0].second; + // update flags: + flags |= boost::match_prev_avail; + flags |= boost::match_not_bob; + } + return(s); + } + int pcprintf( const char * fmt, ...) { char * buffer; va_list args; int ret; - colors = getColors(); + va_start(args, fmt); ret = vasprintf(&buffer, fmt, args); va_end(args); @@ -81,32 +117,12 @@ namespace pipecolors { exit(EXIT_FAILURE); } - - std::string s(buffer), result(buffer); + std::string s(buffer); free(buffer); - regex re( "(\\|\\d\\d)" ); - std::size_t index; - std::string::const_iterator start, end; - start = s.begin(); - end = s.end(); - match_results match; - match_flag_type flags = boost::match_default; - while(regex_search(start, end, match, re, flags)) - { - while ((index = s.find(match[0])) != std::string::npos) - { - s.replace(index, match[0].length(), colors[match[0]]); - } - start = match[0].second; - // update flags: - flags |= boost::match_prev_avail; - flags |= boost::match_not_bob; - } - std::cout << s; + std::cout << replace_colors(s); return(ret); } - } // namespace diff --git a/pcprintf.3 b/pcprintf.3 index 17f9cb4..8736fb9 100644 --- a/pcprintf.3 +++ b/pcprintf.3 @@ -1,10 +1,4 @@ -.\" Copyright (c) 1999 Andries Brouwer (aeb@cwi.nl) -.\" -.\" Earlier versions of this page influenced the present text. -.\" It was derived from a Berkeley page with version -.\" @(#)printf.3 6.14 (Berkeley) 7/30/91 -.\" converted for Linux by faith@cs.unc.edu, updated by -.\" Helmut.Geyer@iwr.uni-heidelberg.de, agulbra@troll.no and Bruno Haible. +.\" Copyright (c) 2015 Eric Wheeler (eric@rewiv.com) .\" .\" %%%LICENSE_START(GPLv2+_DOC_FULL) .\" This is free documentation; you can redistribute it and/or @@ -27,1068 +21,105 @@ .\" . .\" %%%LICENSE_END .\" -.\" 1999-11-25 aeb - Rewritten, using SUSv2 and C99. -.\" 2000-07-26 jsm28@hermes.cam.ac.uk - three small fixes -.\" 2000-10-16 jsm28@hermes.cam.ac.uk - more fixes +.\" 2015-07-06 eric@rewiv.com \- initial program .\" -.TH CPPRINTF 3 2015-07-01 "GNU" "Linux Programmer's Manual" +.TH pcprintf 3 2015-07-06 "LIBPIPECOLORS" "Using pcprintf to print colors" .SH NAME -cpprintf, -cpsprintf \- formatted output conversion +pcprintf, +pcsprintf \- convert pipecode (|10) to ansi colors .SH SYNOPSIS .B #include .sp -.BI "int cpprintf(const char *" format ", ...);" +.BI "int pcprintf(const char *" format ", ...);" .br -.BI "int cpsprintf(char *" str ", const char *" format ", ...);" +.BI "int pcsprintf(char *" str ", const char *" format ", ...);" .sp .in -4n .ad .SH DESCRIPTION The functions in the -.BR printf () +.BR pcprintf () family produce output according to a .I format as described below. -The functions -.BR printf () -and -.BR vprintf () -write output to -.IR stdout , -the standard output stream; -.BR fprintf () -and -.BR vfprintf () -write output to the given output -.IR stream ; -.BR sprintf (), -.BR snprintf (), -.BR vsprintf () -and -.BR vsnprintf () -write to the character string -.IR str . .PP -The functions -.BR snprintf () -and -.BR vsnprintf () -write at most -.I size -bytes (including the terminating null byte (\(aq\e0\(aq)) to -.IR str . -.PP -The functions -.BR vprintf (), -.BR vfprintf (), -.BR vsprintf (), -.BR vsnprintf () -are equivalent to the functions -.BR printf (), -.BR fprintf (), -.BR sprintf (), -.BR snprintf (), -respectively, except that they are called with a -.I va_list -instead of a variable number of arguments. -These functions do not call the -.I va_end -macro. -Because they invoke the -.I va_arg -macro, the value of -.I ap -is undefined after the call. -See -.BR stdarg (3). -.PP -These eight functions write the output under the control of a -.I format -string that specifies how subsequent arguments (or arguments accessed via -the variable-length argument facilities of -.BR stdarg (3)) -are converted for output. +.SS pcprintf () +This function parses input exactly like +.BR printf (3) +the only difference is that it converts old renegade bbs style pipecodes (|10) to ansi sequences. + +See NOTES. +.PP +.SS pcsprintf () +This function parses input exactly like +.BR sprintf (3) +the only difference is that it converts old renegade bbs style pipecodes (|10) to ansi sequences. -C99 and POSIX.1-2001 specify that the results are undefined if a call to -.BR sprintf (), -.BR snprintf (), -.BR vsprintf (), -or -.BR vsnprintf () -would cause copying to take place between objects that overlap -(e.g., if the target string array and one of the supplied input arguments -refer to the same buffer). See NOTES. .SS Return value Upon successful return, these functions return the number of characters -printed (excluding the null byte used to end output to strings). - -The functions -.BR snprintf () -and -.BR vsnprintf () -do not write more than -.I size -bytes (including the terminating null byte (\(aq\e0\(aq)). -If the output was truncated due to this limit, then the return value -is the number of characters (excluding the terminating null byte) -which would have been written to the final string if enough space -had been available. -Thus, a return value of -.I size -or more means that the output was truncated. -(See also below under NOTES.) +printed (excluding the null byte used to end output to strings and +.I including +the ansi color code e.g. \fBx1b[0;39m\fR). If an output error is encountered, a negative value is returned. .SS Format of the format string -The format string is a character string, beginning and ending -in its initial shift state, if any. -The format string is composed of zero or more directives: ordinary -characters (not -.BR % ), -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 -.BR % , -and ends with a -.IR "conversion specifier" . -In between there may be (in this order) zero or more -.IR flags , -an optional minimum -.IR "field width" , -an optional -.I precision -and an optional -.IR "length modifier" . -The arguments must correspond properly (after type promotion) with the -conversion specifier. -By default, the arguments are used in the order -given, where each \(aq*\(aq and each conversion specifier asks for the next -argument (and it is an error if insufficiently many arguments are given). -One can also specify explicitly which argument is taken, -at each place where an argument is required, by writing "%m$" instead -of \(aq%\(aq and "*m$" instead of \(aq*\(aq, -where the decimal integer m denotes -the position in the argument list of the desired argument, indexed starting -from 1. -Thus, -.in +4n -.nf +See +.BR printf (3) -printf("%*d", width, num); - -.fi -.in -and -.in +4n -.nf - -printf("%2$*1$d", width, num); - -.fi -.in -are equivalent. -The second style allows repeated references to the -same argument. -The C99 standard does not include the style using \(aq$\(aq, -which comes from the Single UNIX Specification. -If the style using -\(aq$\(aq is used, it must be used throughout for all conversions taking an -argument and all width and precision arguments, but it may be mixed -with "%%" formats which do not consume an argument. -There may be no -gaps in the numbers of arguments specified using \(aq$\(aq; for example, if -arguments 1 and 3 are specified, argument 2 must also be specified -somewhere in the format string. - -For some numeric conversions a radix character ("decimal point") or -thousands' grouping character is used. -The actual character used -depends on the -.B LC_NUMERIC -part of the locale. -The POSIX locale -uses \(aq.\(aq as radix character, and does not have a grouping character. -Thus, -.in +4n -.nf - - printf("%\(aq.2f", 1234567.89); - -.fi -.in -results in "1234567.89" in the POSIX locale, in "1234567,89" in the -nl_NL locale, and in "1.234.567,89" in the da_DK locale. .SS The flag characters -The character % is followed by zero or more of the following flags: -.TP -.B # -The value should be converted to an "alternate form". -For -.B o -conversions, the first character of the output string is made zero -(by prefixing a 0 if it was not zero already). -For -.B x -and -.B X -conversions, a nonzero result has the string "0x" (or "0X" for -.B X -conversions) prepended to it. -For -.BR a , -.BR A , -.BR e , -.BR E , -.BR f , -.BR F , -.BR g , -and -.B G -conversions, the result will always contain a decimal point, even if no -digits follow it (normally, a decimal point appears in the results of those -conversions only if a digit follows). -For -.B g -and -.B G -conversions, trailing zeros are not removed from the result as they would -otherwise be. -For other conversions, the result is undefined. -.TP -.B \&0 -The value should be zero padded. -For -.BR d , -.BR i , -.BR o , -.BR u , -.BR x , -.BR X , -.BR a , -.BR A , -.BR e , -.BR E , -.BR f , -.BR F , -.BR g , -and -.B G -conversions, the converted value is padded on the left with zeros rather -than blanks. -If the -.B \&0 -and -.B \- -flags both appear, the -.B \&0 -flag is ignored. -If a precision is given with a numeric conversion -.RB ( d , -.BR i , -.BR o , -.BR u , -.BR x , -and -.BR X ), -the -.B \&0 -flag is ignored. -For other conversions, the behavior is undefined. -.TP -.B \- -The converted value is to be left adjusted on the field boundary. -(The default is right justification.) -The converted value is padded on the right with blanks, rather -than on the left with blanks or zeros. -A -.B \- -overrides a -.B \&0 -if both are given. -.TP -.B \(aq \(aq -(a space) A blank should be left before a positive number -(or empty string) produced by a signed conversion. -.TP -.B + -A sign (+ or \-) should always be placed before a number produced by a signed -conversion. -By default a sign is used only for negative numbers. -A -.B + -overrides a space if both are used. -.PP -The five flag characters above are defined in the C99 standard. -The Single UNIX Specification specifies one further flag character. -.TP -.B \(aq -For decimal conversion -.RB ( i , -.BR d , -.BR u , -.BR f , -.BR F , -.BR g , -.BR G ) -the output is to be grouped with thousands' grouping characters -if the locale information indicates any. -Note that many versions of -.BR gcc (1) -cannot parse this option and will issue a warning. -(SUSv2 did not -include \fI%\(aqF\fP, but SUSv3 added it.) -.PP -glibc 2.2 adds one further flag character. -.TP -.B I -For decimal integer conversion -.RB ( i , -.BR d , -.BR u ) -the output uses the locale's alternative output digits, if any. -For example, since glibc 2.2.3 this will give Arabic-Indic digits -in the Persian ("fa_IR") locale. -.\" outdigits keyword in locale file -.SS The field width -An optional decimal digit string (with nonzero 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 "*" or "*m$" -(for some decimal integer \fIm\fP) to specify that the field width -is given in the next argument, or in the \fIm\fP-th argument, respectively, -which must be of type -.IR int . -A negative field width is taken as a \(aq\-\(aq flag followed by a -positive field width. -In no case does a nonexistent 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. -.SS The precision -An optional precision, in the form of a period (\(aq.\(aq) followed by an -optional decimal digit string. -Instead of a decimal digit string one may write "*" or "*m$" -(for some decimal integer m) to specify that the precision -is given in the next argument, or in the m-th argument, respectively, -which must be of type -.IR int . -If the precision is given as just \(aq.\(aq, the precision is taken to -be zero. -A negative precision is taken as if the precision were omitted. -This gives the minimum number of digits to appear for -.BR d , -.BR i , -.BR o , -.BR u , -.BR x , -and -.B X -conversions, the number of digits to appear after the radix character for -.BR a , -.BR A , -.BR e , -.BR E , -.BR f , -and -.B F -conversions, the maximum number of significant digits for -.B g -and -.B G -conversions, or the maximum number of characters to be printed from a -string for -.B s -and -.B S -conversions. -.SS The length modifier -Here, "integer conversion" stands for -.BR d , -.BR i , -.BR o , -.BR u , -.BR x , -or -.B X -conversion. -.TP -.B hh -A following integer conversion corresponds to a -.I signed char -or -.I unsigned char -argument, or a following -.B n -conversion corresponds to a pointer to a -.I signed char -argument. -.TP -.B h -A following integer conversion corresponds to a -.I short int -or -.I unsigned short int -argument, or a following -.B n -conversion corresponds to a pointer to a -.I short int -argument. -.TP -.B l -(ell) A following integer conversion corresponds to a -.I long int -or -.I unsigned long int -argument, or a following -.B n -conversion corresponds to a pointer to a -.I long int -argument, or a following -.B c -conversion corresponds to a -.I wint_t -argument, or a following -.B s -conversion corresponds to a pointer to -.I wchar_t -argument. -.TP -.B ll -(ell-ell). -A following integer conversion corresponds to a -.I long long int -or -.I unsigned long long int -argument, or a following -.B n -conversion corresponds to a pointer to a -.I long long int -argument. -.TP -.B L -A following -.BR a , -.BR A , -.BR e , -.BR E , -.BR f , -.BR F , -.BR g , -or -.B G -conversion corresponds to a -.I long double -argument. -(C99 allows %LF, but SUSv2 does not.) -.\" .TP -.\" .B q -.\" ("quad". 4.4BSD and Linux libc5 only. -.\" Don't use.) -This is a synonym for -.BR ll . -.TP -.B j -A following integer conversion corresponds to an -.I intmax_t -or -.I uintmax_t -argument, or a following -.B n -conversion corresponds to a pointer to an -.I intmax_t -argument. -.TP -.B z -A following integer conversion corresponds to a -.I size_t -or -.I ssize_t -argument, or a following -.B n -conversion corresponds to a pointer to a -.I size_t -argument. -.\" (Linux libc5 has -.\" .B Z -.\" with this meaning. -.\" Don't use it.) -.TP -.B t -A following integer conversion corresponds to a -.I ptrdiff_t -argument, or a following -.B n -conversion corresponds to a pointer to a -.I ptrdiff_t -argument. -.PP -SUSv3 specifies all of the above. -SUSv2 specified only the length modifiers -.B h -(in -.BR hd , -.BR hi , -.BR ho , -.BR hx , -.BR hX , -.BR hn ) -and -.B l -(in -.BR ld , -.BR li , -.BR lo , -.BR lx , -.BR lX , -.BR ln , -.BR lc , -.BR ls ) -and -.B L -(in -.BR Le , -.BR LE , -.BR Lf , -.BR Lg , -.BR LG ). -.SS The conversion specifier -A character that specifies the type of conversion to be applied. -The conversion specifiers and their meanings are: -.TP -.BR d ", " i -The -.I int -argument is converted to signed decimal notation. -The precision, if any, gives the minimum number of digits -that must appear; if the converted value requires fewer digits, it is -padded on the left with zeros. -The default precision is 1. -When 0 is printed with an explicit precision 0, the output is empty. -.TP -.BR o ", " u ", " x ", " X -The -.I "unsigned int" -argument is converted to unsigned octal -.RB ( o ), -unsigned decimal -.RB ( u ), -or unsigned hexadecimal -.RB ( x -and -.BR X ) -notation. -The letters -.B abcdef -are used for -.B x -conversions; the letters -.B ABCDEF -are used for -.B X -conversions. -The precision, if any, gives the minimum number of digits -that must appear; if the converted value requires fewer digits, it is -padded on the left with zeros. -The default precision is 1. -When 0 is printed with an explicit precision 0, the output is empty. -.TP -.BR e ", " E -The -.I double -argument is rounded and converted in the style -.RB [\-]d \&. ddd e \(+-dd -where there is one digit before the decimal-point character and the number -of digits after it is equal to the precision; if the precision is missing, -it is taken as 6; if the precision is zero, no decimal-point character -appears. -An -.B E -conversion uses the letter -.B E -(rather than -.BR e ) -to introduce the exponent. -The exponent always contains at least two -digits; if the value is zero, the exponent is 00. -.TP -.BR f ", " F -The -.I double -argument is rounded and converted to decimal notation in the style -.RB [\-]ddd \&. ddd, -where the number of digits after the decimal-point character is equal to -the precision specification. -If the precision is missing, it is taken as -6; if the precision is explicitly zero, no decimal-point character appears. -If a decimal point appears, at least one digit appears before it. +See +.BR printf (3) -(SUSv2 does not know about -.B F -and says that character string representations for infinity and NaN -may be made available. -SUSv3 adds a specification for -.BR F . -The C99 standard specifies "[\-]inf" or "[\-]infinity" -for infinity, and a string starting with "nan" for NaN, in the case of -.B f -conversion, and "[\-]INF" or "[\-]INFINITY" or "NAN*" in the case of -.B F -conversion.) -.TP -.BR g ", " G -The -.I double -argument is converted in style -.B f -or -.B e -(or -.B F -or -.B E -for -.B G -conversions). -The precision specifies the number of significant digits. -If the precision is missing, 6 digits are given; if the precision is zero, -it is treated as 1. -Style -.B e -is used if the exponent from its conversion is less than \-4 or greater -than or equal to the precision. -Trailing zeros are removed from the -fractional part of the result; a decimal point appears only if it is -followed by at least one digit. -.TP -.BR a ", " A -(C99; not in SUSv2, but added in SUSv3) -For -.B a -conversion, the -.I double -argument is converted to hexadecimal notation (using the letters abcdef) -in the style -.RB [\-] 0x h \&. hhhh p \(+-; -for -.B A -conversion the prefix -.BR 0X , -the letters ABCDEF, and the exponent separator -.B P -is used. -There is one hexadecimal digit before the decimal point, -and the number of digits after it is equal to the precision. -The default precision suffices for an exact representation of the value -if an exact representation in base 2 exists -and otherwise is sufficiently large to distinguish values of type -.IR double . -The digit before the decimal point is unspecified for nonnormalized -numbers, and nonzero but otherwise unspecified for normalized numbers. -.TP -.B c -If no -.B l -modifier is present, the -.I int -argument is converted to an -.IR "unsigned char" , -and the resulting character is written. -If an -.B l -modifier is present, the -.I wint_t -(wide character) argument is converted to a multibyte sequence by a call -to the -.BR wcrtomb (3) -function, with a conversion state starting in the initial state, and the -resulting multibyte string is written. -.TP -.B s -If no -.B l -modifier is present: The -.I "const char\ *" -argument is expected to be a pointer to an array of character type (pointer -to a string). -Characters from the array are written up to (but not -including) a terminating null byte (\(aq\\0\(aq); -if a precision is specified, no more than the number specified -are written. -If a precision is given, no null byte need be present; -if the precision is not specified, or is greater than the size of the -array, the array must contain a terminating null byte. - -If an -.B l -modifier is present: The -.I "const wchar_t\ *" -argument is expected to be a pointer to an array of wide characters. -Wide characters from the array are converted to multibyte characters -(each by a call to the -.BR wcrtomb (3) -function, with a conversion state starting in the initial state before -the first wide character), up to and including a terminating null -wide character. -The resulting multibyte characters are written up to -(but not including) the terminating null byte. -If a precision is -specified, no more bytes than the number specified are written, but -no partial multibyte characters are written. -Note that the precision -determines the number of -.I bytes -written, not the number of -.I wide characters -or -.IR "screen positions" . -The array must contain a terminating null wide character, unless a -precision is given and it is so small that the number of bytes written -exceeds it before the end of the array is reached. -.TP -.B C -(Not in C99 or C11, but in SUSv2, SUSv3, and SUSv4.) -Synonym for -.BR lc . -Don't use. -.TP -.B S -(Not in C99 or C11, but in SUSv2, SUSv3, and SUSv4.) -Synonym for -.BR ls . -Don't use. -.TP -.B p -The -.I "void\ *" -pointer argument is printed in hexadecimal (as if by -.B %#x -or -.BR %#lx ). -.TP -.B n -The number of characters written so far is stored into the integer -pointed to by the corresponding argument. -That argument shall be an -.I "int\ *", -or variant whose size matches the (optionally) -supplied integer length modifier. -No argument is converted. -The behavior is undefined if the conversion specification includes -any flags, a field width, or a precision. -.TP -.B m -(Glibc extension.) -Print output of -.IR strerror(errno) . -No argument is required. -.TP -.B % -A \(aq%\(aq is written. -No argument is converted. -The complete conversion -specification is \(aq%%\(aq. .SH CONFORMING TO The -.BR fprintf (), -.BR printf (), -.BR sprintf (), -.BR vprintf (), -.BR vfprintf (), +.BR pcprintf (), and -.BR vsprintf () -functions conform to C89 and C99. -The -.BR snprintf () +.BR pcsprintf () +functions conform to C99 as they essentially wrap +.BR printf (3) and -.BR vsnprintf () -functions conform to C99. -.PP -Concerning the return value of -.BR snprintf (), -SUSv2 and C99 contradict each other: when -.BR snprintf () -is called with -.IR size =0 -then SUSv2 stipulates an unspecified return value less than 1, -while C99 allows -.I str -to be NULL in this case, and gives the return value (as always) -as the number of characters that would have been written in case -the output string has been large enough. -SUSv3 and later align their specification of -.BR snprintf () -with C99. -.\" .PP -.\" Linux libc4 knows about the five C standard flags. -.\" It knows about the length modifiers \fBh\fP, \fBl\fP, \fBL\fP, -.\" and the conversions -.\" \fBc\fP, \fBd\fP, \fBe\fP, \fBE\fP, \fBf\fP, \fBF\fP, -.\" \fBg\fP, \fBG\fP, \fBi\fP, \fBn\fP, \fBo\fP, \fBp\fP, -.\" \fBs\fP, \fBu\fP, \fBx\fP, and \fBX\fP, -.\" where \fBF\fP is a synonym for \fBf\fP. -.\" Additionally, it accepts \fBD\fP, \fBO\fP, and \fBU\fP as synonyms -.\" for \fBld\fP, \fBlo\fP, and \fBlu\fP. -.\" (This is bad, and caused serious bugs later, when -.\" support for \fB%D\fP disappeared.) -.\" No locale-dependent radix character, -.\" no thousands' separator, no NaN or infinity, no "%m$" and "*m$". -.\" .PP -.\" Linux libc5 knows about the five C standard flags and the \(aq flag, -.\" locale, "%m$" and "*m$". -.\" It knows about the length modifiers \fBh\fP, \fBl\fP, \fBL\fP, -.\" \fBZ\fP, and \fBq\fP, but accepts \fBL\fP and \fBq\fP -.\" both for \fIlong double\fP and for \fIlong long int\fP (this is a bug). -.\" It no longer recognizes \fBF\fP, \fBD\fP, \fBO\fP, and \fBU\fP, -.\" but adds the conversion character -.\" .BR m , -.\" which outputs -.\" .IR strerror(errno) . -.\" .PP -.\" glibc 2.0 adds conversion characters \fBC\fP and \fBS\fP. -.PP -glibc 2.1 adds length modifiers \fBhh\fP, \fBj\fP, \fBt\fP, and \fBz\fP -and conversion characters \fBa\fP and \fBA\fP. -.PP -glibc 2.2 adds the conversion character \fBF\fP with C99 semantics, -and the flag character \fBI\fP. +.BR sprintf (3) +. .SH NOTES -Some programs imprudently rely on code such as the following - - sprintf(buf, "%s some further text", buf); - -to append text to -.IR buf . -However, the standards explicitly note that the results are undefined -if source and destination buffers overlap when calling -.BR sprintf (), -.BR snprintf (), -.BR vsprintf (), +.BR pcprintf () and -.BR vsnprintf (). -.\" http://sourceware.org/bugzilla/show_bug.cgi?id=7075 -Depending on the version of -.BR gcc (1) -used, and the compiler options employed, calls such as the above will -.B not -produce the expected results. +.BR pcsprintf () +use +.BR vasprintf (3) +to automatically allocate buffer memory. -The glibc implementation of the functions -.BR snprintf () -and -.BR vsnprintf () -conforms to the C99 standard, that is, behaves as described above, -since glibc version 2.1. -Until glibc 2.0.6, they would return \-1 -when the output was truncated. -.\" .SH HISTORY -.\" UNIX V7 defines the three routines -.\" .BR printf (), -.\" .BR fprintf (), -.\" .BR sprintf (), -.\" and has the flag \-, the width or precision *, the length modifier l, -.\" and the conversions doxfegcsu, and also D,O,U,X as synonyms for ld,lo,lu,lx. -.\" This is still true for 2.9.1BSD, but 2.10BSD has the flags -.\" #, + and and no longer mentions D,O,U,X. -.\" 2.11BSD has -.\" .BR vprintf (), -.\" .BR vfprintf (), -.\" .BR vsprintf (), -.\" and warns not to use D,O,U,X. -.\" 4.3BSD Reno has the flag 0, the length modifiers h and L, -.\" and the conversions n, p, E, G, X (with current meaning) -.\" and deprecates D,O,U. -.\" 4.4BSD introduces the functions -.\" .BR snprintf () -.\" and -.\" .BR vsnprintf (), -.\" and the length modifier q. -.\" FreeBSD also has functions -.\" .BR asprintf () -.\" and -.\" .BR vasprintf (), -.\" that allocate a buffer large enough for -.\" .BR sprintf (). -.\" In glibc there are functions -.\" .BR dprintf () -.\" and -.\" .BR vdprintf () -.\" that print to a file descriptor instead of a stream. .SH BUGS -Because -.BR sprintf () -and -.BR vsprintf () -assume an arbitrarily long string, callers must be careful not to overflow -the actual space; this is often impossible to assure. -Note that the length -of the strings produced is locale-dependent and difficult to predict. -Use -.BR snprintf () -and -.BR vsnprintf () -instead (or -.BR asprintf (3) -and -.BR vasprintf (3)). -.\" .PP -.\" Linux libc4.[45] does not have a -.\" .BR snprintf (), -.\" but provides a libbsd that contains an -.\" .BR snprintf () -.\" equivalent to -.\" .BR sprintf (), -.\" that is, one that ignores the -.\" .I size -.\" argument. -.\" Thus, the use of -.\" .BR snprintf () -.\" with early libc4 leads to serious security problems. -.PP -Code such as -.BI printf( foo ); -often indicates a bug, since -.I foo -may contain a % character. -If -.I foo -comes from untrusted user input, it may contain \fB%n\fP, causing the -.BR printf () -call to write to memory and creating a security hole. -.\" .PP -.\" Some floating-point conversions under early libc4 -.\" caused memory leaks. +See +.BR printf (3) + .SH EXAMPLE -To print -.I Pi -to five decimal places: -.in +4n .nf +#include <\fBcstdio\fR> +#include <\fBiostream\fR> +#include <\fBpipecolors.h\fR> -#include -#include -fprintf(stdout, "pi = %.5f\en", 4 * atan(1.0)); -.fi -.in -.PP -To print a date and time in the form "Sunday, July 3, 10:02", -where -.I weekday -and -.I month -are pointers to strings: -.in +4n -.nf +using \fBnamespace\fR pipecolors; -#include -fprintf(stdout, "%s, %s %d, %.2d:%.2d\en", - weekday, month, day, hour, min); -.fi -.in -.PP -Many countries use the day-month-year order. -Hence, an internationalized version must be able to print -the arguments in an order specified by the format: -.in +4n -.nf +\fBint\fR main(\fBvoid\fR) { -#include -fprintf(stdout, format, - weekday, month, day, hour, min); + \fBint\fR num = 5; + \fBconst char*\fR str = "My number is"; + pcprintf("|02%s |10%d|39\\n", str, num); -.fi -.in -where -.I format -depends on locale, and may permute the arguments. -With the value: -.in +4n -.nf - -"%1$s, %3$d. %2$s, %4$d:%5$.2d\en" - -.fi -.in -one might obtain "Sonntag, 3. Juli, 10:02". -.PP -To allocate a sufficiently large string and print into it -(code correct for both glibc 2.0 and glibc 2.1): -.nf - -#include -#include -#include - -char * -make_message(const char *fmt, ...) -{ - int n; - int size = 100; /* Guess we need no more than 100 bytes */ - char *p, *np; - va_list ap; - - p = malloc(size); - if (p == NULL) - return NULL; - - while (1) { - - /* Try to print in the allocated space */ - - va_start(ap, fmt); - n = vsnprintf(p, size, fmt, ap); - va_end(ap); - - /* Check error code */ - - if (n < 0) { - free(p); - return NULL; - } - - /* If that worked, return the string */ - - if (n < size) - return p; - - /* Else try again with more space */ - - size = n + 1; /* Precisely what is needed */ - - - np = realloc(p, size); - if (np == NULL) { - free(p); - return NULL; - } else { - p = np; - } - } + \fBreturn\fR 0; } + +\fBOutput\fR "\fB[ESC]\fRx1b[0;32mMy number is \fB[ESC]\fRx1b[0;92m5\fB[ESC]\fRx1b[0;39m"; +.P +This would print \fBMy Number is\fR in dark green and \fI5\fR in light green. +The final code \fB|39\fR resets to the default color. .fi -.PP -If truncation occurs in glibc versions prior to 2.0.6, this is treated as an -error instead of being handled gracefully. .SH SEE ALSO -.BR printf (1), +.BR printf (3), +.BR sprintf (3), +.BR vprintf (3), +.BR vsprintf (3), .BR asprintf (3), -.BR dprintf (3), -.BR scanf (3), -.BR setlocale (3), -.BR wcrtomb (3), -.BR wprintf (3), -.BR locale (5) -.SH COLOPHON -This page is part of release 3.74 of the Linux -.I man-pages -project. -A description of the project, -information about reporting bugs, -and the latest version of this page, -can be found at -\%http://www.kernel.org/doc/man\-pages/. +.BR vasprintf (3)