#!/bin/sh
#
# aegis - project change supervisor.
# Copyright (C) 2008, 2011, 2012 Peter Miller
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or (at
# your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see .
#
TEST_SUBJECT="fmtgen vs redefinition_ok"
# load up standard prelude and test functions
. test_funcs
#
# test the functionality
#
activity="fmtgen"
cat > test.def << 'fubar'
t1a = boolean redefinition_ok;
t1b = [boolean] redefinition_ok;
fubar
if test $? -ne 0 ; then no_result; fi
cat > test.fmtgen.h.ok << 'fubar'
//
// This file is generated by fmtgen.
//
#ifndef TEST_FMTGEN_H
#define TEST_FMTGEN_H
#include
#include
#ifndef TEST_T1B_LIST_DEF
#define TEST_T1B_LIST_DEF
class test_t1b_list
{
public:
/**
* The pointer typedef is used to have a pointer type which may be used
* by clients of this API, allowing the pointer implementation to be
* changed without extensive code changes throughout the rest of the
* code base.
*/
typedef aegis_shared_ptr pointer;
/**
* The destructor.
*/
virtual ~test_t1b_list();
private:
/**
* The default constructor. It is private on purpose, use the #create
* class method instead.
*/
test_t1b_list();
public:
/**
* The create class method is used to create new dynamically allocated
* instances of this class.
*/
static pointer create();
private:
/**
* The copy constructor. It is private on purpose, use the #create class
* method instead.
*
* @param rhs
* The right hand side of the initialization.
*/
test_t1b_list(const test_t1b_list &rhs);
public:
/**
* The create class method is used to create new dynamically allocated
* instances of this class.
*
* @param rhs
* The right hand side of the initialization.
*/
static pointer create(const test_t1b_list &rhs);
/**
* The assignment operator.
*
* @param rhs
* The right hand side of the assignment.
*/
test_t1b_list &operator=(const test_t1b_list &rhs);
/**
* The size method may be used to obtain the numer of items in this
* list.
*/
size_t size() const { return length; }
/**
* The get method is used to get the n'th element of this list.
*
* @param n
* The list element of interest, zero based.
* The results are undefined if n >= size().
*/
bool &get(size_t n);
/**
* The clear method may be used to discard the list contents.
*/
void clear();
/**
* The push_back method may be used to append a value to the end of this
* list.
*
* @param value
* The value to be appended to the list.
*/
void push_back(bool value);
/**
* The introspector_factory method is used to create an introspector for
* this class and instance, usually used with the meta-data parser when
* reading the contents of a meta-data file.
*/
introspector::pointer introspector_factory();
/**
* The write method is used to write this structure's contents to the
* given output.
*
* @param fp
* Where to write the output.
* @param name
* The name of this structure member.
*/
void write(const output::pointer &fp, const nstring &name) const;
/**
* The write_xml method is used to write this structure's contents to
* the given output as XML.
*
* @param fp
* Where to write the output.
* @param name
* The name of this structure member.
*/
void write_xml(const output::pointer &fp, const nstring &name) const;
/**
* The trace_print method is used by the trace_test_t1b_list macro to
* print an object of this type.
*
* @param name
* The name of the variable being printed.
*/
void trace_print(const char *name) const;
/**
* The push_back_new_and_introspector_factory method is used to append a
* value to the end of the list, and return an introspector for managing
* that new value.
*/
introspector::pointer push_back_new_and_introspector_factory();
private:
/**
* The list instance variable is used to remember the base address of a
* dynamically allocated array of boolean values.
*/
bool *list;
public:
/**
* The list_set method is used to set the #list instance variable, and
* remember that it has been set.
*
* @param n
* The new value.
*/
void list_set(bool n);
/**
* The list_get method is used to obtain the value of the #list instance
* variable, or false if it has not been set.
*/
bool list_get() const;
/**
* The list_is_set method is used to determine whether or not the #list
* instance variable is set.
*/
bool list_is_set() const;
/**
* The list_clear method is used to clear the value of the #list
* instance variable, and remember that it is no longer set.
*/
void list_clear();
/**
* The list_introspector_factory method is used to obtain an
* introspector for the #list instance variable.
*/
introspector::pointer list_introspector_factory();
/**
* The length instance variable is used to remember the number items
* used in the #list array.
*/
size_t length;
/**
* The maximum instance variable is used to remember the number items
* allocated to the #list array.
* @note
* assert(!list == !maximum);
* assert(length <= maximum);
*/
size_t maximum;
};
#endif // TEST_T1B_LIST_DEF
#include
#ifndef test_t1b_list_trace
#ifdef DEBUG
#define test_t1b_list_trace(x) ((void)(trace_pretest_ && (trace_where_, test_t1b_list_trace_real(trace_stringize(x), x), 0)))
#else
#define test_t1b_list_trace(x)
#endif
#endif
#ifndef test_DEF
#define test_DEF
/**
* The test class is used to represent ''test'' formatted Aegis meta-data.
* See aetest(5) for more information.
*/
class test
{
public:
/**
* The pointer typedef is used to have a pointer type which may be used
* by clients of this API, allowing the pointer implementation to be
* changed without extensive code changes throughout the rest of the
* code base.
*/
typedef aegis_shared_ptr pointer;
/**
* The destructor.
*/
virtual ~test();
private:
/**
* The default constructor. It is private on purpose, use the #create
* class method instead.
*/
test();
public:
/**
* The create class method is used to create new dynamically allocated
* instances of this class.
*/
static pointer create();
private:
/**
* The copy constructor. It is private on purpose, use the #create class
* method instead.
*
* @param rhs
* The right hand side of the initialization.
*/
test(const test &rhs);
public:
/**
* The create class method is used to create new dynamically allocated
* instances of this class.
*
* @param rhs
* The right hand side of the initialization.
*/
static pointer create(const test &rhs);
/**
* The assignment operator.
*
* @param rhs
* The right hand side of the assignment.
*/
test &operator=(const test &rhs);
private:
/**
* The t1a instance variable is used to remember the boolean t1a.
*/
bool t1a: 1;
/**
* The t1a_is_set_flag instance variable is used to remember whether or
* not the #t1a instance variable has been set.
*/
bool t1a_is_set_flag: 1;
public:
/**
* The t1a_set method is used to set the #t1a instance variable, and
* remember that it has been set.
*
* @param n
* The new value.
*/
void t1a_set(bool n);
/**
* The t1a_get method is used to obtain the value of the #t1a instance
* variable, or false if it has not been set.
*/
bool t1a_get() const;
/**
* The t1a_is_set method is used to determine whether or not the #t1a
* instance variable is set.
*/
bool t1a_is_set() const;
/**
* The t1a_clear method is used to clear the value of the #t1a instance
* variable, and remember that it is no longer set.
*/
void t1a_clear();
/**
* The t1a_introspector_factory method is used to obtain an introspector
* for the #t1a instance variable.
*/
introspector::pointer t1a_introspector_factory();
private:
/**
* The t1b instance variable is used to remember the test t1b list t1b.
*/
test_t1b_list::pointer t1b;
public:
/**
* The t1b_get method is used to obtain the value of the #t1b instance
* variable. It will be created if it does not yet exist.
*/
test_t1b_list::pointer t1b_get();
/**
* The t1b_is_set method is used to determine whether or not the #t1b
* instance variable is set.
*/
bool t1b_is_set() const;
/**
* The t1b_clear method is used to clear the value of the #t1b instance
* variable, and remember that it is no longer set.
*/
void t1b_clear();
/**
* The t1b_introspector_factory method is used to obtain an introspector
* for the #t1b instance variable.
*/
introspector::pointer t1b_introspector_factory();
public:
/**
* The introspector_factory method is used to create an introspector for
* this class and instance, usually used with the meta-data parser when
* reading the contents of a meta-data file.
*/
introspector::pointer introspector_factory();
/**
* The write method is used to write this structure's contents to the
* given output.
*
* @param fp
* Where to write the output.
*/
void write(const output::pointer &fp) const;
/**
* The write_xml method is used to write this structure's contents to
* the given output as XML.
*
* @param fp
* Where to write the output.
*/
void write_xml(const output::pointer &fp) const;
/**
* The trace_print method is used by the trace_test macro to print an
* object of this type.
*
* @param name
* The name of the variable being printed.
*/
void trace_print(const char *name) const;
/**
* The create_from_file class method is used to read the given file to
* create a new dynamically allocated instance of this class.
*
* @param filename
* The name of the file to be read.
* @note
* If any errors are encountered, this method will not return. All
* errors will print a fatal error message, and exit with an exit
* status of 1.
*/
static pointer create_from_file(const nstring &filename);
/**
* The write_file method is used to write the data to the named file,
* via the #write method.
*
* @param filename
* The name of the file to be written.
* @param compress
* true if data should be compressed, false if not.
* @note
* If any errors are encountered, this method will not return. All
* errors will print a fatal error message, and exit with an exit
* status of 1.
*/
void write_file(const nstring &filename, bool compress) const;
/**
* The report_init class method is used to initialize the report
* generator with the names and values of enumerations used by this
* meta-data.
*/
static void report_init();
};
/**
* The test_trace macro is used to conditionally print a trace of a test
* value, if the DEBUG macro is defined.
*/
#ifndef test_trace
#ifdef DEBUG
#define test_trace(x) ((void)(trace_pretest_ && (trace_where_, (x).trace_print(trace_stringize(x)), 0)))
#else
#define test_trace(x)
#endif
#endif
#endif // test_DEF
#endif // TEST_FMTGEN_H
fubar
if test $? -ne 0 ; then no_result; fi
fmtgen -ii test.fmtgen.h test.def
test $? -eq 0 || fail
diff test.fmtgen.h.ok test.fmtgen.h
test $? -eq 0 || fail
cat > test.fmtgen.cc.ok << 'fubar'
//
// This file is generated by fmtgen.
//
#include
#include
#include
#include
void
test_t1b_list::write(const output::pointer &fp, const nstring &name)
const
{
trace(("%s {\n", __PRETTY_FUNCTION__));
if (name)
{
fp->fputs(name);
fp->fputs(" =\n");
}
assert(length <= maximum);
assert(!list == !maximum);
fp->fputs("[\n");
for (size_t j = 0; j < length; ++j)
{
introspector_boolean::write(fp, "list[j]", list[j], true);
fp->fputs(",\n");
}
fp->fputs("]");
if (name)
fp->fputs(";\n");
trace(("}\n"));
}
void
test_t1b_list::write_xml(const output::pointer &fp, const nstring &name)
const
{
trace(("%s {\n", __PRETTY_FUNCTION__));
assert(name);
fp->fputc('<');
fp->fputs(name);
fp->fputs(">\n");
assert(length <= maximum);
assert(!list == !maximum);
for (size_t j = 0; j < length; ++j)
{
introspector_boolean::write_xml(fp, "list[j]", list[j], true);
}
fp->fputs("");
fp->fputs(name);
fp->fputs(">\n");
trace(("}\n"));
}
test_t1b_list::test_t1b_list() :
list(0),
length(0),
maximum(0)
{
trace(("%s\n", __PRETTY_FUNCTION__));
}
test_t1b_list::~test_t1b_list()
{
trace(("%s {\n", __PRETTY_FUNCTION__));
delete [] list;
list = 0;
length = 0;
maximum = 0;
trace(("}\n"));
}
test::~test()
{
trace(("%s\n", __PRETTY_FUNCTION__));
}
test::test() :
t1a(false),
t1a_is_set_flag(false),
t1b()
{
trace(("%s\n", __PRETTY_FUNCTION__));
}
test::pointer
test::create()
{
trace(("%s\n", __PRETTY_FUNCTION__));
return pointer(new test());
}
test::test(const test &rhs) :
t1a(rhs.t1a),
t1a_is_set_flag(rhs.t1a_is_set_flag),
t1b(rhs.t1b)
{
trace(("%s\n", __PRETTY_FUNCTION__));
}
test::pointer
test::create(const test &rhs)
{
trace(("%s\n", __PRETTY_FUNCTION__));
return pointer(new test(rhs));
}
test &
test::operator=(const test &rhs)
{
trace(("%s\n", __PRETTY_FUNCTION__));
if (this != &rhs)
{
t1a = rhs.t1a;
t1a_is_set_flag = rhs.t1a_is_set_flag;
t1b = rhs.t1b;
}
return *this;
}
bool
test::t1a_get()
const
{
return t1a;
}
bool
test::t1a_is_set()
const
{
return (t1a || t1a_is_set_flag);
}
void
test::t1a_set(bool x)
{
t1a = x;
t1a_is_set_flag = true;
}
void
test::t1a_clear()
{
t1a = false;
t1a_is_set_flag = false;
}
#include
introspector::pointer
test::t1a_introspector_factory()
{
return introspector_boolean_by_method < test > ::create ( *this,
&test::t1a_set, &test::t1a_is_set);
}
test_t1b_list::pointer
test::t1b_get()
{
if (!t1b)
{
t1b = test_t1b_list::create();
}
return t1b;
}
bool
test::t1b_is_set()
const
{
return !!t1b;
}
introspector::pointer
test::t1b_introspector_factory()
{
return t1b_get()->introspector_factory();
}
#include
introspector::pointer
test::introspector_factory()
{
trace(("%s\n", __PRETTY_FUNCTION__));
introspector_structure::pointer ip =
introspector_structure::create("test");
ip->register_member ( "t1a", introspector_structure::adapter_by_method
< test > ::create ( this, &test::t1a_introspector_factory,
&test::t1a_is_set));
ip->register_member ( "t1b", introspector_structure::adapter_by_method
< test > ::create ( this, &test::t1b_introspector_factory,
&test::t1b_is_set));
return ip;
};
void
test::write(const output::pointer &fp)
const
{
trace(("%s\n{\n", __PRETTY_FUNCTION__));
introspector_boolean::write(fp, "t1a", t1a, t1a_is_set_flag);
if (t1b)
{
t1b->write ( fp, "t1b");
}
trace(("}\n"));
}
void
test::write_xml(const output::pointer &fp)
const
{
trace(("%s\n{\n", __PRETTY_FUNCTION__));
fp->fputs("\n");
introspector_boolean::write_xml(fp, "t1a", t1a, t1a_is_set_flag);
if (t1b)
t1b->write_xml(fp, "t1b");
fp->fputs("\n");
trace(("}\n"));
}
void
test::trace_print(const char *name_)
const
{
if (name_ && *name_)
{
trace_printf("%s = ", name_);
}
trace_printf("{\n");
if (t1a_is_set())
trace_bool_real("t1a", t1a_get());
if (t1b)
{
t1b->trace_print( "t1b");
}
trace_printf("}");
trace_printf((name_ && *name_) ? ";\n" : ",\n");
}
#include
#include
test::pointer
test::create_from_file(const nstring &filename)
{
trace(("%s\n{\n", __PRETTY_FUNCTION__));
pointer p = create();
introspector::pointer ip = p->introspector_factory();
meta_context_introspector meta;
os_become_must_be_active();
meta.parse_file(filename, ip);
trace(("}\n"));
return p;
}
#include
#include
#include
#include
void
test::write_file(const nstring &filename, bool needs_compression)
const
{
trace(("%s\n{\n", __PRETTY_FUNCTION__));
if (filename)
os_become_must_be_active();
output::pointer fp = (needs_compression ?
output_filter_gzip::create(output_file::binary_open(filename)) :
output_file::text_open(filename));
fp = output_filter_indent::create(fp);
io_comment_emit(fp);
write(fp);
type_enum_option_clear();
trace(("}\n"));
}
void
test::report_init(void)
{
trace(("%s\n{\n", __PRETTY_FUNCTION__));
trace(("}\n"));
}
fubar
if test $? -ne 0 ; then no_result; fi
fmtgen -ic test.fmtgen.cc test.def
test $? -eq 0 || fail
diff test.fmtgen.cc.ok test.fmtgen.cc
test $? -eq 0 || fail
#
# Only definite negatives are possible.
# The functionality exercised by this test appears to work,
# no other guarantees are made.
#
pass
// vim: set ts=8 sw=4 et :