diff options
Diffstat (limited to 'man3head')
-rw-r--r-- | man3head/printf.h.3head | 582 | ||||
-rw-r--r-- | man3head/sysexits.h.3head | 200 |
2 files changed, 782 insertions, 0 deletions
diff --git a/man3head/printf.h.3head b/man3head/printf.h.3head new file mode 100644 index 0000000..1c6ad32 --- /dev/null +++ b/man3head/printf.h.3head @@ -0,0 +1,582 @@ +.\" Copyright (C) 2022 Alejandro Colomar <alx.manpages@gmail.com> +.\" +.\" SPDX-License-Identifier: Linux-man-pages-copyleft +.\" +.TH printf.h 3head 2022-09-18 "Linux man-pages 6.05.01" +.SH NAME +printf.h, +\%register_printf_specifier, +\%register_printf_modifier, +\%register_printf_type, +\%printf_function, +\%printf_arginfo_size_function, +\%printf_va_arg_function, +\%printf_info, +\%PA_INT, +\%PA_CHAR, +\%PA_WCHAR, +\%PA_STRING, +\%PA_WSTRING, +\%PA_POINTER, +\%PA_FLOAT, +\%PA_DOUBLE, +\%PA_LAST, +\%PA_FLAG_LONG_LONG, +\%PA_FLAG_LONG_DOUBLE, +\%PA_FLAG_LONG, +\%PA_FLAG_SHORT, +\%PA_FLAG_PTR +\- define custom behavior for printf-like functions +.SH LIBRARY +Standard C library +.RI ( libc ", " \-lc ) +.SH SYNOPSIS +.nf +.B #include <printf.h> +.PP +.BI "int register_printf_specifier(int " spec ", printf_function " func , +.BI " printf_arginfo_size_function " arginfo ); +.BI "int register_printf_modifier(const wchar_t *" str ); +.BI "int register_printf_type(printf_va_arg_function " fct ); +.fi +.SS Callbacks +.nf +.BI "typedef int printf_function(FILE *" stream ", const struct printf_info *" info , +.BI " const void *const " args []); +.BI "typedef int printf_arginfo_size_function(const struct printf_info *" info , +.BI " size_t " n ", int " argtypes [ n "], int " size [ n ]); +.BI "typedef void printf_va_arg_function(void *" mem ", va_list *" ap ); +.fi +.SS Types +.EX +.B struct printf_info { +.BR " int prec; " "// Precision" +.BR " int width; " "// Width" +.BR " wchar_t spec; " "// Format letter" +.BR " unsigned int is_long_double:1;" "// " L " or " ll " flag" +.BR " unsigned int is_short:1; " "// " h " flag" +.BR " unsigned int is_long:1; " "// " l " flag" +.BR " unsigned int alt:1; " "// " # " flag" +.BR " unsigned int space:1; " "// Space flag" +.BR " unsigned int left:1; " "// " - " flag" +.BR " unsigned int showsign:1; " "// " + " flag" +.BR " unsigned int group:1; " "// " \[aq] " flag" +.BR " unsigned int extra:1; " "// For special use" +.BR " unsigned int is_char:1; " "// " hh " flag" +.BR " unsigned int wide:1; " "// True for wide character streams" +.BR " unsigned int i18n:1; " "// " I " flag" +.BR " unsigned int is_binary128:1; " "/* Floating-point argument is" +.BR " " " ABI-compatible with" +.BR " " " IEC 60559 binary128 */" +.BR " unsigned short user; " "// Bits for user-installed modifiers" +.BR " wchar_t pad; " "// Padding character" +.B }; +.EE +.SS Constants +.EX +.BR "#define PA_FLAG_LONG_LONG " "/* ... */" +.BR "#define PA_FLAG_LONG_DOUBLE " "/* ... */" +.BR "#define PA_FLAG_LONG " "/* ... */" +.BR "#define PA_FLAG_SHORT " "/* ... */" +.BR "#define PA_FLAG_PTR " "/* ... */" +.EE +.SH DESCRIPTION +These functions serve to extend and/or modify the behavior of the +.BR printf (3) +family of functions. +.SS register_printf_specifier() +This function registers a custom conversion specifier for the +.BR printf (3) +family of functions. +.TP +.I spec +The character which will be used as a conversion specifier in the format string. +.TP +.I func +Callback function that will be executed by the +.BR printf (3) +family of functions +to format the input arguments into the output +.IR stream . +.RS +.TP +.I stream +Output stream where the formatted output should be printed. +This stream transparently represents the output, +even in the case of functions that write to a string. +.TP +.I info +Structure that holds context information, +including the modifiers specified in the format string. +This holds the same contents as in +.IR arginfo . +.TP +.I args +Array of pointers to the arguments to the +.BR printf (3)\c +-like function. +.RE +.TP +.I arginfo +Callback function that will be executed by the +.BR printf (3) +family of functions +to know how many arguments should be parsed for the custom specifier +and also their types. +.RS +.TP +.I info +Structure that holds context information, +including the modifiers specified in the format string. +This holds the same contents as in +.IR func . +.TP +.I n +Number of arguments remaining to be parsed. +.TP +.I argtypes +This array should be set to +define the type of each of the arguments that will be parsed. +Each element in the array represents one of the arguments to be parsed, +in the same order that they are passed to the +.BR printf (3)\c +-like function. +Each element should be set to a base type +.RB ( PA_ *) +from the enum above, +or a custom one, +and optionally ORed with an appropriate length modifier +.RB ( PA_FLAG_ *). +.RS +.PP +The type is determined by using one of the following constants: +.TP +.B PA_INT +.IR int . +.TP +.B PA_CHAR +.IR int , +cast to +.IR char . +.TP +.B PA_WCHAR +.IR wchar_t . +.TP +.B PA_STRING +.IR "const char\~*" , +a \(aq\e0\(aq-terminated string. +.TP +.B PA_WSTRING +.IR "const wchar_t\~*" , +a wide character L\(aq\e0\(aq-terminated string. +.TP +.B PA_POINTER +.IR void\~* . +.TP +.B PA_FLOAT +.IR float . +.TP +.B PA_DOUBLE +.IR double . +.TP +.B PA_LAST +TODO. +.RE +.TP +.I size +For user-defined types, +the size of the type (in bytes) should also be specified through this array. +Otherwise, leave it unused. +.RE +.PP +.I arginfo +is called before +.IR func , +and prepares some information needed to call +.IR func . +.SS register_printf_modifier() +TODO +.SS register_printf_type() +TODO +.SH RETURN VALUE +.BR \%register_printf_specifier (), +.BR \%register_printf_modifier (), +and +.BR \%register_printf_type () +return zero on success, or \-1 on error. +.SS Callbacks +The callback of type +.I printf_function +should return the number of characters written, +or \-1 on error. +.PP +The callback of type +.I \%printf_arginfo_size_function +should return the number of arguments to be parsed by this specifier. +It also passes information about the type of those arguments +to the caller through +.IR argtypes . +On error, it should return \-1. +.SH ERRORS +.TP +.B EINVAL +The specifier was not a valid character. +.SH STANDARDS +GNU. +.SH HISTORY +.BR \%register_printf_function (3) +is an older function similar to +.BR \%register_printf_specifier (), +and is now deprecated. +That function can't handle user-defined types. +.PP +.BR \%register_printf_specifier () +superseeds +.BR \%register_printf_function (3). +.SH EXAMPLES +The following example program registers the 'b' and 'B' specifiers +to print integers in binary format, +mirroring rules for other unsigned conversion specifiers like 'x' and 'u'. +This can be used to print in binary prior to C23. +.PP +.\" SRC BEGIN (register_printf_specifier.c) +.EX +/* This code is in the public domain */ +\& +#include <err.h> +#include <limits.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/param.h> +\& +#include <printf.h> +\& +#define GROUP_SEP \[aq]\e\[aq]\[aq] +\& +struct Printf_Pad { + char ch; + size_t len; +}; +\& +static int b_printf(FILE *stream, const struct printf_info *info, + const void *const args[]); +static int b_arginf_sz(const struct printf_info *info, + size_t n, int argtypes[n], int size[n]); +\& +static uintmax_t b_value(const struct printf_info *info, + const void *arg); +static size_t b_bin_repr(char bin[UINTMAX_WIDTH], + const struct printf_info *info, const void *arg); +static size_t b_bin_len(const struct printf_info *info, + ptrdiff_t min_len); +static size_t b_pad_len(const struct printf_info *info, + ptrdiff_t bin_len); +static ssize_t b_print_prefix(FILE *stream, + const struct printf_info *info); +static ssize_t b_pad_zeros(FILE *stream, const struct printf_info *info, + ptrdiff_t min_len); +static ssize_t b_print_number(FILE *stream, + const struct printf_info *info, + const char bin[UINTMAX_WIDTH], + size_t min_len, size_t bin_len); +static char pad_ch(const struct printf_info *info); +static ssize_t pad_spaces(FILE *stream, size_t pad_len); +\& +int +main(void) +{ + if (register_printf_specifier(\[aq]b\[aq], b_printf, b_arginf_sz) == \-1) + err(EXIT_FAILURE, "register_printf_specifier(\[aq]b\[aq], ...)"); + if (register_printf_specifier(\[aq]B\[aq], b_printf, b_arginf_sz) == \-1) + err(EXIT_FAILURE, "register_printf_specifier(\[aq]B\[aq], ...)"); +\& + printf("....----....----....----....----\en"); + printf("%llb;\en", 0x5Ellu); + printf("%lB;\en", 0x5Elu); + printf("%b;\en", 0x5Eu); + printf("%hB;\en", 0x5Eu); + printf("%hhb;\en", 0x5Eu); + printf("%jb;\en", (uintmax_t)0x5E); + printf("%zb;\en", (size_t)0x5E); + printf("....----....----....----....----\en"); + printf("%#b;\en", 0x5Eu); + printf("%#B;\en", 0x5Eu); + printf("....----....----....----....----\en"); + printf("%10b;\en", 0x5Eu); + printf("%010b;\en", 0x5Eu); + printf("%.10b;\en", 0x5Eu); + printf("....----....----....----....----\en"); + printf("%\-10B;\en", 0x5Eu); + printf("....----....----....----....----\en"); + printf("%\[aq]B;\en", 0x5Eu); + printf("....----....----....----....----\en"); + printf("....----....----....----....----\en"); + printf("%#16.12b;\en", 0xAB); + printf("%\-#\[aq]20.12b;\en", 0xAB); + printf("%#\[aq]020B;\en", 0xAB); + printf("....----....----....----....----\en"); + printf("%#020B;\en", 0xAB); + printf("%\[aq]020B;\en", 0xAB); + printf("%020B;\en", 0xAB); + printf("....----....----....----....----\en"); + printf("%#021B;\en", 0xAB); + printf("%\[aq]021B;\en", 0xAB); + printf("%021B;\en", 0xAB); + printf("....----....----....----....----\en"); + printf("%#022B;\en", 0xAB); + printf("%\[aq]022B;\en", 0xAB); + printf("%022B;\en", 0xAB); + printf("....----....----....----....----\en"); + printf("%#023B;\en", 0xAB); + printf("%\[aq]023B;\en", 0xAB); + printf("%023B;\en", 0xAB); + printf("....----....----....----....----\en"); + printf("%\-#\[aq]19.11b;\en", 0xAB); + printf("%#\[aq]019B;\en", 0xAB); + printf("%#019B;\en", 0xAB); + printf("....----....----....----....----\en"); + printf("%\[aq]019B;\en", 0xAB); + printf("%019B;\en", 0xAB); + printf("%#016b;\en", 0xAB); + printf("....----....----....----....----\en"); +\& + return 0; +} +\& +static int +b_printf(FILE *stream, const struct printf_info *info, + const void *const args[]) +{ + char bin[UINTMAX_WIDTH]; + size_t min_len, bin_len; + ssize_t len, tmp; + struct Printf_Pad pad = {0}; +\& + len = 0; +\& + min_len = b_bin_repr(bin, info, args[0]); + bin_len = b_bin_len(info, min_len); +\& + pad.ch = pad_ch(info); + if (pad.ch == \[aq] \[aq]) + pad.len = b_pad_len(info, bin_len); +\& + /* Padding with \[aq] \[aq] (right aligned) */ + if ((pad.ch == \[aq] \[aq]) && !info->left) { + tmp = pad_spaces(stream, pad.len); + if (tmp == EOF) + return EOF; + len += tmp; + } +\& + /* "0b"/"0B" prefix */ + if (info->alt) { + tmp = b_print_prefix(stream, info); + if (tmp == EOF) + return EOF; + len += tmp; + } +\& + /* Padding with \[aq]0\[aq] */ + if (pad.ch == \[aq]0\[aq]) { + tmp = b_pad_zeros(stream, info, min_len); + if (tmp == EOF) + return EOF; + len += tmp; + } +\& + /* Print number (including leading 0s to fill precision) */ + tmp = b_print_number(stream, info, bin, min_len, bin_len); + if (tmp == EOF) + return EOF; + len += tmp; +\& + /* Padding with \[aq] \[aq] (left aligned) */ + if (info\->left) { + tmp = pad_spaces(stream, pad.len); + if (tmp == EOF) + return EOF; + len += tmp; + } +\& + return len; +} +\& +static int +b_arginf_sz(const struct printf_info *info, size_t n, int argtypes[n], + [[maybe_unused]] int size[n]) +{ + if (n < 1) + return \-1; +\& + if (info\->is_long_double) + argtypes[0] = PA_INT | PA_FLAG_LONG_LONG; + else if (info\->is_long) + argtypes[0] = PA_INT | PA_FLAG_LONG; + else + argtypes[0] = PA_INT; +\& + return 1; +} +\& +static uintmax_t +b_value(const struct printf_info *info, const void *arg) +{ + if (info\->is_long_double) + return *(const unsigned long long *)arg; + if (info\->is_long) + return *(const unsigned long *)arg; +\& + /* short and char are both promoted to int */ + return *(const unsigned int *)arg; +} +\& +static size_t +b_bin_repr(char bin[UINTMAX_WIDTH], + const struct printf_info *info, const void *arg) +{ + size_t min_len; + uintmax_t val; +\& + val = b_value(info, arg); +\& + bin[0] = \[aq]0\[aq]; + for (min_len = 0; val; min_len++) { + bin[min_len] = \[aq]0\[aq] + (val % 2); + val >>= 1; + } +\& + return MAX(min_len, 1); +} +\& +static size_t +b_bin_len(const struct printf_info *info, ptrdiff_t min_len) +{ + return MAX(info\->prec, min_len); +} +\& +static size_t +b_pad_len(const struct printf_info *info, ptrdiff_t bin_len) +{ + ptrdiff_t pad_len; +\& + pad_len = info\->width \- bin_len; + if (info\->alt) + pad_len \-= 2; + if (info\->group) + pad_len \-= (bin_len \- 1) / 4; +\& + return MAX(pad_len, 0); +} +\& +static ssize_t +b_print_prefix(FILE *stream, const struct printf_info *info) +{ + ssize_t len; +\& + len = 0; + if (fputc(\[aq]0\[aq], stream) == EOF) + return EOF; + len++; + if (fputc(info\->spec, stream) == EOF) + return EOF; + len++; +\& + return len; +} +\& +static ssize_t +b_pad_zeros(FILE *stream, const struct printf_info *info, + ptrdiff_t min_len) +{ + ssize_t len; + ptrdiff_t tmp; +\& + len = 0; + tmp = info\->width \- (info\->alt * 2); + if (info\->group) + tmp \-= tmp / 5 \- !(tmp % 5); + for (ptrdiff_t i = tmp \- 1; i > min_len \- 1; i\-\-) { + if (fputc(\[aq]0\[aq], stream) == EOF) + return EOF; + len++; +\& + if (!info\->group || (i % 4)) + continue; + if (fputc(GROUP_SEP, stream) == EOF) + return EOF; + len++; + } +\& + return len; +} +\& +static ssize_t +b_print_number(FILE *stream, const struct printf_info *info, + const char bin[UINTMAX_WIDTH], + size_t min_len, size_t bin_len) +{ + ssize_t len; +\& + len = 0; +\& + /* Print leading zeros to fill precision */ + for (size_t i = bin_len \- 1; i > min_len \- 1; i\-\-) { + if (fputc(\[aq]0\[aq], stream) == EOF) + return EOF; + len++; +\& + if (!info\->group || (i % 4)) + continue; + if (fputc(GROUP_SEP, stream) == EOF) + return EOF; + len++; + } +\& + /* Print number */ + for (size_t i = min_len \- 1; i < min_len; i\-\-) { + if (fputc(bin[i], stream) == EOF) + return EOF; + len++; +\& + if (!info\->group || (i % 4) || !i) + continue; + if (fputc(GROUP_SEP, stream) == EOF) + return EOF; + len++; + } +\& + return len; +} +\& +static char +pad_ch(const struct printf_info *info) +{ + if ((info\->prec != \-1) || (info\->pad == \[aq] \[aq]) || info\->left) + return \[aq] \[aq]; + return \[aq]0\[aq]; +} +\& +static ssize_t +pad_spaces(FILE *stream, size_t pad_len) +{ + ssize_t len; +\& + len = 0; + for (size_t i = pad_len - 1; i < pad_len; i\-\-) { + if (fputc(\[aq] \[aq], stream) == EOF) + return EOF; + len++; + } +\& + return len; +} +.EE +.\" SRC END +.SH SEE ALSO +.BR asprintf (3), +.BR printf (3), +.BR wprintf (3) diff --git a/man3head/sysexits.h.3head b/man3head/sysexits.h.3head new file mode 100644 index 0000000..a1b8d08 --- /dev/null +++ b/man3head/sysexits.h.3head @@ -0,0 +1,200 @@ +'\" t +.\" Copyright (c) 1996 Joerg Wunsch +.\" Copyright (c) 2022 Alejandro Colomar <alx@kernel.org> +.\" +.\" All rights reserved. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" Rewritten for the Linux man-pages by Alejandro Colomar +.\" +.TH sysexits.h 3head 2023-03-30 "Linux man-pages 6.05.01" +.SH NAME +sysexits.h \- exit codes for programs +.SH LIBRARY +Standard C library +.RI ( libc ) +.SH SYNOPSIS +.nf +.B #include <sysexits.h> +.fi +.TS +lB2 lB2 l1 lX. +#define EX_OK 0 /* T{ +successful termination */ +T} +.PP +#define EX__BASE 64 /* T{ +base value for error messages */ +T} +.PP +#define EX_USAGE 64 /* T{ +command line usage error */ +T} +#define EX_DATAERR 65 /* T{ +data format error */ +T} +#define EX_NOINPUT 66 /* T{ +cannot open input */ +T} +#define EX_NOUSER 67 /* T{ +addressee unknown */ +T} +#define EX_NOHOST 68 /* T{ +host name unknown */ +T} +#define EX_UNAVAILABLE 69 /* T{ +service unavailable */ +T} +#define EX_SOFTWARE 70 /* T{ +internal software error */ +T} +#define EX_OSERR 71 /* T{ +system error (e.g., can't fork) */ +T} +#define EX_OSFILE 72 /* T{ +critical OS file missing */ +T} +#define EX_CANTCREAT 73 /* T{ +can't create (user) output file */ +T} +#define EX_IOERR 74 /* T{ +input/output error */ +T} +#define EX_TEMPFAIL 75 /* T{ +temp failure; user is invited to retry */ +T} +#define EX_PROTOCOL 76 /* T{ +remote error in protocol */ +T} +#define EX_NOPERM 77 /* T{ +permission denied */ +T} +#define EX_CONFIG 78 /* T{ +configuration error */ +T} +.PP +.T& +lB2 l2 l1 lX. +#define EX__MAX ... /* T{ +maximum listed value */ +T} +.TE +.SH DESCRIPTION +A few programs exit with the following error codes. +.PP +The successful exit is always indicated by a status of +.BR 0 , +or +.B EX_OK +(equivalent to +.B EXIT_SUCCESS +from +.IR <stdlib.h> ). +Error numbers begin at +.B EX__BASE +to reduce the possibility of clashing with other exit statuses +that random programs may already return. +The meaning of the code is approximately as follows: +.TP +.B EX_USAGE +The command was used incorrectly, +e.g., +with the wrong number of arguments, +a bad flag, +bad syntax in a parameter, +or whatever. +.TP +.B EX_DATAERR +The input data was incorrect in some way. +This should only be used for user's data and not system files. +.TP +.B EX_NOINPUT +An input file (not a system file) did not exist or was not readable. +This could also include errors like "No message" to a mailer +(if it cared to catch it). +.TP +.B EX_NOUSER +The user specified did not exist. +This might be used for mail addresses or remote logins. +.TP +.B EX_NOHOST +The host specified did not exist. +This is used in mail addresses or network requests. +.TP +.B EX_UNAVAILABLE +A service is unavailable. +This can occur if a support program or file does not exist. +This can also be used as a catch-all message +when something you wanted to do doesn't work, but you don't know why. +.TP +.B EX_SOFTWARE +An internal software error has been detected. +This should be limited to non-operating system related errors if possible. +.TP +.B EX_OSERR +An operating system error has been detected. +This is intended to be used for such things as +"cannot fork", +"cannot create pipe", +or the like. +It includes things like +.BR getuid (2) +returning a user that does not exist in the +.BR passwd (5) +file. +.TP +.B EX_OSFILE +Some system file +(e.g., +.IR /etc/passwd , +.IR /etc/utmp , +etc.) +does not exist, +cannot be opened, +or has some sort of error (e.g., syntax error). +.TP +.B EX_CANTCREAT +A (user specified) output file cannot be created. +.TP +.B EX_IOERR +An error occurred while doing I/O on some file. +.TP +.B EX_TEMPFAIL +Temporary failure, +indicating something that is not really an error. +For example that a mailer could not create a connection, +and the request should be reattempted later. +.TP +.B EX_PROTOCOL +The remote system returned something that +was "not possible" during a protocol exchange. +.TP +.B EX_OSFILE +You did not have sufficient permission to perform the operation. +This is not intended for file system problems, +which should use +.B EX_NOINPUT +or +.BR EX_CANTCREAT , +but rather for higher level permissions. +.TP +.B EX_CONFIG +Something was found in an unconfigured or misconfigured state. +.PP +The numerical values corresponding to the symbolical ones +are given in parenthesis for easy reference. +.SH STANDARDS +BSD. +.SH HISTORY +The +.I <sysexits.h> +file appeared in 4.0BSD for use by the deliverymail utility, +later renamed to +.BR sendmail (8). +.SH CAVEATS +The choice of an appropriate exit value is often ambiguous. +.SH SEE ALSO +.BR err (3), +.BR error (3), +.BR exit (3) |