diff --git a/Makefile b/Makefile index 88ff212..992dea5 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ INCDIR=include CXX=cl /nologo LD=link /nologo -CXXFLAGS=/c /O1 /I$(INCDIR) /W4 /Zi /DWIN32_LEAN_AND_MEAN /DWINVER=0x0501 /D_WIN32_WINNT=0x0501 /wd4100 /DUNICODE /D_UNICODE +CXXFLAGS=/c /O1 /I$(INCDIR) /W4 /Zi /DWIN32_LEAN_AND_MEAN /DWINVER=0x0501 /D_WIN32_WINNT=0x0501 /wd4100 /DUNICODE /D_UNICODE /EHsc LDFLAGS=/subsystem:windows /debug /manifest /incremental:no /opt:REF LDFLAGS=$(LDFLAGS) "/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'" RC=rc /nologo @@ -31,16 +31,24 @@ FILES=$(OUTDIR)\Zalgo.obj \ $(OUTDIR)\NLSWrap.obj \ $(OUTDIR)\MyDropTarget.obj \ $(OUTDIR)\Zalgo.res +DISTS=$(DISTDIR)\Zalgo.exe \ + $(DISTDIR)\hecomes.exe \ + $(DISTDIR)\hegoes.exe -all: initdir $(DISTDIR)\Zalgo.exe +CMDFILE=$(OUTDIR)\ZalgoLib.obj \ + $(OUTDIR)\OptionParser.obj + +all: initdir $(DISTS) +hecomes: $(DISTDIR)\hecomes.exe +hecomes: $(DISTDIR)\hegoes.exe initdir: - if not exist build md build - if not exist $(OUTDIR) md $(OUTDIR) - if not exist build md dist - if not exist $(DISTDIR) md $(DISTDIR) + @if not exist build md build + @if not exist $(OUTDIR) md $(OUTDIR) + @if not exist build md dist + @if not exist $(DISTDIR) md $(DISTDIR) -compress: $(DISTDIR)\Zalgo.exe +compress: $(DISTS) upx --best $** $(INCDIR)\MainWindow.hpp: $(INCDIR)\Window.hpp $(INCDIR)\MyDropTarget.hpp $(INCDIR)\PreviewWindow.hpp @@ -57,6 +65,11 @@ $(SRCDIR)\Window.cpp: $(INCDIR)\Window.hpp $(SRCDIR)\NLSWrap.cpp: $(INCDIR)\NLSWrap.hpp $(SRCDIR)\MainLogic.cpp: $(INCDIR)\MainWindow.hpp $(INCDIR)\NLSWrap.hpp $(INCDIR)\ConversionData.inc +$(SRCDIR)\ZalgoLib.cpp: $(INCDIR)\ZalgoLib.h $(INCDIR)\ConversionData.inc +$(SRCDIR)\OptionParser.cpp: $(INCDIR)\OptionParser.h +$(SRCDIR)\hecomes.cpp: $(INCDIR)\OptionParser.h $(INCDIR)\ZalgoLib.h +$(SRCDIR)\hegoes.cpp: $(INCDIR)\OptionParser.h $(INCDIR)\ZalgoLib.h + $(OUTDIR)\Zalgo.res: Zalgo.rc res\x-sampa.txt res\init.txt $(RC) $(RCFLAGS) /fo$@ Zalgo.rc @@ -66,3 +79,9 @@ $(OUTDIR)\Zalgo.res: Zalgo.rc res\x-sampa.txt res\init.txt $(DISTDIR)\Zalgo.exe: $(FILES) $(LD) /out:$@ $(LDFLAGS) $** $(LIBS) mt.exe -nologo -manifest $@.manifest -outputresource:$@;1 && del $@.manifest || set ERRORLEVEL=0 + +$(DISTDIR)\hecomes.exe: $(CMDFILE) $(OUTDIR)\hecomes.obj + $(LD) /out:$@ $** + +$(DISTDIR)\hegoes.exe: $(CMDFILE) $(OUTDIR)\hegoes.obj + $(LD) /out:$@ $** diff --git a/Makefile.gcc b/Makefile.gcc new file mode 100644 index 0000000..3705e12 --- /dev/null +++ b/Makefile.gcc @@ -0,0 +1,62 @@ +SRCDIR=src +INCDIR=include + +ifdef CROSS + KROSS=$(CROSS)- +endif + +CXX=$(KROSS)g++ -std=c++11 +STRIP=$(KROSS)strip +LD=$(CXX) +CXXFLAGS=-c -O3 -I$(INCDIR) -Wall -DWIN32_LEAN_AND_MEAN -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 -DUNICODE -D_UNICODE +LDFLAGS=-static-libstdc++ +LIBS= + +ifdef DEBUG +BUILD=Debug +CXXFLAGS=$(CXXFLAGS) -DDEBUG +LDFLAGS=$(LDFLAGS) -g +else +BUILD=Release +endif + +OUTDIR=build/$(BUILD) +DISTDIR=dist/$(BUILD) +DISTS=$(DISTDIR)/hecomes \ + $(DISTDIR)/hegoes + +FILES=$(OUTDIR)/ZalgoLib.o \ + $(OUTDIR)/OptionParser.o + +all: initdir $(DISTS) +hecomes: $(DISTDIR)/hecomes +hecomes: $(DISTDIR)/hegoes + +.PHONY: clean + +clean: + rm $(OUTDIR)/*.o + rm $(DISTS) + +strip: + $(STRIP) $(DISTS) + +initdir: + -test -d build || mkdir build + -test -d $(OUTDIR) || mkdir $(OUTDIR) + -test -d build || mkdir dist + -test -d $(DISTDIR) || mkdir $(DISTDIR) + +$(SRCDIR)/ZalgoLib.cpp: $(INCDIR)/ZalgoLib.h $(INCDIR)/ConversionData.inc +$(SRCDIR)/OptionParser.cpp: $(INCDIR)/OptionParser.h +$(SRCDIR)/hecomes.cpp: $(INCDIR)/OptionParser.h $(INCDIR)/ZalgoLib.h +$(SRCDIR)/hegoes.cpp: $(INCDIR)/OptionParser.h $(INCDIR)/ZalgoLib.h + +$(OUTDIR)/%.o: $(SRCDIR)/%.cpp + $(CXX) $(CXXFLAGS) -o $@ -c $< + +$(DISTDIR)/hecomes: $(FILES) $(OUTDIR)/hecomes.o + $(LD) $(LDFLAGS) -o $@ $^ + +$(DISTDIR)/hegoes: $(FILES) $(OUTDIR)/hegoes.o + $(LD) $(LDFLAGS) -o $@ $^ diff --git a/include/OptionParser.h b/include/OptionParser.h new file mode 100644 index 0000000..8b74de9 --- /dev/null +++ b/include/OptionParser.h @@ -0,0 +1,307 @@ +/** + * Copyright (C) 2010 Johannes Weißl + * License: your favourite BSD-style license + * + * git clone http://github.com/weisslj/cpp-optparse.git + * + * This is yet another option parser for C++. It is modelled after the + * excellent Python optparse API. Although incomplete, anyone familiar to + * optparse should feel at home: + * http://docs.python.org/library/optparse.html + * + * Design decisions: + * - elegant and easy usage more important than speed / flexibility + * - shortness more important than feature completeness + * * no unicode + * * no checking for user programming errors + * + * Why not use getopt/getopt_long? + * - not C++ / not completely POSIX + * - too cumbersome to use, would need lot of additional code + * + * Why not use Boost.Program_options? + * - boost not installed on all target platforms (esp. cluster, HPC, ...) + * - too big to include just for option handling: + * 322 *.h (44750 lines) + 7 *.cpp (2078 lines) + * + * Why not use tclap/Opag/Options/CmdLine/Anyoption/Argument_helper/...? + * - no reason, writing one is faster than code inspection :-) + * - similarity to Python desired for faster learning curve + * + * Future work: + * - nargs > 1? + * - comments? + * + * Python only features: + * - conflict handlers + * - adding new actions + * + * + * Example: + * + * using optparse::OptionParser; + * + * OptionParser parser = OptionParser() .description("just an example"); + * + * parser.add_option("-f", "--file") .dest("filename") + * .help("write report to FILE") .metavar("FILE"); + * parser.add_option("-q", "--quiet") + * .action("store_false") .dest("verbose") .set_default("1") + * .help("don't print status messages to stdout"); + * + * optparse::Values options = parser.parse_args(argc, argv); + * vector args = parser.args(); + * + * if (options.get("verbose")) + * cout << options["filename"] << endl; + * + */ + +#ifndef OPTIONPARSER_H_ +#define OPTIONPARSER_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4512) +#endif +namespace optparse { + +class OptionParser; +class OptionGroup; +class Option; +class Values; +class Value; +class Callback; + +typedef std::map strMap; +typedef std::map > lstMap; +typedef std::map optMap; + +const char* const SUPPRESS_HELP = "SUPPRESS" "HELP"; +const char* const SUPPRESS_USAGE = "SUPPRESS" "USAGE"; + +//! Class for automatic conversion from string -> anytype +class Value { + public: + Value() : str(), valid(false) {} + Value(const std::string& v) : str(v), valid(true) {} + operator const char*() { return str.c_str(); } + operator bool() { bool t; return (valid && (std::istringstream(str) >> t)) ? t : false; } + operator short() { short t; return (valid && (std::istringstream(str) >> t)) ? t : 0; } + operator unsigned short() { unsigned short t; return (valid && (std::istringstream(str) >> t)) ? t : 0; } + operator int() { int t; return (valid && (std::istringstream(str) >> t)) ? t : 0; } + operator unsigned int() { unsigned int t; return (valid && (std::istringstream(str) >> t)) ? t : 0; } + operator long() { long t; return (valid && (std::istringstream(str) >> t)) ? t : 0; } + operator unsigned long() { unsigned long t; return (valid && (std::istringstream(str) >> t)) ? t : 0; } + operator float() { float t; return (valid && (std::istringstream(str) >> t)) ? t : 0; } + operator double() { double t; return (valid && (std::istringstream(str) >> t)) ? t : 0; } + operator long double() { long double t; return (valid && (std::istringstream(str) >> t)) ? t : 0; } + private: + const std::string str; + bool valid; +}; + +class Values { + public: + Values() : _map() {} + const std::string& operator[] (const std::string& d) const; + std::string& operator[] (const std::string& d) { return _map[d]; } + bool is_set(const std::string& d) const { return _map.find(d) != _map.end(); } + bool is_set_by_user(const std::string& d) const { return _userSet.find(d) != _userSet.end(); } + void is_set_by_user(const std::string& d, bool yes); + Value get(const std::string& d) const { return (is_set(d)) ? Value((*this)[d]) : Value(); } + + typedef std::list::iterator iterator; + typedef std::list::const_iterator const_iterator; + std::list& all(const std::string& d) { return _appendMap[d]; } + const std::list& all(const std::string& d) const { return _appendMap.find(d)->second; } + + private: + strMap _map; + lstMap _appendMap; + std::set _userSet; +}; + +class OptionParser { + public: + OptionParser(); + virtual ~OptionParser() {} + + OptionParser& usage(const std::string& u) { set_usage(u); return *this; } + OptionParser& version(const std::string& v) { _version = v; return *this; } + OptionParser& description(const std::string& d) { _description = d; return *this; } + OptionParser& add_help_option(bool h) { _add_help_option = h; return *this; } + OptionParser& add_version_option(bool v) { _add_version_option = v; return *this; } + OptionParser& prog(const std::string& p) { _prog = p; return *this; } + OptionParser& epilog(const std::string& e) { _epilog = e; return *this; } + OptionParser& set_defaults(const std::string& dest, const std::string& val) { + _defaults[dest] = val; return *this; + } + OptionParser& enable_interspersed_args() { _interspersed_args = true; return *this; } + OptionParser& disable_interspersed_args() { _interspersed_args = false; return *this; } + OptionParser& add_option_group(const OptionGroup& group); + + const std::string& usage() const { return _usage; } + const std::string& version() const { return _version; } + const std::string& description() const { return _description; } + bool add_help_option() const { return _add_help_option; } + bool add_version_option() const { return _add_version_option; } + const std::string& prog() const { return _prog; } + const std::string& epilog() const { return _epilog; } + bool interspersed_args() const { return _interspersed_args; } + + Option& add_option(const std::string& opt); + Option& add_option(const std::string& opt1, const std::string& opt2); + Option& add_option(const std::string& opt1, const std::string& opt2, const std::string& opt3); + Option& add_option(const std::vector& opt); + + Values& parse_args(int argc, char const* const* argv); + Values& parse_args(const std::vector& args); + template + Values& parse_args(InputIterator begin, InputIterator end) { + return parse_args(std::vector(begin, end)); + } + + const std::list& args() const { return _leftover; } + std::vector args() { + return std::vector(_leftover.begin(), _leftover.end()); + } + + std::string format_help() const; + std::string format_option_help(unsigned int indent = 2) const; + void print_help() const; + + void set_usage(const std::string& u); + std::string get_usage() const; + void print_usage(std::ostream& out) const; + void print_usage() const; + + std::string get_version() const; + void print_version(std::ostream& out) const; + void print_version() const; + + void error(const std::string& msg) const; + void exit() const; + + private: + const Option& lookup_short_opt(const std::string& opt) const; + const Option& lookup_long_opt(const std::string& opt) const; + + void handle_short_opt(const std::string& opt, const std::string& arg); + void handle_long_opt(const std::string& optstr); + + void process_opt(const Option& option, const std::string& opt, const std::string& value); + + std::string format_usage(const std::string& u) const; + + std::string _usage; + std::string _version; + std::string _description; + bool _add_help_option; + bool _add_version_option; + std::string _prog; + std::string _epilog; + bool _interspersed_args; + + Values _values; + + std::list