diff --git a/SConstruct b/SConstruct index 834ca984a..d81db1408 100644 --- a/SConstruct +++ b/SConstruct @@ -196,6 +196,8 @@ elif env['CC'] == 'clang': else: print "WARNING: Unrecognized C compiler '%s'" % env['CC'] +defaults.threadFlags = '-pthread' if os.name != 'nt' else '' + # TODO: Once deprecated functions have been removed, remove the # compiler options: -Wno-deprecated-declarations and /wd4996 @@ -468,6 +470,9 @@ opts.AddVariables( ('cc_flags', 'Compiler flags passed to both the C and C++ compilers, regardless of optimization level', defaults.ccFlags), + ('thread_flags', + 'Compiler and linker flags for POSIX multithreading support', + defaults.threadFlags), BoolVariable( 'optimize', """Enable extra compiler optimizations specified by the "optimize_flags" variable, @@ -831,11 +836,13 @@ env['inst_mandir'] = pjoin(instRoot, 'man1') env['inst_matlab_dir'] = pjoin(instRoot, 'matlab', 'toolbox') env['CXXFLAGS'] = listify(env['cxx_flags']) +env['CCFLAGS'] = listify(env['cc_flags']) + listify(env['thread_flags']) +env['LINKFLAGS'] += listify(env['thread_flags']) if env['optimize']: - env['CCFLAGS'] = listify(env['cc_flags']) + listify(env['optimize_flags']) + env['CCFLAGS'] += listify(env['optimize_flags']) else: - env['CCFLAGS'] = listify(env['cc_flags']) + listify(env['no_optimize_flags']) + env['CCFLAGS'] += listify(env['no_optimize_flags']) if env['debug']: env['CCFLAGS'] += listify(env['debug_flags']) @@ -844,7 +851,6 @@ else: env['CCFLAGS'] += listify(env['no_debug_flags']) env['LINKFLAGS'] += listify(env['no_debug_linker_flags']) - if env['coverage']: if env['CC'] == 'gcc': env.Append(CCFLAGS=['-fprofile-arcs', '-ftest-coverage']) diff --git a/ext/SConscript b/ext/SConscript index 9611ce634..b5dab2ca8 100644 --- a/ext/SConscript +++ b/ext/SConscript @@ -53,7 +53,7 @@ def prep_gtest(env): return localenv # (subdir, (file extensions), prepfunction) -libs = [] +libs = [('libexecstream', ['cpp'], prep_default)] if env['build_with_f2c']: libs.append(('f2c_math', ['cpp','c'], prep_f2c)) diff --git a/ext/libexecstream/README b/ext/libexecstream/README new file mode 100644 index 000000000..e07773e9a --- /dev/null +++ b/ext/libexecstream/README @@ -0,0 +1,42 @@ +This is version 0.3 of libexecstream, a C++ library +that allows you to run a child process and have its input, +output and error avaliable as standard C++ streams. + +Copyright (c) 2004 Artem Khodush +Libexecstream is distributed under the BSD-style license, +see doc/license.html for the details. + +Documentation: + doc/index.html + http://libexecstream/sourceforge.net/ + +Features: + Works on Linux and Windows + Uses threads + Does not depend on any other non-standard library + Distributed as source code only, requires you to compile and link + one file into your program + +Installaion: + +Libexecstream is provided in source code form only. +In order to use it, you need to compile and link one file, exec-stream.cpp, +into your program. + +Header file exec-stream.h defines interface of the library and uses +only standard C++. It does not include any platform-specific header files. + +On Linux, libexecstream was tested on Red Hat 9 with gcc compiler. +Versions of gcc prior to 3.0 will not work. Make sure that exec-stream.h +is found somewhere on the include path, compile exec-stream.cpp as usual, +link your program with -lpthread. GCC must be configured with --enable-threads, +which is by default on most Linux distributions. + +On Windows, libexecstream was tested on XP and 95 flavors with VC++ 7 compiler. +VC++ 6 will not work. Make sure that exec-stream.h is found somewhere +on the include path, compile exec-stream.cpp as usual, link you program +with multi-threaded runtime. + +Example makefiles for Windows and Linux (used to build the testsute) +are provided in the test subdirectory. + diff --git a/ext/libexecstream/doc/index.html b/ext/libexecstream/doc/index.html new file mode 100644 index 000000000..eee86f261 --- /dev/null +++ b/ext/libexecstream/doc/index.html @@ -0,0 +1,163 @@ + + + + +
+| + + + + + + + + | + +
+
+
+
+Overview+ +Libexecstream is a C++ library that allows you to run a child process and have its input, output and error +avaliable as standard C++ streams. + +Like this: + +
+#include <exec-stream.h>
+#include <string>
+...
+try {
+ exec_stream_t es( "perl", "" ); // run perl without any arguments
+ es.in() << "print \"hello world\";"; // and make it print "hello world"
+ es.close_in(); // after the input was closed
+ std::string hello, world;
+ es.out() >> hello; // read the first word of output
+ es.out() >> world; // read the second word
+}catch( std::exception const & e ) {
+ std::cerr << "error: " << e.what() << "\n";
+}
+
+
+Features: +
Another example: + ++#include <exec-stream.h> +... +exec_stream_t es; +try { + // run command to print network configuration, depending on the operating system + #ifdef _WIN32 + es.start( "ipconfig", "/all" ); + #else + es.start( "ifconfig", "-a" ); + #endif + + std::string s; + while( std::getline( es.out(), s ).good() ) { + // do something with s + } +}catch( std::exception const & e ) { + std::cerr << "error: " << e.what() << "\n"; +} ++ + For more examples see the file test/exec-stream-test.cpp in the source distribution. +The interface provided by the library is documented in the reference. + + + + +Download+ +
Installation+ +Libexecstream is provided in source code form only. In order to use it, you need to compile and link +one file, exec-stream.cpp, into your program. + + +On Linux, libexecstream was tested on Red Hat 9 with gcc compiler. Versions of gcc prior to 3.0 will not work. +Make sure that exec-stream.h is found somewhere on the include path, +compile exec-stream.cpp as usual, link your program with -lpthread. +GCC must be configured with --enable-threads, which is by default on most Linux distributions. + + +On Windows, libexecstream was tested on XP and 95 flavors with VC++ 7 compiler. VC++ 6 will not work. +Make sure that exec-stream.h is found somewhere on the include path, +compile exec-stream.cpp as usual, link you program with multi-threaded runtime. + + +Example makefiles for Windows and Linux (used to build the testsute) are provided in the test directory +of the source distribution. + + +The exec-stream.cpp file includes several platform-dependent +implementation files. Selection of platform-specific implementation is done at compile time: when _WIN32 +macro is defined (usually by windows compiler) win32 implementation is included, when that macro is not defined, +posix implementation is included. + + +Header file exec-stream.h defines interface of the library and uses only standard C++. +It does not include any platform-specific header files. + + + |
+
| + + + + + + + + | + +
+
+ Libexecsteam copyright Artem Khodush, 2004. + + +License+ +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. The name of the author may not be used to endorse or promote products +derived from this software without specific prior written permission. + + ++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + + + |
+
| + + + + + + + + | + ++ +April 12, 2004. +Version 0.3 - first public release. + + | +
| + + + + + + + + | + +
+
+ Libexecstream provides one class, exec_stream_t, which has the following members: + + +class error_t : public std::exception+Exceptions thrown from exec_stream_t members are derived from error_t. error_t is derived from std::exception and has no additional +public members besides constructors. Exceptions may be thrown from any exec_stream_t member function except destructor and accessors: in(), out() and err(). +Writing to in() and reading out() and err() will also throw exceptions when errors occur. + + +exec_stream_t()+Constructs exec_stream_t in the default state. You may change timeouts, buffer limits and text or binary modes +of the streams before starting child process (see set_buffer_limit, +set_binary_mode, set_text_mode, +set_wait_timeout). In the default state, amount of data buffered for writing to child's stdin, +and amount of data read in advance from child's stdout and stderr is unlimited. On windows, all streams are in the text mode. + + +exec_stream_t( std::string const & program, std::string const & arguments )+Constructs exec_stream_t in the default state, then starts program with arguments. Arguments containing space should be +included in double quotation marks, and double quote in such arguments should be escaped with backslash. + + +template< class iterator > exec_stream_t( std::string const & program, iterator args_begin, iterator args_end )+Constructs exec_stream_t in the default state, then starts program with arguments specified by the range args_begin, args_end. +args_begin should be an input iterator that when dereferenced gives value assignable to std::string. +Spaces and double quotes in arguments need not to be escaped. + + +~exec_stream_t()+Writes (with timeout) all pending data to child stdin, +closes streams and waits (with timeout) for child process to stop. + + +std::ostream & in()+Returns output stream for writing to child's stdin. + + +std::istream & out()+Returns input stream for reading child's stdout. + + +std::istream & err()+Returns input stream for reading child's stderr. + + +bool close_in()+Closes child's standard input after writing (with timeout) all pending data to it. + + +void start( std::string const & program, std::string const & arguments )+Starts program with arguments. Arguments are space-separated. Arguments containing space should be +included in double quotation marks, and double quote in such arguments should be escaped with backslash. + + +template< class iterator > void start( std::string const & program, iterator args_begin, iterator args_end )+Starts program with arguments specified by the range args_begin, args_end. args_begin should be an input iterator that when dereferenced +gives value assignable to std::string. Spaces and double quotes in arguments need not to be escaped. + + +enum stream_kind_t { s_in=1, s_out=2, s_err=4, s_all=s_in|s_out|s_err, s_child=8 }+Used for the first argument to set_buffer_limit, set_wait_timeout, +set_binary_mode, set_text_mode for selecting stream to operate upon. + + +void set_buffer_limit( int stream_kind, std::size_t size )+For out() and err() streams (when exec_stream_t::s_out +or exec_stream_t::s_err is set in the stream_kind), sets maximum amount of data to read from child process +before it will be consumed by reading from out() or err(). + +For in() stream (when exec_stream_t::s_in is set in the stream_kind) +sets maximum amount of data to store as result of writing to in() before it will be consumed by child process. + +Setting limit for both input and output streams may cause deadlock in situations when both your program and child process +are writing data to each other without reading it. Such deadlock will cause the timeout to expire while +writing to in(). + +When size argument to set_buffer_limit is 0, buffers are considered unlimited, and will grow unlimited if one side produce data that the other side does not consume. +This is the default state after exec_stream_t creation. + +set_buffer_limit will throw exception when called while child process is running. + + +typedef unsigned long timeout_t+Type of second argument to set_wait_timeout - timeout in milliseconds. + + +void set_wait_timeout( int stream_kind, timeout_t milliseconds )+For out() and err() streams (when exec_stream_t::s_out +or exec_stream_t::s_err is set in the stream_kind), sets maximum amount of time to wait for a +child process to produce data when reading out() and err() respectively. + +For in() stream (when exec_stream_t::s_in is set in the stream_kind), +sets maximum amount of time to wait for a child process to consume data that were written to in(). +Note that when buffer limit for in() is not set, writing to in() always writes to buffer and does not wait for child at all. + +If that amount of time is exceeded while reading in() or writing to out() and err(), exception is thrown. + +When exec_stream_t::s_child is set in the stream kind, set_wait_timeout sets the maximum amount of time to wait +for a child process to terminate when close is called. If that amount of time is exceeded, close() will return false. + +set_wait_timeout will throw exception when called while child process is running. + + +void set_text_mode( int stream_kind )++sets stream specified by stream_kind to text mode. In text mode, in the data written to child's stdin, +\n are replaced by \r\n; and in the data read from child's stdout and stderr, \r\n are replaced by \n. Text mode is the default on Windows. +set_text_mode has no effect on Linux. + +set_text_mode will throw exception when called while child process is running. + + +void set_binary_mode( int stream_kind )++sets stream specified by stream_kind to binary mode. All data written or read from streams are passed unchanged. +set_binary_mode has no effect on Linux. + +set_binary_mode will throw exception when called while child process is running. + + +bool close()+Writes (with timeout) all pending data to child stdin, +closes streams and waits (with timeout) for child process to stop. +If timeout expires while waiting for child to stop, returns false. Otherwise, returns true. + + +void kill()++Terminates child process, without giving it a chance of proper shutdown. + + +int exit_code()+Returns exit code from child process. Exit code usually is available only after close. Exception is thrown if chid process +has not yet terminated. Exit code has indeterminable value after kill. + + + + |
+