From bd9b2bd740b6722535f1039a720b28d687674c1a Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 1 Jun 2015 10:03:14 -0600 Subject: [PATCH] Add hello++5 to ELF example. From Leo Aloe3132 --- examples/elf/tests/helloxx/.gitignore | 3 +- examples/elf/tests/helloxx/Makefile | 26 +-- examples/elf/tests/helloxx/hello++5.cpp | 297 ++++++++++++++++++++++++ 3 files changed, 311 insertions(+), 15 deletions(-) create mode 100644 examples/elf/tests/helloxx/hello++5.cpp diff --git a/examples/elf/tests/helloxx/.gitignore b/examples/elf/tests/helloxx/.gitignore index 8efbe3826..049b72312 100644 --- a/examples/elf/tests/helloxx/.gitignore +++ b/examples/elf/tests/helloxx/.gitignore @@ -2,5 +2,4 @@ hello++1 hello++2 hello++3 hello++4 - - +hello++5 \ No newline at end of file diff --git a/examples/elf/tests/helloxx/Makefile b/examples/elf/tests/helloxx/Makefile index 260b83cc0..4ab072a21 100644 --- a/examples/elf/tests/helloxx/Makefile +++ b/examples/elf/tests/helloxx/Makefile @@ -1,7 +1,7 @@ ############################################################################ # examples/elf/tests/helloxx/Makefile # -# Copyright (C) 2012, 2014 Gregory Nutt. All rights reserved. +# Copyright (C) 2012, 2014-2015 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -69,9 +69,10 @@ ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y) BIN3 = hello++3 ifeq ($(CONFIG_EXAMPLES_ELF_UCLIBCXX),y) BIN4 = hello++4 +BIN5 = hello++5 endif endif -ALL_BIN = $(BIN1) $(BIN2) $(BIN3) $(BIN4) +ALL_BIN = $(BIN1) $(BIN2) $(BIN3) $(BIN4) $(BIN5) SRCS1 = $(BIN1).c OBJS1 = $(SRCS1:.c=$(OBJEXT)) @@ -85,17 +86,18 @@ OBJS3 = $(SRCS3:.c=$(OBJEXT)) ifeq ($(CONFIG_EXAMPLES_ELF_UCLIBCXX),y) SRCS4 = $(BIN4).c OBJS4 = $(SRCS4:.c=$(OBJEXT)) +SRCS5 = $(BIN5).c +OBJS5 = $(SRCS5:.c=$(OBJEXT)) endif endif - -SRCS = $(SRCS1) $(SRCS2) $(SRCS3) $(SRCS4) -OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) +SRCS = $(SRCS1) $(SRCS2) $(SRCS3) $(SRCS4) $(SRCS5) +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) $(OBJS5) LDLIBSTDC_STUBS_DIR = $(TOPDIR)/libxx LDLIBSTDC_STUBS_LIB = $(LDLIBSTDC_STUBS_DIR)/liblibxx.a -all: $(BIN1) $(BIN2) $(BIN3) $(BIN4) +all: $(BIN1) $(BIN2) $(BIN3) $(BIN4) $(BIN5) $(OBJS): %$(OBJEXT): %.cpp @echo "CC: $<" @@ -135,6 +137,9 @@ ifeq ($(CONFIG_EXAMPLES_ELF_UCLIBCXX),y) $(BIN4): $(OBJS4) @echo "LD: $<" $(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $@ $(ARCHCRT0OBJ) $^ $(LDLIBS) +$(BIN5): $(OBJS5) + @echo "LD: $<" + $(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $@ $(ARCHCRT0OBJ) $^ $(LDLIBS) endif endif @@ -143,6 +148,7 @@ clean: $(call DELFILE, $(BIN2)) $(call DELFILE, $(BIN3)) $(call DELFILE, $(BIN4)) + $(call DELFILE, $(BIN5)) $(call CLEAN) install: $(ALL_BIN) @@ -153,12 +159,6 @@ ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y) $(Q) install $(BIN3) $(ROMFS_DIR)/$(BIN3) ifeq ($(CONFIG_EXAMPLES_ELF_UCLIBCXX),y) $(Q) install $(BIN4) $(ROMFS_DIR)/$(BIN4) + $(Q) install $(BIN5) $(ROMFS_DIR)/$(BIN5) endif endif - - - - - - - diff --git a/examples/elf/tests/helloxx/hello++5.cpp b/examples/elf/tests/helloxx/hello++5.cpp new file mode 100644 index 000000000..165ac4c07 --- /dev/null +++ b/examples/elf/tests/helloxx/hello++5.cpp @@ -0,0 +1,297 @@ +///////////////////////////////////////////////////////////////////////////// +// examples/elf/tests/helloxx/hello++5.c +// +// Copyright (C) 2015 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. 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. +// 3. Neither the name NuttX 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. +// +///////////////////////////////////////////////////////////////////////////// +// +// This is an excessively complex version of "Hello, World" design to +// illustrate some basic properties of C++: +// +// - Building a C++ program +// - Streams / statically linked libstdc++ +// - Static constructor and destructors (in main program only) +// - Exception handling +// +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +#ifndef NULL +# define NULL ((void*)0L) +#endif + +///////////////////////////////////////////////////////////////////////////// +// Private Classes +///////////////////////////////////////////////////////////////////////////// + +using namespace std; + +// A hello world sayer class + +class CThingSayer +{ + const char *szWhatToSay; +public: + CThingSayer(void); + virtual ~CThingSayer(void); + virtual void Initialize(const char *czSayThis); + virtual void SayThing(void); + virtual void ThrowThing(void); + virtual void ThrowMyThing(const char *czSayThis); +}; + +class MyException: public std::exception +{ + std::string reason; + +public: + virtual ~MyException() throw(); + MyException(); + MyException(std::string r); + + virtual const char *what() const throw(); +}; + +///////////////////////////////////////////////////////////////////////////// +// Private Data +///////////////////////////////////////////////////////////////////////////// + +// A static instance of the CThingSayer class. This instance MUST +// be constructed by the system BEFORE the program is started at +// main() and must be destructed by the system AFTER the main() +// returns to the system + +static CThingSayer MyThingSayer; + +///////////////////////////////////////////////////////////////////////////// +// MyException Method Implementations +///////////////////////////////////////////////////////////////////////////// + +MyException::MyException(std::string r = NULL) : reason(r) +{ + if( r.length() > 0 ) + { + cout << "MyException(" << r << "): constructing with reason." << endl; + } + else + { + cout << "MyException(): constructing." << endl; + } +} + +MyException::~MyException() throw() +{ + cout << "~MyException(): destructing." << endl; +} + +const char *MyException::what() const throw() +{ + return reason.c_str(); +} + +///////////////////////////////////////////////////////////////////////////// +// CThingSayer Method Implementations +///////////////////////////////////////////////////////////////////////////// + +// These are implementations of the methods of the CThingSayer class + +CThingSayer::CThingSayer(void) +{ + cout << "CThingSayer::CThingSayer: I am!" << endl; + szWhatToSay = (const char*)NULL; +} + +CThingSayer::~CThingSayer(void) +{ + cout << "CThingSayer::~CThingSayer: I cease to be" << endl; + if (szWhatToSay) + { + cout << "CThingSayer::~CThingSayer: I will never say '" + << szWhatToSay << "' again" << endl; + } + szWhatToSay = (const char*)NULL; +} + +void CThingSayer::Initialize(const char *czSayThis) +{ + cout << "CThingSayer::Initialize: When told, I will say '" + << czSayThis << "'" << endl; + szWhatToSay = czSayThis; +} + +void CThingSayer::SayThing(void) +{ + cout << "CThingSayer::SayThing: I am now saying '" + << szWhatToSay << "'" << endl; +} + +void CThingSayer::ThrowThing(void) +{ + cout << "CThingSayer::ThrowThing: I am now throwing an exception." << endl; + throw exception(); +} + +void CThingSayer::ThrowMyThing(const char *czSayThis = NULL) +{ + cout << "CThingSayer::ThrowMyThing: I am now throwing an MyException (with reason)." << endl; + throw MyException( string(czSayThis) ); +} + +///////////////////////////////////////////////////////////////////////////// +// Public Functions +///////////////////////////////////////////////////////////////////////////// + +int main(int argc, char **argv) +{ + // We should see the message from constructor, CThingSayer::CThingSayer(), + // BEFORE we see the following messages. That is proof that the + // C++ static initializer is working + + cout << "main: Started" << endl; + + // Tell MyThingSayer that "Hello, World!" is the string to be said + + cout << "main: Calling MyThingSayer.Initialize" << endl; + MyThingSayer.Initialize("Hello, World!"); + + // Tell MyThingSayer to say the thing we told it to say + + cout << "main: Calling MyThingSayer.SayThing" << endl; + MyThingSayer.SayThing(); + + // Test Static object throwing std::exception located in flash + + try + { + cout << "main: Calling MyThingSayer.ThrowThing (and catching it)" << endl; + MyThingSayer.ThrowThing(); + } + + catch (const exception& e) + { + cout << "main: Caught exception: " << e.what() << endl; + } + + // Test Static object throwing MyException shipped in the ELF and located in RAM. + + try + { + cout << "main: Calling MyThingSayer.ThrowMyThing (and catching it)" << endl; + MyThingSayer.ThrowMyThing(); + } + + catch (const MyException& e) + { + cout << "main: Caught MyException: " << e.what() << endl; + } + + // Testing with a local object + + CThingSayer localMyThingSayer; + + cout << "main: Calling localMyThingSayer.Initialize" << endl; + localMyThingSayer.Initialize("Repeat in heap."); + cout << "main: Calling localMyThingSayer.SayThing" << endl; + localMyThingSayer.SayThing(); + + // Test local object throwing std::exception located in flash + + try + { + cout << "main: Calling localMyThingSayer.ThrowThing (and catching it)" << endl; + localMyThingSayer.ThrowThing(); + } + + catch (const exception& e) + { + cout << "main: Caught exception: " << e.what() << endl; + } + + catch (const MyException& e) + { + cout << "main: Caught MyException: " << e.what() << endl; + } + + // Test local object throwing MyException shipped in the ELF and located in RAM. + // Also testing the action record selection logic trying different sorting of the + // catch clauses + + try + { + cout << "main: Calling localMyThingSayer.ThrowMyThing (and catching it)" << endl; + localMyThingSayer.ThrowMyThing(); + } + + catch (const exception& e) + { + cout << "main: Caught exception: " << e.what() << endl; + } + + catch (const MyException& e) + { + cout << "main: Caught MyException: " << e.what() << endl; + } + + // AGAING: Test local object throwing MyException shipped in the ELF and located in RAM. + // Also testing the action record selection logic trying different sorting of the + // catch clauses + + try + { + cout << "main: Calling localMyThingSayer.ThrowMyThing (and catching it)" << endl; + localMyThingSayer.ThrowMyThing("Custom Reason."); + } + + catch (const MyException& e) + { + cout << "main: Caught MyException: " << e.what() << endl; + } + + catch (const exception& e) + { + cout << "main: Caught exception: " << e.what() << endl; + } + + // We are finished, return. We should see the message from the + // destructor, CThingSayer::~CThingSayer(), AFTER we see the following + // message. That is proof that the C++ static destructor logic + // is working + + cout << "main: Returning" << endl; + return 0; +}