1f834b569c
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
292 lines
8.6 KiB
C++
292 lines
8.6 KiB
C++
/*
|
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met: redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer;
|
|
* redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution;
|
|
* neither the name of the copyright holders nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* Authors: Nathan Binkert
|
|
*/
|
|
|
|
#ifndef __BASE_VARARGS_HH__
|
|
#define __BASE_VARARGS_HH__
|
|
|
|
#include "base/refcnt.hh"
|
|
|
|
#define VARARGS_DECLARATION(receiver) \
|
|
VarArgs::Argument<receiver> a01 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a02 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a03 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a04 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a05 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a06 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a07 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a08 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a09 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a10 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a11 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a12 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a13 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a14 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a15 = VarArgs::Null(), \
|
|
VarArgs::Argument<receiver> a16 = VarArgs::Null()
|
|
|
|
#define VARARGS_DEFINITION(receiver) \
|
|
VarArgs::Argument<receiver> a01, \
|
|
VarArgs::Argument<receiver> a02, \
|
|
VarArgs::Argument<receiver> a03, \
|
|
VarArgs::Argument<receiver> a04, \
|
|
VarArgs::Argument<receiver> a05, \
|
|
VarArgs::Argument<receiver> a06, \
|
|
VarArgs::Argument<receiver> a07, \
|
|
VarArgs::Argument<receiver> a08, \
|
|
VarArgs::Argument<receiver> a09, \
|
|
VarArgs::Argument<receiver> a10, \
|
|
VarArgs::Argument<receiver> a11, \
|
|
VarArgs::Argument<receiver> a12, \
|
|
VarArgs::Argument<receiver> a13, \
|
|
VarArgs::Argument<receiver> a14, \
|
|
VarArgs::Argument<receiver> a15, \
|
|
VarArgs::Argument<receiver> a16
|
|
|
|
#define VARARGS_ALLARGS \
|
|
a01, a02, a03, a04, a05, a06, a07, a08, \
|
|
a09, a10, a11, a12, a13, a14, a15, a16
|
|
|
|
#define VARARGS_ADDARGS(receiver) do { \
|
|
do { \
|
|
if (!a01) break; \
|
|
a01.add_arg(receiver); \
|
|
if (!a02) break; \
|
|
a02.add_arg(receiver); \
|
|
if (!a03) break; \
|
|
a03.add_arg(receiver); \
|
|
if (!a04) break; \
|
|
a04.add_arg(receiver); \
|
|
if (!a05) break; \
|
|
a05.add_arg(receiver); \
|
|
if (!a06) break; \
|
|
a06.add_arg(receiver); \
|
|
if (!a07) break; \
|
|
a07.add_arg(receiver); \
|
|
if (!a08) break; \
|
|
a08.add_arg(receiver); \
|
|
if (!a09) break; \
|
|
a09.add_arg(receiver); \
|
|
if (!a10) break; \
|
|
a10.add_arg(receiver); \
|
|
if (!a11) break; \
|
|
a11.add_arg(receiver); \
|
|
if (!a12) break; \
|
|
a12.add_arg(receiver); \
|
|
if (!a13) break; \
|
|
a13.add_arg(receiver); \
|
|
if (!a14) break; \
|
|
a14.add_arg(receiver); \
|
|
if (!a15) break; \
|
|
a15.add_arg(receiver); \
|
|
if (!a16) break; \
|
|
a16.add_arg(receiver); \
|
|
} while (0); \
|
|
receiver.end_args(); \
|
|
} while (0)
|
|
|
|
namespace VarArgs {
|
|
|
|
struct Null {};
|
|
|
|
template <typename T>
|
|
struct Traits
|
|
{
|
|
enum { enabled = true };
|
|
};
|
|
|
|
template <>
|
|
struct Traits<Null>
|
|
{
|
|
enum { enabled = false };
|
|
};
|
|
|
|
template <class RECV>
|
|
struct Base : public RefCounted
|
|
{
|
|
virtual void add_arg(RECV &receiver) const = 0;
|
|
};
|
|
|
|
template <typename T, class RECV>
|
|
struct Any : public Base<RECV>
|
|
{
|
|
const T &argument;
|
|
|
|
Any(const T &arg) : argument(arg) {}
|
|
|
|
virtual void
|
|
add_arg(RECV &receiver) const
|
|
{
|
|
receiver.add_arg(argument);
|
|
}
|
|
};
|
|
|
|
template <class RECV>
|
|
struct Argument : public RefCountingPtr<Base<RECV> >
|
|
{
|
|
typedef RefCountingPtr<Base<RECV> > Base;
|
|
|
|
Argument() { }
|
|
Argument(const Null &null) { }
|
|
template <typename T>
|
|
Argument(const T& arg) : Base(new Any<T, RECV>(arg)) { }
|
|
|
|
void
|
|
add_arg(RECV &receiver) const
|
|
{
|
|
if (this->data)
|
|
this->data->add_arg(receiver);
|
|
}
|
|
};
|
|
|
|
template<class RECV>
|
|
class List
|
|
{
|
|
public:
|
|
typedef Argument<RECV> Argument;
|
|
typedef std::list<Argument> list;
|
|
typedef typename list::iterator iterator;
|
|
typedef typename list::const_iterator const_iterator;
|
|
typedef typename list::size_type size_type;
|
|
|
|
protected:
|
|
list l;
|
|
|
|
public:
|
|
List() {}
|
|
List(Argument a01, Argument a02, Argument a03, Argument a04,
|
|
Argument a05, Argument a06, Argument a07, Argument a08,
|
|
Argument a09, Argument a10, Argument a11, Argument a12,
|
|
Argument a13, Argument a14, Argument a15, Argument a16)
|
|
{
|
|
if (!a01) return;
|
|
l.push_back(a01);
|
|
if (!a02) return;
|
|
l.push_back(a02);
|
|
if (!a03) return;
|
|
l.push_back(a03);
|
|
if (!a04) return;
|
|
l.push_back(a04);
|
|
if (!a05) return;
|
|
l.push_back(a05);
|
|
if (!a06) return;
|
|
l.push_back(a06);
|
|
if (!a07) return;
|
|
l.push_back(a07);
|
|
if (!a08) return;
|
|
l.push_back(a08);
|
|
if (!a09) return;
|
|
l.push_back(a09);
|
|
if (!a10) return;
|
|
l.push_back(a10);
|
|
if (!a11) return;
|
|
l.push_back(a11);
|
|
if (!a12) return;
|
|
l.push_back(a12);
|
|
if (!a13) return;
|
|
l.push_back(a13);
|
|
if (!a14) return;
|
|
l.push_back(a14);
|
|
if (!a15) return;
|
|
l.push_back(a15);
|
|
if (!a16) return;
|
|
l.push_back(a16);
|
|
}
|
|
|
|
size_type size() const { return l.size(); }
|
|
bool empty() const { return l.empty(); }
|
|
|
|
iterator begin() { return l.begin(); }
|
|
const_iterator begin() const { return l.begin(); }
|
|
|
|
iterator end() { return l.end(); }
|
|
const_iterator end() const { return l.end(); }
|
|
|
|
void
|
|
push_back(const Argument &arg)
|
|
{
|
|
if (arg)
|
|
l.push_back(arg);
|
|
}
|
|
|
|
void
|
|
push_front(const Argument &arg)
|
|
{
|
|
if (arg)
|
|
l.push_front(arg);
|
|
}
|
|
|
|
template <typename T>
|
|
void
|
|
push_back(const T &arg)
|
|
{
|
|
if (Traits<T>::enabled)
|
|
l.push_back(arg);
|
|
}
|
|
|
|
template <typename T>
|
|
void
|
|
push_front(const T &arg)
|
|
{
|
|
if (Traits<T>::enabled)
|
|
l.push_front(arg);
|
|
}
|
|
|
|
Argument& front() { return l.front(); }
|
|
const Argument& front() const { return l.front(); }
|
|
Argument& back() { return l.back(); }
|
|
const Argument& back() const { return l.back(); }
|
|
|
|
void erase(iterator position) { return l.erase(position); }
|
|
void erase(iterator first, iterator last) { return l.erase(first, last); }
|
|
void clear() { return l.clear(); }
|
|
void pop_front() { return l.pop_front(); }
|
|
void pop_back() { return l.pop_back(); }
|
|
void reverse() { l.reverse(); }
|
|
|
|
/*
|
|
* Functions specific to variable arguments
|
|
*/
|
|
void
|
|
add_args(RECV &recv) const
|
|
{
|
|
const_iterator i = l.begin();
|
|
const_iterator end = l.end();
|
|
while (i != end) {
|
|
i->add_arg(recv);
|
|
++i;
|
|
}
|
|
|
|
recv.end_args();
|
|
}
|
|
};
|
|
|
|
/* end namespace VarArgs */ }
|
|
|
|
#endif /* __BASE_VARARGS_HH__ */
|