/usr/share/nickle/printf.5c is in nickle 2.71-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | /* $Header$*/
/*
* Copyright © 2002 Keith Packard and Bart Massey.
* All Rights Reserved. See the file COPYING in this directory
* for licensing information.
*/
extend namespace File {
int default_output_precision = -1;
int infinite_output_precision = -2;
public exception too_many_arguments (string format, poly[*] args)
/*
* Raised when too many arguments are passed to a printf
* function
*/;
public exception too_few_arguments (string format, poly[*] args)
/*
* Raised when too few arguments are passed to a printf
* function
*/;
void to_utf8 (int c, void(int c) f)
{
int bits;
if (c < 0x0) return;
else if (c < 0x80) { f(c); bits= -6; }
else if (c < 0x800) { f(((c >> 6) & 0x1F) | 0xC0); bits= 0; }
else if (c < 0x10000) { f(((c >> 12) & 0x0F) | 0xE0); bits= 6; }
else if (c < 0x200000) { f(((c >> 18) & 0x07) | 0xF0); bits= 12; }
else if (c < 0x4000000) { f(((c >> 24) & 0x03) | 0xF8); bits= 18; }
else if (c < 0x80000000) { f(((c >> 30) & 0x01) | 0xFC); bits= 24; }
else return;
for ( ; bits >= 0; bits-= 6)
f(((c >> bits) & 0x3F) | 0x80);
}
public void fprintf (file f, string format, poly args...)
/*
* print 'args' to 'f' according to 'format'
*/
{
/*
* A private namespace to walk the format string
*/
namespace fmt {
int i = 0;
int len = String::length(format);
/*
* Return whether the end of the string has been reached
*/
public bool done () {
return i >= len;
}
/*
* Return current character, raising an exception if
* the end of the string has been reached
*/
public int c() {
if (done())
raise invalid_argument ("invalid format", 1, format);
return format[i];
}
/*
* Step to next character
*/
public void step () {
++i;
}
/*
* Return true and step if current character matches 'm'
*/
public bool match(int m) {
if (c() == m)
{
step();
return true;
}
return false;
}
/*
* Return a number from the format string
*/
public int number () {
int n = 0;
while ('0' <= c() && c() <= '9')
{
n = n * 10 + c() - '0';
step();
}
return n;
}
}
namespace arg {
int n = 0;
public poly next () {
if (n == dim(args))
raise too_few_arguments (format, args);
return args[n++];
}
public void done () {
if (n != dim(args))
raise too_many_arguments (format, args);
}
}
while (!fmt::done() && !File::error (f))
{
if (fmt::match ('%') && fmt::c() != '%')
{
/*
* width
*/
string fill = " ";
if (fmt::match('0'))
fill = "0";
int width = 0;
if (fmt::match('*'))
width = arg::next ();
else
{
int sign = 1;
if (fmt::match('-'))
sign = -1;
width = fmt::number () * sign;
}
/*
* precision
*/
int prec = default_output_precision;
if (fmt::match ('.'))
{
if (fmt::match('-'))
prec = infinite_output_precision;
else if (fmt::match('*'))
prec = arg::next ();
else
prec = fmt::number ();
}
/*
* typecheck and select base
*/
const struct {
string formats;
bool(poly) test;
string message;
int base;
}[*] fmts = {
{ .formats = "s", .test = is_string,
.message = "string", .base = 10 },
{ .formats = "dD", .test = is_int,
.message = "int", .base = 10 },
{ .formats = "bB", .test = is_int,
.message = "int", .base = 2 },
{ .formats = "oO", .test = is_int,
.message = "int", .base = 8 },
{ .formats = "xX", .test = is_int,
.message = "int", .base = 16 },
{ .formats = "efEF", .test = is_number,
.message = "real", .base = 10 }
};
poly this_arg = arg::next();
string this_fmt = String::new (fmt::c());
int this_base = 10;
for (int i = 0; i < dim (fmts); i++)
if (String::index (fmts[i].formats, this_fmt) >= 0)
{
if (!fmts[i].test (this_arg))
raise invalid_argument (fmts[i].message +
"format with non-" +
fmts[i].message,
1, this_arg);
this_base = fmts[i].base;
break;
}
print (f, this_arg, this_fmt, this_base, width, prec, fill);
} else
putc (fmt::c(), f);
fmt::step ();
}
arg::done ();
}
public namespace PrintfGlobals {
public void printf (string format, poly args...)
/*
* print 'args' to stdout according to 'format'
*/
{
fprintf (stdout, format, args ...);
}
public string sprintf (string format, poly args...)
/*
* print 'args' to a string according to 'format'
*/
{
file f = File::string_write ();
fprintf (f, format, args ...);
return File::string_string (f);
}
}
public import PrintfGlobals;
}
public import File::PrintfGlobals;
|