Get rid of the gross operator,()/variadic macro hack
that made ccprintf and friends work, turn it into a normal function (though it still has a slightly strange implementation.) All instances of variadic macros are not yet removed, but I know how, and it will happen. One side effect of this new implementation is that a cprintf statement can now only have 16 parameters, though it's easy enough to raise this number if needed. --HG-- extra : convert_revision : 85cb3c17f8e2ecf9cd2f31ea80a760a28ea127a7
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||
* Copyright (c) 2002-2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -39,232 +39,247 @@ using namespace std;
|
||||
|
||||
namespace cp {
|
||||
|
||||
ArgList::~ArgList()
|
||||
Print::Print(std::ostream &stream, const std::string &format)
|
||||
: stream(stream), format(format.c_str()), ptr(format.c_str())
|
||||
{
|
||||
saved_flags = stream.flags();
|
||||
saved_fill = stream.fill();
|
||||
saved_precision = stream.precision();
|
||||
}
|
||||
|
||||
Print::Print(std::ostream &stream, const char *format)
|
||||
: stream(stream), format(format), ptr(format)
|
||||
{
|
||||
saved_flags = stream.flags();
|
||||
saved_fill = stream.fill();
|
||||
saved_precision = stream.precision();
|
||||
}
|
||||
|
||||
Print::~Print()
|
||||
{
|
||||
while (!objects.empty()) {
|
||||
delete objects.front();
|
||||
objects.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ArgList::dump(const string &format)
|
||||
Print::process(Format &fmt)
|
||||
{
|
||||
list_t::iterator iter = objects.begin();
|
||||
list_t::iterator end = objects.end();
|
||||
size_t len;
|
||||
|
||||
const char *p = format.c_str();
|
||||
while (*ptr) {
|
||||
switch (*ptr) {
|
||||
case '%':
|
||||
if (ptr[1] != '%')
|
||||
goto processing;
|
||||
|
||||
stream->fill(' ');
|
||||
stream->flags((ios::fmtflags)0);
|
||||
|
||||
while (*p) {
|
||||
switch (*p) {
|
||||
case '%': {
|
||||
if (p[1] == '%') {
|
||||
*stream << '%';
|
||||
p += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
Format fmt;
|
||||
bool done = false;
|
||||
bool end_number = false;
|
||||
bool have_precision = false;
|
||||
int number = 0;
|
||||
|
||||
while (!done) {
|
||||
++p;
|
||||
if (*p >= '0' && *p <= '9') {
|
||||
if (end_number)
|
||||
continue;
|
||||
} else if (number > 0)
|
||||
end_number = true;
|
||||
|
||||
switch (*p) {
|
||||
case 's':
|
||||
fmt.format = Format::string;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
fmt.format = Format::character;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
fmt.format = Format::integer;
|
||||
fmt.base = Format::hex;
|
||||
fmt.alternate_form = true;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
fmt.uppercase = true;
|
||||
case 'x':
|
||||
fmt.base = Format::hex;
|
||||
fmt.format = Format::integer;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
fmt.base = Format::oct;
|
||||
fmt.format = Format::integer;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'u':
|
||||
fmt.format = Format::integer;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
fmt.uppercase = true;
|
||||
case 'g':
|
||||
fmt.format = Format::floating;
|
||||
fmt.float_format = Format::best;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
fmt.uppercase = true;
|
||||
case 'e':
|
||||
fmt.format = Format::floating;
|
||||
fmt.float_format = Format::scientific;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
fmt.format = Format::floating;
|
||||
fmt.float_format = Format::fixed;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
*stream << "we don't do %n!!!\n";
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
fmt.alternate_form = true;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
fmt.flush_left = true;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
fmt.print_sign = true;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
fmt.blank_space = true;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
fmt.width = number;
|
||||
fmt.precision = 0;
|
||||
have_precision = true;
|
||||
number = 0;
|
||||
end_number = false;
|
||||
break;
|
||||
|
||||
case '0':
|
||||
if (number == 0) {
|
||||
fmt.fill_zero = true;
|
||||
break;
|
||||
}
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
number = number * 10 + (*p - '0');
|
||||
break;
|
||||
|
||||
case '%':
|
||||
assert("we shouldn't get here");
|
||||
break;
|
||||
|
||||
default:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (end_number) {
|
||||
if (have_precision)
|
||||
fmt.precision = number;
|
||||
else
|
||||
fmt.width = number;
|
||||
|
||||
end_number = false;
|
||||
number = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter != end)
|
||||
{
|
||||
ios::fmtflags saved_flags = stream->flags();
|
||||
char old_fill = stream->fill();
|
||||
int old_precision = stream->precision();
|
||||
|
||||
(*iter)->process(*stream, fmt);
|
||||
|
||||
stream->flags(saved_flags);
|
||||
stream->fill(old_fill);
|
||||
stream->precision(old_precision);
|
||||
|
||||
++iter;
|
||||
} else {
|
||||
*stream << "<missing arg for format>";
|
||||
}
|
||||
|
||||
++p;
|
||||
}
|
||||
stream.put('%');
|
||||
ptr += 2;
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
*stream << endl;
|
||||
++p;
|
||||
stream << endl;
|
||||
++ptr;
|
||||
break;
|
||||
case '\r':
|
||||
++p;
|
||||
if (*p != '\n')
|
||||
*stream << endl;
|
||||
++ptr;
|
||||
if (*ptr != '\n')
|
||||
stream << endl;
|
||||
break;
|
||||
|
||||
default: {
|
||||
size_t len = strcspn(p, "%\n\r\0");
|
||||
stream->write(p, len);
|
||||
p += len;
|
||||
}
|
||||
default:
|
||||
len = strcspn(ptr, "%\n\r\0");
|
||||
stream.write(ptr, len);
|
||||
ptr += len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (iter != end) {
|
||||
*stream << "<extra arg>";
|
||||
++iter;
|
||||
return;
|
||||
|
||||
processing:
|
||||
bool done = false;
|
||||
bool end_number = false;
|
||||
bool have_precision = false;
|
||||
int number = 0;
|
||||
|
||||
stream.fill(' ');
|
||||
stream.flags((ios::fmtflags)0);
|
||||
|
||||
while (!done) {
|
||||
++ptr;
|
||||
if (*ptr >= '0' && *ptr <= '9') {
|
||||
if (end_number)
|
||||
continue;
|
||||
} else if (number > 0)
|
||||
end_number = true;
|
||||
|
||||
switch (*ptr) {
|
||||
case 's':
|
||||
fmt.format = Format::string;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
fmt.format = Format::character;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
fmt.format = Format::integer;
|
||||
fmt.base = Format::hex;
|
||||
fmt.alternate_form = true;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
fmt.uppercase = true;
|
||||
case 'x':
|
||||
fmt.base = Format::hex;
|
||||
fmt.format = Format::integer;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
fmt.base = Format::oct;
|
||||
fmt.format = Format::integer;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'u':
|
||||
fmt.format = Format::integer;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
fmt.uppercase = true;
|
||||
case 'g':
|
||||
fmt.format = Format::floating;
|
||||
fmt.float_format = Format::best;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
fmt.uppercase = true;
|
||||
case 'e':
|
||||
fmt.format = Format::floating;
|
||||
fmt.float_format = Format::scientific;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
fmt.format = Format::floating;
|
||||
fmt.float_format = Format::fixed;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
stream << "we don't do %n!!!\n";
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
fmt.alternate_form = true;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
fmt.flush_left = true;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
fmt.print_sign = true;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
fmt.blank_space = true;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
fmt.width = number;
|
||||
fmt.precision = 0;
|
||||
have_precision = true;
|
||||
number = 0;
|
||||
end_number = false;
|
||||
break;
|
||||
|
||||
case '0':
|
||||
if (number == 0) {
|
||||
fmt.fill_zero = true;
|
||||
break;
|
||||
}
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
number = number * 10 + (*ptr - '0');
|
||||
break;
|
||||
|
||||
case '%':
|
||||
assert("we shouldn't get here");
|
||||
break;
|
||||
|
||||
default:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (end_number) {
|
||||
if (have_precision)
|
||||
fmt.precision = number;
|
||||
else
|
||||
fmt.width = number;
|
||||
|
||||
end_number = false;
|
||||
number = 0;
|
||||
}
|
||||
}
|
||||
|
||||
++ptr;
|
||||
}
|
||||
|
||||
string
|
||||
ArgList::dumpToString(const string &format)
|
||||
void
|
||||
Print::end_args()
|
||||
{
|
||||
stringstream ss;
|
||||
size_t len;
|
||||
|
||||
dump(ss, format);
|
||||
while (*ptr) {
|
||||
switch (*ptr) {
|
||||
case '%':
|
||||
if (ptr[1] != '%')
|
||||
stream << "<extra arg>";
|
||||
|
||||
return ss.str();
|
||||
stream.put('%');
|
||||
ptr += 2;
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
stream << endl;
|
||||
++ptr;
|
||||
break;
|
||||
case '\r':
|
||||
++ptr;
|
||||
if (*ptr != '\n')
|
||||
stream << endl;
|
||||
break;
|
||||
|
||||
default:
|
||||
len = strcspn(ptr, "%\n\r\0");
|
||||
stream.write(ptr, len);
|
||||
ptr += len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stream.flags(saved_flags);
|
||||
stream.fill(saved_fill);
|
||||
stream.precision(saved_precision);
|
||||
}
|
||||
|
||||
}
|
||||
/* end namespace cp */ }
|
||||
|
||||
Reference in New Issue
Block a user