#!/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, enum" # load up standard prelude and test functions . test_funcs # # test the include file # activity="fmtgen -ii enum" cat > test.def << 'fubar' /* * The comment attached to ''one'' in the .def file. */ one = (two, three, four); fubar test $? -eq 0 || no_result cat > test.fmtgen.h.ok << 'fubar' // // This file is generated by fmtgen. // #ifndef TEST_FMTGEN_H #define TEST_FMTGEN_H #include #include #ifndef TEST_ONE_DEF #define TEST_ONE_DEF enum test_one_ty { test_one_two, test_one_three, test_one_four }; #define test_one_max 3 #include /** * The introspector_enumeration_test_one class is used to represent how the * meta-data parser manipulates a test_one_ty variable. */ class introspector_enumeration_test_one: public introspector_enumeration { public: /** * The destructor. */ virtual ~introspector_enumeration_test_one(); private: /** * The constructor. It is private on purpose, use the #create class * method instead. * * @param how * This argument is used to describe how to actually manipulate a * field of test_one_ty enumerated type in a meta-data structure. */ introspector_enumeration_test_one(const introspector_enumeration::adapter::pointer &how); public: /** * The create class method is used to create new dynamically allocated * instances of this class. * * @param how * This argument is used to describe how to actually manipulate a * field of test_one_ty enumerated type in a meta-data structure. */ static pointer create(const introspector_enumeration::adapter::pointer &how); /** * The ename class method is used to obtain the string corresponding to * given value. * * @param value * The value to be translated. */ static nstring ename(test_one_ty value); /** * The report_init class method is used to initialize the report * generator with the names and values of this enumeration`s tags. */ static void report_init(void); /** * The write class method is used to write a test_one value to the given * output. * * @param fp * The output stream to write on. * @param name * The name of the field. * @param value * The value to be printed. * @param show * true means show even if defult value, false means show only if * not default value. */ static void write(const output::pointer &fp, const char *name, test_one_ty value, bool show); /** * The write_xml class method is used to write a test_one value as XML * to the given output. * * @param fp * The output stream to write on. * @param name * The name of the XML element. * @param value * The value to be printed. * @param show * true means show even if defult value, false means show only if * not default value. */ static void write_xml(const output::pointer &fp, const char *name, test_one_ty value, bool show); /** * The trace_print class method is used to write a test_one value via * trace_printf. Used by the #test_one_trace macro. * * @param name * The name of the variable being printed. * @param value * The value to be printed. */ static void trace_print(const char *name, test_one_ty value); private: /** * The default constructor. Do not use. */ introspector_enumeration_test_one(); /** * The copy constructor. Do not use. */ introspector_enumeration_test_one(const introspector_enumeration_test_one &); /** * The assignment operator. Do not use. */ introspector_enumeration_test_one &operator=(const introspector_enumeration_test_one &); }; /** * The test_one_trace macro is used to conditionally print a trace of a * test_one value, if the DEBUG macro is defined. */ #include #ifndef test_one_trace #ifdef DEBUG #define test_one_trace(x) ((void)(trace_pretest_ && (trace_where_, introspector_enumeration_test_one::trace_print(trace_stringize(x), (x)), 0))) #else #define test_one_trace(x) #endif #endif #endif // TEST_ONE_DEF #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 comment attached to ''one'' in the .def file. */ test_one_ty one: 2; /** * The one_is_set_flag instance variable is used to remember whether or * not the #one instance variable has been set. */ bool one_is_set_flag: 1; public: /** * The one_get method is used to obtain the value of the one instance * variable, or the default if it has not been set. */ test_one_ty one_get() const; /** * The one_is_set method is used to determine whether or not the one * instance variable has been set. */ bool one_is_set() const; /** * The one_set method is used to set the value of the #one instance * variable, and record that it has been set. */ void one_set(test_one_ty value); /** * The one_clear method is used to reset the the #one instance variable * to its default value, and record that it is no longer set. */ void one_clear(); /** * The one_introspector_factory method is used to obtain an introspector * for the #one instance variable. */ introspector::pointer one_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 test $? -eq 0 || no_result fmtgen -ii test.fmtgen.h test.def; test $? -eq 0 || fail diff test.fmtgen.h.ok test.fmtgen.h test $? -eq 0 || fail # # test the code file # activity="fmtgen -ic enum" cat > test.fmtgen.cc.ok << 'fubar' // // This file is generated by fmtgen. // #include #include static const char *test_one_s[] = { "two", "three", "four", }; introspector_enumeration_test_one::~introspector_enumeration_test_one() { } introspector_enumeration_test_one::introspector_enumeration_test_one(const adapter::pointer &arg) : introspector_enumeration("test_one", arg) { register_tags(test_one_s, SIZEOF(test_one_s)); } introspector::pointer introspector_enumeration_test_one::create(const adapter::pointer &arg) { return pointer(new introspector_enumeration_test_one(arg)); } nstring introspector_enumeration_test_one::ename(test_one_ty value) { if (int(value) >= 0 && value < test_one_max) return test_one_s[value]; return nstring::format("%d", int(value)); } #include #include void introspector_enumeration_test_one::write(const output::pointer &fp, const char *name, test_one_ty value, bool show) { if (value == 0) { if (!show || type_enum_option_query()) return; } if (name) { fp->fputs(name); fp->fputs(" = "); } assert(value < test_one_max); fp->fputs(test_one_s[value]); if (name) fp->fputs(";\n"); } void introspector_enumeration_test_one::write_xml(const output::pointer &fp, const char *name, test_one_ty value, bool show) { if (value == 0) { if (!show || type_enum_option_query()) return; } assert(name); assert(value < test_one_max); fp->fputc('<'); fp->fputs(name); fp->fputc('>'); fp->fputs(test_one_s[value]); fp->fputs("fputs(name); fp->fputs(">\n"); } void introspector_enumeration_test_one::report_init() { introspector_enumeration::report_init(test_one_s, SIZEOF(test_one_s)); } #include test::~test() { trace(("%s\n", __PRETTY_FUNCTION__)); } test::test() : one(test_one_two), one_is_set_flag(false) { trace(("%s\n", __PRETTY_FUNCTION__)); } test::pointer test::create() { trace(("%s\n", __PRETTY_FUNCTION__)); return pointer(new test()); } test::test(const test &rhs) : one(rhs.one), one_is_set_flag(rhs.one_is_set_flag) { 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) { one = rhs.one; one_is_set_flag = rhs.one_is_set_flag; } return *this; } test_one_ty test::one_get() const { return one; } bool test::one_is_set() const { return (one || one_is_set_flag); } void test::one_set(test_one_ty x) { one = x; one_is_set_flag = true; } void test::one_clear() { one = test_one_two; one_is_set_flag = false; } introspector::pointer test::one_introspector_factory() { return introspector_enumeration_test_one::create ( introspector_enumeration::adapter_by_method < test, test_one_ty > ::create ( this, &test::one_set, &test::one_is_set)); } #include introspector::pointer test::introspector_factory() { trace(("%s\n", __PRETTY_FUNCTION__)); introspector_structure::pointer ip = introspector_structure::create("test"); ip->register_member ( "one", introspector_structure::adapter_by_method < test > ::create ( this, &test::one_introspector_factory, &test::one_is_set)); return ip; }; void test::write(const output::pointer &fp) const { trace(("%s\n{\n", __PRETTY_FUNCTION__)); introspector_enumeration_test_one::write(fp, "one", one, false); trace(("}\n")); } void test::write_xml(const output::pointer &fp) const { trace(("%s\n{\n", __PRETTY_FUNCTION__)); fp->fputs("\n"); introspector_enumeration_test_one::write_xml(fp, "one", one, false); fp->fputs("\n"); trace(("}\n")); } void test::trace_print(const char *name_) const { if (name_ && *name_) { trace_printf("%s = ", name_); } trace_printf("{\n"); trace_string_real("one", introspector_enumeration_test_one::ename(one)); 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__)); introspector_enumeration_test_one::report_init(); trace(("}\n")); } fubar test $? -eq 0 || no_result 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 :