The C++ Console Tool Set (CTS)
Version 0.86
2.
Command-line argument parser
Argument
syntax supported by CTS..
Argument
specification example
Argument
specification guidelines
Obtain
unbound argument values.
Compiling
CTS and test programs
The C++ Console Tool Set (CTS) is a small and light-weight open source set
of utility classes mainly for console applications.
CTS consists of a command-line
argument parser, a thread-safe logging service and other utility classes
(string tokenizer, timer, file and directory walker, …).
See more details in the following sections. You can also refer to the code
documentation for programming interfaces.
Note: CTS is NOT really cross-platform. It has been tested on Windows (XP,
The CTS command-line argument parser simplifies how arguments are handled
by a program. Developer specifies requirements of command-line arguments (how
they look like, whether they are optional/required, …)
the parser will make sure that the real input arguments match that
specification and provides functions to retrieve them.
The argument parser supports the
POSIX and GNU program argument syntax conventions [1], in which an option
either is a dash followed by a single character or starts with two dashes and
followed by characters or dashes, e.g. -f
or --input-file. On Windows, besides
POSIX and GNU conventions, option can be introduced by a slash, e.g. /I.
Option input by user can appear
multiple times and come in any order. An option can be referred to by any name
in its specification. If you have both -f
and --input-file for the same option,
you can refer to it with either of them.
$ editor -f
/home/user/readme.txt
is the same
as:
$ editor –-input-file
/home/user/readme.txt
CTS argument parser also supports Windows-style argument conventions, where an option starts with a
slash. Note that in Windows-style options are NOT case-sensitive.
C:\>
editor /f readme.txt
Depending on the code is compiled on Unix or Windows, the argument style is set accordingly. You
can also set it manually in your code before handleUsage() is
called, but this is not recommended.
CtsConsole::setConsoleStyle(CTS_WIN); // set Windows argument style
CtsConsole::setConsoleStyle(CTS_UNIX); // set Unix argument style
The following describes how arguments can be provided
in various ways supported by CTS command line argument parser:
+ Argument comes after option, separated by white
spaces
$ editor -f /home/user/readme.txt
+ Option is followed directly by argument
$ compiler -I/usr/include
+ Option equals argument
$ compiler
--include-dir=/usr/include
+ numeric option
$ editor +10 -f
/home/user/readme.txt
+ Combined flags
$ decompressor -xvf
/home/user/download/documents.tar
There are rules for option
specification but they are pretty strait-forward. Let's take an example:
#include "cts.hpp"
const char* DESCRIPTION = "My application";
const char* COPYRIGHT = "My company";
const char* USAGE = "(-s --server <host name>) # Server name\n"
"(-u --user <user ID>) # User name to log in\n"
"[-p --password <password>] # User's
password\n"
"[-t --trace [<trace file>]]
# Turn on tracing\n"
"[-v --verbose] # Show more details\n"
"[-q --quiet] # Silent mode\n";
using namespace cts;
int main(int argc, const char* argv[]) {
CtsConsole console(argc,
argv, DESCRIPTION, COPYRIGHT);
if (!console.handleUsage(USAGE))
return -1;
CtsConsole::format("Server", console.getOptionValue("server"));
CtsConsole::format("User ID", console.getOptionValue("user"));
}
The variable USAGE specifies 5
options, in which the first 2 options are required, the rest is optional.
Option "(-s --server <host name>) # Server
name\n" is required, it can be refered to either by -s or --server, and has a required argument <host name>.
Option "(-u --user <user ID>) # User name to log
in\n" is
required, it can be refered to either by -u or --user, and has
a required argument <user ID>.
Option "[-p --password <password>] # User's
password\n" is optional, it can be refered to either by -p or --password, and has a required argument <password>.
Option "[-t --trace [<trace file>]] # Turn on
tracing\n" is optional, it can be refered to either by -t or --trace, and has an optional argument <trace file>.
Option "[-v --verbose] # Show more details\n" is optional,
it can be refered to either by -v or --verbose, and has no argument (also called
a flag).
Option "[-q --quiet] # Silent mode\n" is optional,
it can be refered to either by -q or --quiet, and has no argument (also called
a flag).
The code in main() instantiates a CtsConsole
variable and calls its function handleUsage(). This function analyses the
option specification and checks that user's input matches this specification.
In case there is some mismatch it prints the error messages to standard output
and returns false. Otherwise the program proceeds showing real arguments server
and user ID as you see below:
TESTPROGRAM /server http://gmail.com /user linhmt
My company
TESTPROGRAM – My
application
Server..................................: http://gmail.com
User ID.................................:
linhmt
The example above should give you
some ideas about how argument specification should look like. Specification of
an option usually consists of option names, arguments and an optional
description. In the example above, -s and –-server
are option names, <host name> is an argument, and "Server
name to connect to" is the option description. Following is some
guidelines:
- An option can have multiple
distinct names starting with one or two dashes (Unix)
or a slash (Windows). Option names are interchangable.
- A non-option token is considered
a formal argument. Arguments with multiple words must be surrounded by angle
brackets, e.g. <this is an argument>.
- An option or argument is optional
if it is surrounded by square brackets, e.g. [<trace file>].
- Option description is separated with the previous part of option
specification by a # character.
- Options MUST be separated by a
new line character.
- Option names must be unique.
- Option name followed directly by
an argument name in angle brackets indicates that the argument can follow the
option name directly in the command-line input. e.g.
[-I<include dir>
--include-dir=<include dir>] # add directory to search path
- An option may not have
description, argument or even option name. If an option has argument but no
option name, the argument is called an unbound argument (not bound to nay
option), e.g. <src. file> <desc. file>
CTS argument parser does not handle
contraints among options. For instance, if you have two options –verbose and
–quiet that cannot show up together, it is developer’s responsibility to check
and handle that. The following pseudo code describes this situation.
if
(console.hasOption(“verbose”) && console.hasOption(“quiet”)) {
console.error(“Program can only run either in verbose or quiet mode”);
return RC_ERROR;
}
The CtsConsole class provides the following functions
to retrieve the number and values of the option's arguments:
const int getNumberOfOptionValues(const char* cpszOptionName);
Funtion getNumberOfOptionValues() returns
the number of argument values of the option. It returns zero if the option name
is not found, or no argument values are provided by use (e.g. optional
argument).
const int getNumberOfUnboundOptionValues();
Function getNumberOfUnboundOptionValues() returns
the number of unbound argument values. It returns zero if the no argument
values were provided by user.
const char* getOptionValue(const char* cpszOptionName, const int idx = 0);
Function getOptionValue() returns a
pointer to the argument value provided by user. It returns NULL if the option
name is not found or the argument index is not in the range [0..number of arguments – 1].
const char* getUnboundOptionValue(const int idx = 0);
Function getUnboundOptionValue() returns a
pointer to the unbound argument value provided by user. It returns NULL if no
unbound argument values are provided by user.
The following shows how you can
loop over all argument values of the option server using a for
loop, and refer to particular argument value by its index.
for (int i = 0; i < console.getNumberOfOptionValues("server"); i++) {
CtsConsole::format("Server", console.getOptionValue("server", i));
}
The following shows how you can loop over all unbound
argument values using a for loop and refer to particular argument value by
its index.
for (int i = 0; i < console.getNumberOfUnboundOptionValues();
i++) {
CtsConsole::format("Argument", console.getUnboundOptionValue(i));
}
For more
on how to use this class, please look into the test programs provided together
with CTS code.
CTS provides you with a light-weight, easy and
thread-safe logging capability, with which you can keep track the contexts of
application runs. You can write log data to console, to files, or both. This is
achieved by retrieving a logger and attaching log handlers to your logger
intance. When you log data via a logger, the data is forwarded to all handlers attached to it,
which write to log output destinations. Loggers are referenced by name so a
logger can be refered to from anywhere via its name.
Each logging command and each
logger has a level of logging. There are 6 levels: SEVERE, ERROR, WARNING, INFO,
FINE and FINEST. SEVERE is the lowest and FINEST is the highest level.
The level of a logging command indicates the severity of the log message. The level of a logger indicates the highest level of logging commands it
will process. For instance, when a logger is set to level INFO, all logging
commands at level FINE or FINEST are not processed. The level of a logger can
be set by dynamically in code or configured in logging configuration file at
run-time.
CtsLogger::setLogLevel(CtsLogLevel
level);
where can take values CtsSevere,
CtsError, CtsWarning, CtsInfo, CtsFine, CtsFinest. To log a message with specific logging level, you
call the following functions:
CtsLogger::severe(const
char* format, ...);
CtsLogger::error(const char* format, ...);
CtsLogger::warning(const char* format, ...);
CtsLogger::info(const char* format, ...);
CtsLogger::fine(const char* format, ...);
CtsLogger::finest(const char* format, ...);
The following is an example
of using CTS logging in a function:
/**
* Compress file
*/
RC_CODE
compress(CtsConsole & console,
const char * & filename,
const OutputFormat & format,
void * buffer,
int & size)
{
CtsLoggerRef logger = CtsLogManager::getCtsLogger(“dblogger”);
//
logging with finest when trace is turned on
if
(console.hasOption(“trace”) {
logger.setLogLevel(CtsFinest);
}
try {
logger.finest(“Compressing
file %s”, filename);
float ratio = 1;
switch (format) {
case FORMAT_ZIP: {
logger.info(“Output
format ZIP”);
ratio=
compress_zip(format, buffer, size);
break;
}
case FORMAT_RAR: {
logger.info(“Output
format RAR”);
ratio= compress_RAR(format,
buffer, size);
break;
}
case FORMAT_LZ: {
logger.info(“Output
format LZ”);
ratio=
compress_LZ(format, buffer, size);
break;
}
case FORMAT_TAR: {
logger.info(“Output
format TAR”);
ratio=
compress_TAR(format, buffer, size);
break;
}
default: {
logger.error(“Unsupported
compression format”);
break;
}
}
logger.finest(“Compression
ratio: %f”, ratio);
}
catch (Exception & e) {
logger.severe(“Compressing
file failed: %s”, e.what());
return RC_ERROR;
}
return RC_SUCCESS;
}
A log message written
by handlers may contain timestamp when it is executed, the level of the message,
ID of the thread that executed the log command, the message itself, the source
code origin (including source file name, line number and function name) and
Nested Diagnostic Context information (that tells you what thread this message
is from). Sometimes it is unnecessary to have the source origin logged, or when
timestamp is not needed, you can in some extent set what of the above
information should be ignored by setting/configuring the logger's level of
details. There are 3 levels: LOW, MEDIUM, HIGH, with which more details are
written to output respectively. Note that when you call the logging functions mentioned
above, no source origin is passed to log handlers, therefore source origin is
not written to log entries even when you set logging detail to HIGH.
In
order to make source origin available in log entries, you must instead call the
following version of the functions, where the first parameter CTS_ORIGIN, a
macro defined by CTS, is required:
CtsLogger::severe(CTS_ORIGIN, const char* format, ...);
CtsLogger::error(CTS_ORIGIN, const char* format, ...);
CtsLogger::warning(CTS_ORIGIN, const char* format, ...);
CtsLogger::info(CTS_ORIGIN, const char* format, ...);
CtsLogger::fine(CTS_ORIGIN, const char* format, ...);
CtsLogger::finest(CTS_ORIGIN, const char* format, ...);
The following is part of a
log file generated by a CTS logging test program:
10-05-2010
15:49:55.500 ERROR 6132 Error 2 [test/testlogger.cpp:68 doLogging]
Thread_5
10-05-2010
15:49:55.500 ERROR 7944 Error 1 [test/testlogger.cpp:68 doLogging]
Thread_8
10-05-2010
15:49:55.500 ERROR 3936 Error 2 [test/testlogger.cpp:68 doLogging]
Thread_1
10-05-2010
15:49:55.500 ERROR 3164 Error 0 [test/testlogger.cpp:68 doLogging]
Thread_16
10-05-2010
15:49:55.500 ERROR 5496 Error 0 [test/testlogger.cpp:68 doLogging]
Thread_15
10-05-2010
15:49:55.500 WARNING 4084 Warning 1
[test/testlogger.cpp:69 doLogging] Thread_9
The log file was
generated with detail level HIGH. The first column contains the timestamps when
the log entries were written, the second column shows the logging level of each
entry, the third one shows ID of the calling thread, the rest contains the log
messages, which is for demonstration purpose very simple, the source origin and
function name surrounded by square brackets, and finally the Nested Diagnostic
Context - the unique string that identifies a thread. In this case NDC is made
of with Thread_ followed by the order of the thread in which it was created.
Logging is expensive
with respect to performance. At run-time you may set the logger's levels and
details in the CTS logging configuration file to control what to be logged.
However you could also completely disable logging by turning off option
CtsEnableLogging, note that even though, log files are still created by log
handlers and filled with some logging configuration. Alternatively you can also
dynamically pause and resume logging using functions CtsLogger::pause() and CtsLogger::resume() in your code.
CTS logging implements a
file rolling policy to control the log file size and number of files. The
policy allows you to specify a maximal file size and number of log files to be
created. Log files are numbered from 1 to N (number of log files). Initially, a
log file with index 1 is created and written to. When the log file reaches the
maximal file size, the next log file with index 2 is created, and so on. When
the Nth log file reaches the maximal file size, the 1th log file is used as the
next one.
When logging to files, the
log entries can be written directly to a file, but they can be written to
memory buffer first and flushed to file when the buffer is full. You can
control this behavior at run-time, define an environment variable
CTS_DIRECT_LOGGING to enable direct logging and undefine it to enable buffered
logging. This must be done before your application is started.
CTS logging provides a
minimal support for Nested Diagnostic Context (NDC), which is mainly used in
multithreaded applications, where a per thread
context is helpful to identify log records from specific thread. You would
calls setNDC() function to set a context for the
current thread, this function will not affect other threads. When no longer
needed, you can call removeNDC() to get rid of
NDC information for the current thread.
Supposed you have a buffer
for generating a string that uniquely identifies the current thread. You can
call CtsLogger::setNDC(const char*) for each thread
that you create:
sprintf(buffer, "Thread_%d", ndcIndex++);
logger.setNDC(buffer);
Several aspects of logging
can be adjusted via a configuration file named ctslogging.ini in the currnet
directory where you start your application. The following is an example of
the logging configuration file coming with CTS:
#-----------------------------------------------------------------------#
# CTS loggging configuration file
CtsEnableLogging = 1
CtsMaxFileSize = 10
# maximal log file size in MB
CtsNumFiles = 10
# number of log files
CtsLogDetail = HIGH
CtsLogLevel = SEVERE
CtsLogDirectory = C:\\temp\\log
# Logging details (logger names are case sensitive)
# Values include LOW, MEDIUM, HIGH
[details]
logger1 = HIGH
logger2 = HIGH
# Logging levels (logger names are case sensitive)
# Values include SEVERE, ERROR, WARNING, INFO, FINE, FINEST
[levels]
logger1 = FINEST
logger2 = FINEST
#-----------------------------------------------------------------------#
The following describes the global options in the logging configuration
file:
CtsEnableLogging
Type: boolean
Value: True, False, 1, 0, On, Off (case
insensitive)
Default: True
CtsMaxFileSize
Type: integer
Value: positive integer
Default: 2 (MB)
CtsNumFiles
Type: integer
Value: positive integer
Default: 5 (files)
CtsLogDetail
Type: character string
Value: HIGH, MEDIUM, LOW (case insensitive)
Default: MEDIUM
CtsLogLevel
Type: character string
Value: SEVERE, ERROR, WARNING, INFO, FINE,
FINEST (case insensitive)
Default: INFO
CtsLogDirectory
Type: character string
Value: path to directory containing log files
Default: current directory
CTS logging is amed at essential
functionalities, simplicity and especiallly performance (logging can greatly
impact your application’s performance). Therefore you have few possibilities to
customize logging, but you can subclass CtsLogHandler and overwrite flush() and log() functions (like CtsLogConsoleHandler and
CtsLogFileHandler) to handle writing to log destinations yourself e.g. to
socket servers, Windows event loggers or Unix syslog daemons.
This section describes briefly
other utility classes. For more details please refer to the API documentation
and test programs.
The class CtsTimer is for
calculating the time elapsed between a timer start and timer stop, it is exact
to milliseconds, so it can be used to time how long an activity takes. The time
difference is described by a structure called CtsTimeDiff, which has two fields
for seconds and milliseconds.
Using CtsTimer is very simple, here is an example:
CtsTimer timer;
timer.start();
compress(buffer,
size);
timer.stop();
CtsTimeDiff td = timer.getTimeDiff();
console.println("compress completed after %d.%03d seconds",
td.lSeconds,
td.lMilliseconds);
CtsString is a subclass of
std::string. This class is used internally by CTS to manipulate character
strings. It provides following Java String-like functions:
bool startsWith(const string&
str) const;
bool endsWith(const string& str) const;
bool isEmpty() const;
bool isWhiteSpace() const;
bool equalsIgnoreCase(const string& str) const;
bool equalsIgnoreCase(const char* cpszString) const;
long hashCode()
const;
const char* getCString()
const;
void toUpper();
void toLower();
const CtsString& trim();
const char& charAt( size_type loc ) const;
CtsString
substring( size_type index, size_type length = npos ) const;
void replaceAll(const string& s1, const string& s2);
Class CtsTokenizer is also another
Java-like tokenizer for C++, not only provides it the possibility to tokenize a
string by delimiters, but also allows tokenizing delimiters of different types,
i.e. consecutive different delimiters can be tokenized as separate tokens. The
following shows an example of CtsTokenizer in use.
CtsTokenizer tokenizer(input,
delims, true, true);
while
(tokenizer.hasMoreTokens()) {
CtsString token = tokenizer.nextToken();
process(token)
}
The class CtsFileInfo provides some information about
a file specified by a file path. It checks whether the path specifies a
directory or a file, whether it exists on file systems, gets the file size,
file name, extension and determines the absolute path to that file. On
Unix-like platforms it also checks whether the file is readable, writable or
executable by the program.
The class CtsDirInfo is similar to
CtsFileInfo in that, it gives information about a particular directory, whether
the directory exists, calculate directory size, get
parent name, get absolute path and also provides functions to navigate to
children.
The class CtsConfigFile is for handling configuration
files which satisfy following restrictions
- Section name is surrounded by square brackets and is
in a separate line.
- Option is of the form option = value.
- Option name may contain spaces.
- A backslash \ indicates that the next line of also
path of the current option.
- The hash sign # indicates begin
of a comment.
- Special characters must be escaped (e.g. \\, \#,
\=).
With this class you can walk through the sections and
access their options by name. The test program tconfig will show you how it
works.
The test programs coming with CTS
illustrate how you can parse program arguments using CtsConsole and also the
use of other classes in logging, getting file, directory information, ...
tconsole simulates
the command-line interface of a compiler, which expects at least path to one
source file. It then displays the option values and if the source file exists
it does a hex dump of the content. For illustration purposes, no contraints
among options are checked. You may try:
C:\> tconsole –c –o
prog.exe –IC:\dev\cpp\include sourcefile.cpp
C:\> tconsole
–-compile-only –o prog.exe sourcefile.cpp
C:\> tconsole
–-compile-only –-output-file=prog.exe sourcefile.cpp
tlogger tests the
logging functionality in single and multiple thread mode. It takes no parameter
and will generate log files by default in directory log (specified in logging
configuration file ctslogging.ini).
C:\ tlogger
CTS version 0.8x built at Oct 13 2010 23:06:34
TLOGGER - CTS test program
Testing CTS logging with single thread
-------------------------------------------------
Test completed after 0.325 seconds
Testing CTS logging with multiple
threads
-------------------------------------------------
Number of
threads.......................: 10
Test completed after 3.221 seconds
The following log files will be generated:
13.10.2010 23:06 3.145.782
multithread.#1.log
13.10.2010 23:06 3.145.775
multithread.#2.log
13.10.2010 23:06 3.145.759
multithread.#3.log
13.10.2010 23:06 3.145.798
multithread.#4.log
13.10.2010 23:06 3.145.797
multithread.#5.log
13.10.2010 23:06 3.145.770
multithread.#6.log
13.10.2010 23:06 3.145.817
multithread.#7.log
13.10.2010 23:06 3.145.749
multithread.#8.log
13.10.2010 23:06 2.897.383
multithread.#9.log
13.10.2010 23:06 2.563.570
singlethread.#1.log
tmore
simulates the more command but it does not show the file content, but only some
information about the input file or directory (whether it exists, absolute
path, file name, file type and size). You may try tmore as follows:
C:\>tmore ctsconsole.cpp
CTS version 0.86 built at Oct 13 2010 23:06:37
TMORE - CTS test program
Enable extended
feature.................: No
Clear screen before displaying
page.....: No
Expand FormFeed
characters..............: No
Squeeze multiple blank
lines............: No
Expand tab size
to......................: 8 (default)
Start displaying the first file at
line.: 1 (default)
Input
file..............................: ctsconsole.cpp
Input
exists............................: Yes
Absolute
path...........................: C:\code\cts\ctsconsole.cpp
File
name...............................: ctsconsole.cpp
File
type...............................: cpp
File size in
bytes......................: 13093
tlist
simulates the dir command on Windows, it lists all files and directories in input
path. Running tlist without parameters will list the content of current
directory. By default it shows the modifiy timestamps of files and directories.
You may run tlist as follows to show last change, last modify and last access
timestamps respectively:
tlist –c
tlist –m
tlist –a
Sample output:
C:\code\cts>tlist ctslogger.cpp log
CTS version 0.86 built at
TLIST - List directory content
Listing C:\Users\
10/13/2010 23:06:52 3145782
multithread.#1.log
10/13/2010 23:06:53 3145775
multithread.#2.log
10/13/2010 23:06:53 3145759
multithread.#3.log
10/13/2010 23:06:53 3145798
multithread.#4.log
10/13/2010 23:06:54 3145797
multithread.#5.log
10/13/2010 23:06:54 3145770
multithread.#6.log
10/13/2010 23:06:54 3145817
multithread.#7.log
10/13/2010 23:06:55 3145749
multithread.#8.log
10/13/2010 23:06:55 2897383
multithread.#9.log
10/13/2010 23:06:52 2563570
singlethread.#1.log
tconfig
reads a configuration file as input and shows all configuration values. There
is a sample configuration file testconfig.ini in CTS directory with which you
will get following output:
C:\Users\
TCONFIG
GlobalOption1...........................:
ON
GlobalOption2...........................:
ON
GlobalOption3...........................:
ON
Skins
-------------------------------------------------
Extension...............................:
Vista
Extension...............................:
XP
Extension...............................:
MacOS
Extension...............................:
KDE
Extension...............................:
Gnome
Media
-------------------------------------------------
MIMEtypes...............................:
MP3 WMA WAV FLV MP4 AVI
Quality.................................:
High
Users...................................:
user1 user2 user3
Maximal screen
size.....................: 1400 x 900
The test program testtokenizer demonstrates how
strings can be tokenized by CtsTokenizer. It takes 2 parameters: the string to
be tokenized and an optional string containing delimiters. You may try it as
follows:
Note: the option value for delimiters in this case may
start with either a minus or a plus sign which may be considered as
command-line option. In POSIX, two consecutive dash –– should indicates that everything comes after it
is option values. CtsConsole supports this.
C:\> ttokenizer -i
"1+(2+3)*(4+5)+(6-7)" -d -- "-+*()"
C:\> ttokenizer -i
"123ab456cd789" -d "abcd"
Using CTS in your code is simple,
you only need to include the header file cts.hpp
and if needed specify that the namespace cts is being used. You need to either put CTS include directory in your environment
variable INCLUDE or specify it as compiler argument to compile your code. On
Windows, CTS is compiled as a dynamic-link library, the cts.dll and cts.lib files
will be created in directory lib. The cts.lib
must be provided at link time and cts.dll
must be found at run time. You need to add this directory to your PATH
environment variable so that the system can find it. Test program executables
are found in directory bin.
On Windows, you can regenerate
documentation from code with Doxygen. The file doxyfile in CTS directory is the
configuration file for this purpose. Documentation in HTML format will be
generated in directory doc.
Currently, CTS supports only
Visual C++ compiler and NMAKE on Windows, GNU g++ compiler and MAKE on Unix.
On Windows
1. Extract
CTS to a directory (e.g. cts)
cd cts
2. Set the
path and environment variables for command-line builds by running vcvars32.bat
(usually found at %VCINSTALLDIR%\bin\vcvars32.bat)
%VCINSTALLDIR%\bin\vcvars32.bat
3. Rename
makefile_Win32 to makefile
ren makefile_Win32 makefile
4. Run NMAKE
to build CTS and test programs, executables are generated in bin, DLL is generated
in lib.
nmake
5. If you
have doxygen installed, run nmake gendoc to generate API Documentation.
nmake gendoc
6. Run
setCtsPath.cmd to set add CTS to library path
setCtsPath.cmd
7. Now you
can run test programs: tlogger, tconsole, tmore, tconfig, tlist, tnow
tconsole -?
On Unix/Linux
1. Extract CTS
to a directory (e.g. cts)
$ mkdir cts
$ cd cts
$ unzip Cts_v086.zip
–d .
2. Rename
makefile_Unix to makefile
$ mv makefile_Unix makefile
3. Run MAKE
to build CTS and test programs, executables are generated in bin, DLL is generated
in lib.
$
make
4. Run . setCtsPath.sh (note the dot) to add CTS to library
path.
$ .
setCtsPath.sh
5. Now you
can run test programs: tlogger, tconsole, tmore, tconfig, tlist, tnow
$ tconsole -?
If you have problems compiling CTS
and test programs, you may contact us at project hompage (http://sourceforge.net/projects/clp/forums/), we will
try to help you as soon as we can.
- CTS is compiled as DLL on Windows. If you use CTS in your code,
you MAY have to compile it with the same compiler version as you compiled CTS
library file to avoid the name mangling problem.
CTS is
open source and freely available under Eclipse Public License 1.0.
Version
0.86 (
- New logging interface
- Support direct logging and buffered logging
- Bug fixes in CtsConfigFile, CtsTimer
- Update CtsUtils
Version
0.85 (
- New classes CtsDirInfo, CtsConfigFile
- New logging features: logging configuration, Nested
Diagnostic Context (NDC)
- CtsUtils::calculateDirectorySizeNonRecursive
- Bug fixes in CtsConsole, CtsString
- Bug fix in makefile for Windows that prevents user
code from linking with C++ runtime library
- Makefile for Linux, compiled as shared library
- Makfile dependencies using g++ -MM on Debian
- Debug with debenv Windows
- Unix makefile debug and ship
flags
Version
0.84 (
- Introduce new classes CtsLogger,
CtsFileInfo, CtsTimer
- Bug
fixes in CtsConsole, CtsString
- Some
interface change in CtsConsole
- Code documentation
We appreciate your feedbacks, bug
reports, feature requests, recommendations and critiques. Please contact us at Sourceforge or write to linhmt[at]gmail[dot]com.
[1] The
POSIX and GNU argument syntax convention
http://www.gnu.org/s/libc/manual/html_node/Argument-Syntax.html