summaryrefslogtreecommitdiff
path: root/cli-tests
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-04-08 14:51:57 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2020-04-27 11:38:53 +0300
commit720c5a33b6a49cf328fdd7611f49153cf8f60247 (patch)
tree9725f3d1f42ec90fde84520f49647edea013ce5e /cli-tests
parent3183f3bb927a90783ae0aeaf190a0919377aabe4 (diff)
Separate tests and examples into individual packages
Also make cli module to be explicitly enabled via the config.cli configuration variable.
Diffstat (limited to 'cli-tests')
-rw-r--r--cli-tests/.gitignore22
l---------cli-tests/LICENSE1
-rw-r--r--cli-tests/README8
-rw-r--r--cli-tests/build/.gitignore3
-rw-r--r--cli-tests/build/bootstrap.build9
-rw-r--r--cli-tests/build/root.build27
-rw-r--r--cli-tests/buildfile4
-rw-r--r--cli-tests/combined/buildfile9
-rw-r--r--cli-tests/combined/driver.cxx39
-rw-r--r--cli-tests/combined/test.cli16
-rw-r--r--cli-tests/combined/testscript108
-rw-r--r--cli-tests/ctor/buildfile8
-rw-r--r--cli-tests/ctor/driver.cxx60
-rw-r--r--cli-tests/ctor/test.cli8
-rw-r--r--cli-tests/erase/buildfile10
-rw-r--r--cli-tests/erase/driver.cxx34
-rw-r--r--cli-tests/erase/test.cli9
-rw-r--r--cli-tests/file/buildfile9
-rw-r--r--cli-tests/file/driver.cxx39
-rw-r--r--cli-tests/file/test.cli7
-rw-r--r--cli-tests/file/testscript286
-rw-r--r--cli-tests/group/buildfile9
-rw-r--r--cli-tests/group/driver.cxx58
-rw-r--r--cli-tests/group/test.cli7
-rw-r--r--cli-tests/group/testscript140
-rw-r--r--cli-tests/headings/buildfile6
-rw-r--r--cli-tests/headings/testscript36
-rw-r--r--cli-tests/inheritance/buildfile11
-rw-r--r--cli-tests/inheritance/driver.cxx35
-rw-r--r--cli-tests/inheritance/test.cli25
-rw-r--r--cli-tests/inheritance/test.std4
-rw-r--r--cli-tests/manifest15
-rw-r--r--cli-tests/merge/buildfile9
-rw-r--r--cli-tests/merge/driver.cxx55
-rw-r--r--cli-tests/merge/test.cli18
-rw-r--r--cli-tests/note/buildfile6
-rw-r--r--cli-tests/note/testscript197
-rw-r--r--cli-tests/specifier/buildfile10
-rw-r--r--cli-tests/specifier/driver.cxx29
-rw-r--r--cli-tests/specifier/test.cli12
-rw-r--r--cli-tests/toc/buildfile6
-rw-r--r--cli-tests/toc/testscript155
42 files changed, 1559 insertions, 0 deletions
diff --git a/cli-tests/.gitignore b/cli-tests/.gitignore
new file mode 100644
index 0000000..0b99f39
--- /dev/null
+++ b/cli-tests/.gitignore
@@ -0,0 +1,22 @@
+# Compiler/linker output.
+#
+*.d
+*.t
+*.i
+*.ii
+*.o
+*.obj
+*.so
+*.dll
+*.a
+*.lib
+*.exp
+*.pdb
+*.ilk
+*.exe
+*.exe.dlls/
+*.exe.manifest
+*.pc
+
+driver
+test.?xx
diff --git a/cli-tests/LICENSE b/cli-tests/LICENSE
new file mode 120000
index 0000000..ea5b606
--- /dev/null
+++ b/cli-tests/LICENSE
@@ -0,0 +1 @@
+../LICENSE \ No newline at end of file
diff --git a/cli-tests/README b/cli-tests/README
new file mode 100644
index 0000000..28e7868
--- /dev/null
+++ b/cli-tests/README
@@ -0,0 +1,8 @@
+This package contains tests for the CLI compiler for C++.
+
+See the LICENSE file for distribution conditions.
+
+The project page is at http://codesynthesis.com/projects/cli/.
+
+Send questions, bug reports, or any other feedback to
+cli-users@codesynthesis.com.
diff --git a/cli-tests/build/.gitignore b/cli-tests/build/.gitignore
new file mode 100644
index 0000000..4a730a3
--- /dev/null
+++ b/cli-tests/build/.gitignore
@@ -0,0 +1,3 @@
+config.build
+root/
+bootstrap/
diff --git a/cli-tests/build/bootstrap.build b/cli-tests/build/bootstrap.build
new file mode 100644
index 0000000..f5c693e
--- /dev/null
+++ b/cli-tests/build/bootstrap.build
@@ -0,0 +1,9 @@
+# file : build/bootstrap.build
+# license : MIT; see accompanying LICENSE file
+
+project = cli-tests
+
+using version
+using config
+using dist
+using test
diff --git a/cli-tests/build/root.build b/cli-tests/build/root.build
new file mode 100644
index 0000000..53bde39
--- /dev/null
+++ b/cli-tests/build/root.build
@@ -0,0 +1,27 @@
+# file : build/root.build
+# license : MIT; see accompanying LICENSE file
+
+cxx.std = latest
+
+using cxx
+
+hxx{*}: extension = hxx
+ixx{*}: extension = ixx
+txx{*}: extension = txx
+cxx{*}: extension = cxx
+
+if ($cxx.target.system == 'win32-msvc')
+ cxx.poptions += -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS
+
+if ($cxx.class == 'msvc')
+ cxx.coptions += /wd4251 /wd4275 /wd4800
+
+using cli
+
+# Every exe{} in this subproject is by default a test.
+#
+exe{*}: test = true
+
+# Specify the test target for cross-testing.
+#
+test.target = $cxx.target
diff --git a/cli-tests/buildfile b/cli-tests/buildfile
new file mode 100644
index 0000000..53d51dd
--- /dev/null
+++ b/cli-tests/buildfile
@@ -0,0 +1,4 @@
+# file : buildfile
+# license : MIT; see accompanying LICENSE file
+
+./: {*/ -build/} doc{LICENSE README} manifest
diff --git a/cli-tests/combined/buildfile b/cli-tests/combined/buildfile
new file mode 100644
index 0000000..943ca25
--- /dev/null
+++ b/cli-tests/combined/buildfile
@@ -0,0 +1,9 @@
+# file : combined/buildfile
+# license : MIT; see accompanying LICENSE file
+
+exe{driver}: {hxx cxx}{* -test} cli.cxx{test} testscript
+
+cxx.poptions =+ "-I$out_base"
+
+cli.cxx{test}: cli{test}
+cli.options = --generate-specifier --generate-file-scanner
diff --git a/cli-tests/combined/driver.cxx b/cli-tests/combined/driver.cxx
new file mode 100644
index 0000000..dcbdd34
--- /dev/null
+++ b/cli-tests/combined/driver.cxx
@@ -0,0 +1,39 @@
+// file : combined/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+// Test combined flags (-xyz vs -x -y -z) and option values (--foo=bar).
+//
+
+#include <iostream>
+
+#include "test.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ cli::argv_file_scanner s (argc, argv, "--file");
+ options o (s);
+
+ if (o.foo_specified ())
+ cout << "--foo=" << o.foo () << endl;
+
+ if (o.x () || o.y () || o.z ())
+ cout << '-'
+ << (o.x () ? "x" : "")
+ << (o.y () ? "y" : "")
+ << (o.z () ? "z" : "") << endl;
+
+ if (o.xyz ())
+ cout << "--xyz" << endl;
+ }
+ catch (const cli::exception& e)
+ {
+ cerr << e << endl;
+ return 1;
+ }
+}
diff --git a/cli-tests/combined/test.cli b/cli-tests/combined/test.cli
new file mode 100644
index 0000000..6377de8
--- /dev/null
+++ b/cli-tests/combined/test.cli
@@ -0,0 +1,16 @@
+// file : combined/test.cli
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+include <string>;
+
+class options
+{
+ std::string --foo|-f;
+
+ bool -x;
+ bool -y;
+ bool -z;
+
+ bool --xyz;
+};
diff --git a/cli-tests/combined/testscript b/cli-tests/combined/testscript
new file mode 100644
index 0000000..d1f9830
--- /dev/null
+++ b/cli-tests/combined/testscript
@@ -0,0 +1,108 @@
+# file : combined/testscript
+# license : MIT; see accompanying LICENSE file
+
+: values
+:
+{
+ : long
+ :
+ $* --foo=123 >'--foo=123'
+
+ : short
+ :
+ $* -f=123 >'--foo=123'
+
+ : empty
+ :
+ $* --foo= >'--foo='
+
+ : unknown-option-long
+ :
+ $* --bar=123 2>>EOE != 0
+ unknown option '--bar'
+ EOE
+
+ : unknown-option-short
+ :
+ $* -b=123 2>>EOE != 0
+ unknown option '-b'
+ EOE
+
+ : unknown-value
+ :
+ $* --xyz=123 2>>EOE != 0
+ invalid value '123' for option '--xyz'
+ EOE
+
+ : options-file
+ :
+ {
+ : basics
+ :
+ cat <<EOI >=options;
+ --foo=123
+ EOI
+ $* --file=options >'--foo=123'
+
+ : equal-in-value
+ :
+ cat <<EOI >=options;
+ --foo bar=123
+ EOI
+ $* --file=options >'--foo=bar=123'
+
+ : space-in-value
+ :
+ cat <<EOI >=options;
+ --foo= 123
+ EOI
+ $* --file=options >'--foo= 123'
+
+ : quoted-value
+ :
+ cat <<EOI >=options;
+ --foo="'bar 123'"
+ EOI
+ $* --file=options >"--foo='bar 123'"
+ }
+}
+
+: flags
+:
+{
+ : basic
+ :
+ $* -zyx >'-xyz'
+
+ : separate
+ :
+ $* -zx -y >'-xyz'
+
+ : long
+ :
+ $* --xyz >'--xyz'
+
+ : unknown-option
+ :
+ $* -xYz 2>>EOE != 0
+ unknown option '-Y'
+ EOE
+
+ : alnum-only
+ :
+ $* -xy+ 2>>EOE != 0
+ unknown option '-xy+'
+ EOE
+
+ : flags-only
+ :
+ $* -xyf 123 2>>EOE != 0
+ missing value for option '-f'
+ EOE
+
+ : flags-only-combined
+ :
+ $* -xyf=123 2>>EOE != 0
+ missing value for option '-f'
+ EOE
+}
diff --git a/cli-tests/ctor/buildfile b/cli-tests/ctor/buildfile
new file mode 100644
index 0000000..4144988
--- /dev/null
+++ b/cli-tests/ctor/buildfile
@@ -0,0 +1,8 @@
+# file : ctor/buildfile
+# license : MIT; see accompanying LICENSE file
+
+exe{driver}: {hxx cxx}{* -test} cli.cxx{test}
+
+cxx.poptions =+ "-I$out_base"
+
+cli.cxx{test}: cli{test}
diff --git a/cli-tests/ctor/driver.cxx b/cli-tests/ctor/driver.cxx
new file mode 100644
index 0000000..ed306f4
--- /dev/null
+++ b/cli-tests/ctor/driver.cxx
@@ -0,0 +1,60 @@
+// file : ctor/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#include "test.hxx"
+
+int
+main (int argc, char* argv[])
+{
+ // Test that we can call all the c-tors unambiguously.
+ //
+ {
+ options o1 (argc, argv);
+ options o2 (argc, argv, true);
+ options o3 (argc, argv, true,
+ cli::unknown_mode::fail);
+ options o4 (argc, argv, true,
+ cli::unknown_mode::fail,
+ cli::unknown_mode::stop);
+ }
+
+ {
+ options o1 (1, argc, argv);
+ options o2 (1, argc, argv, true);
+ options o3 (1, argc, argv, true,
+ cli::unknown_mode::fail);
+ options o4 (1, argc, argv, true,
+ cli::unknown_mode::fail,
+ cli::unknown_mode::stop);
+ }
+
+ {
+ int end;
+ options o1 (argc, argv, end);
+ options o2 (argc, argv, end, true);
+ options o3 (argc, argv, end, true,
+ cli::unknown_mode::fail);
+ options o4 (argc, argv, end, true,
+ cli::unknown_mode::fail,
+ cli::unknown_mode::stop);
+ }
+
+ {
+ int end;
+ options o1 (1, argc, argv, end);
+ options o2 (1, argc, argv, end, true);
+ options o3 (1, argc, argv, end, true,
+ cli::unknown_mode::fail);
+ options o4 (1, argc, argv, end, true,
+ cli::unknown_mode::fail,
+ cli::unknown_mode::stop);
+ }
+
+ {
+ cli::argv_scanner s (argc, argv);
+ options o1 (s);
+ options o2 (s, cli::unknown_mode::fail);
+ options o3 (s, cli::unknown_mode::fail, cli::unknown_mode::stop);
+ }
+}
diff --git a/cli-tests/ctor/test.cli b/cli-tests/ctor/test.cli
new file mode 100644
index 0000000..94797fb
--- /dev/null
+++ b/cli-tests/ctor/test.cli
@@ -0,0 +1,8 @@
+// file : ctor/test.cli
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+class options
+{
+ bool --help;
+};
diff --git a/cli-tests/erase/buildfile b/cli-tests/erase/buildfile
new file mode 100644
index 0000000..024e021
--- /dev/null
+++ b/cli-tests/erase/buildfile
@@ -0,0 +1,10 @@
+# file : erase/buildfile
+# license : MIT; see accompanying LICENSE file
+
+exe{driver}: {hxx cxx}{* -test} cli.cxx{test}
+exe{driver}: test.arguments = foo -a bar -b 123 --arg -- -b 234
+
+cxx.poptions =+ "-I$out_base"
+
+cli.cxx{test}: cli{test}
+cli.options = --no-combined-flags # Can't be used with the skip unknown mode.
diff --git a/cli-tests/erase/driver.cxx b/cli-tests/erase/driver.cxx
new file mode 100644
index 0000000..af35836
--- /dev/null
+++ b/cli-tests/erase/driver.cxx
@@ -0,0 +1,34 @@
+// file : erase/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+// Test argument erasing.
+//
+
+#include <string>
+#include <cassert>
+
+#include "test.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ options o (argc, argv, true,
+ cli::unknown_mode::skip,
+ cli::unknown_mode::skip);
+
+ assert (o.a ());
+ assert (o.b () == 123);
+
+ // We should have 'foo bar --arg -- -b 234'.
+ //
+ assert (argc == 7);
+ assert (argv[1] == string ("foo"));
+ assert (argv[2] == string ("bar"));
+ assert (argv[3] == string ("--arg"));
+ assert (argv[4] == string ("--"));
+ assert (argv[5] == string ("-b"));
+ assert (argv[6] == string ("234"));
+}
diff --git a/cli-tests/erase/test.cli b/cli-tests/erase/test.cli
new file mode 100644
index 0000000..a5d7672
--- /dev/null
+++ b/cli-tests/erase/test.cli
@@ -0,0 +1,9 @@
+// file : erase/test.cli
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+class options
+{
+ bool -a;
+ int -b;
+};
diff --git a/cli-tests/file/buildfile b/cli-tests/file/buildfile
new file mode 100644
index 0000000..793d2a9
--- /dev/null
+++ b/cli-tests/file/buildfile
@@ -0,0 +1,9 @@
+# file : file/buildfile
+# license : MIT; see accompanying LICENSE file
+
+exe{driver}: {hxx cxx}{* -test} cli.cxx{test} testscript
+
+cxx.poptions =+ "-I$out_base"
+
+cli.cxx{test}: cli{test}
+cli.options = --generate-file-scanner
diff --git a/cli-tests/file/driver.cxx b/cli-tests/file/driver.cxx
new file mode 100644
index 0000000..eef7ef1
--- /dev/null
+++ b/cli-tests/file/driver.cxx
@@ -0,0 +1,39 @@
+// file : file/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+// Test argv_file_scanner.
+//
+#include <memory>
+#include <string>
+#include <iostream>
+
+#include "test.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ string a (argc > 1 ? argv[1] : "");
+
+ // Special modes.
+ //
+ // ---- <file>
+ // --- <file>
+ //
+ unique_ptr<cli::scanner> s (
+ a == "----" ? new cli::argv_file_scanner (argv[2], "--file") :
+ a == "---" ? new cli::argv_file_scanner (argv[2]) :
+ new cli::argv_file_scanner (argc, argv, "--file"));
+
+ while (s->more ())
+ cout << s->next () << endl;
+ }
+ catch (const cli::exception& e)
+ {
+ cerr << e << endl;
+ }
+}
diff --git a/cli-tests/file/test.cli b/cli-tests/file/test.cli
new file mode 100644
index 0000000..c72a495
--- /dev/null
+++ b/cli-tests/file/test.cli
@@ -0,0 +1,7 @@
+// file : file/test.cli
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+class options
+{
+};
diff --git a/cli-tests/file/testscript b/cli-tests/file/testscript
new file mode 100644
index 0000000..d86ec1d
--- /dev/null
+++ b/cli-tests/file/testscript
@@ -0,0 +1,286 @@
+# file : file/testscript
+# license : MIT; see accompanying LICENSE file
+
+# End-of-line marker. Place its expansion in here-documents after the trailing
+# spaces to prevent them from being stripped by editors and to improve
+# readability.
+#
+eol = ""
+
++cat <<EOI >=empty.ops
+# Empty options file.
+#
+
+EOI
++cat <<EOI >=base.ops
+-a 21
+-b 21
+EOI
+
+# @@ Give tests some meaningfull descriptions.
+#
+
+: 000
+:
+cat <<EOI >=test.ops;
+-a 11
+-b 11
+ -a 12
+
+ -b 12
+a
+EOI
+$* -a 1 --file ../empty.ops -b 1 --file ../base.ops --file test.ops b >>EOO
+-a
+1
+-b
+1
+-a
+21
+-b
+21
+-a
+11
+-b
+11
+-a
+12
+-b
+12
+a
+b
+EOO
+
+: 001
+:
+cat <<EOI >=test.ops;
+# Empty options file.
+#
+
+EOI
+$* -a 1 -- --file test.ops b >>EOO
+-a
+1
+--
+--file
+test.ops
+b
+EOO
+
+: 002
+:
+cat <<EOI >=test.ops;
+-a 11
+-b 11
+--
+--file ../base.ops
+-a 12
+-b 12
+a
+EOI
+$* -a 1 --file test.ops --file ../empty.ops b >>EOO
+-a
+1
+-a
+11
+-b
+11
+--
+--file
+../base.ops
+-a
+12
+-b
+12
+a
+--file
+../empty.ops
+b
+EOO
+
+: 003
+:
+$* -a 1 --file ../base.ops --file test.ops b >>EOO 2>>EOE
+-a
+1
+-a
+21
+-b
+21
+EOO
+unable to open file 'test.ops' or read failure
+EOE
+
+: 004
+:
+cat <<EOI >=test.ops;
+-a a"b"c
+-a "abc"
+-a "a"b"
+-a ""
+-a " abc "
+-a " "
+-a """
+-a "'"
+
+-a a'b'c
+-a 'abc'
+-a 'a'b'
+-a ''
+-a ' abc '
+-a ' '
+-a '''
+-a '"'
+EOI
+$* --file test.ops >>"EOO"
+-a
+a"b"c
+-a
+abc
+-a
+a"b
+-a
+
+-a
+ abc $eol
+-a
+ $eol
+-a
+"
+-a
+'
+-a
+a'b'c
+-a
+abc
+-a
+a'b
+-a
+
+-a
+ abc $eol
+-a
+ $eol
+-a
+'
+-a
+"
+EOO
+
+: 005
+:
+cat <<EOI >=test.ops;
+-a "
+EOI
+$* --file test.ops 2>>EOE
+unmatched quote in argument '"'
+EOE
+
+: 006
+:
+cat <<EOI >=test.ops;
+-a "abc
+EOI
+$* --file test.ops 2>>EOE
+unmatched quote in argument '"abc'
+EOE
+
+: 007
+:
+cat <<EOI >=test.ops;
+-a abc"
+EOI
+$* --file test.ops 2>>EOE
+unmatched quote in argument 'abc"'
+EOE
+
+: 008
+:
+cat <<EOI >=test.ops;
+-a '
+EOI
+$* --file test.ops 2>>EOE
+unmatched quote in argument '''
+EOE
+
+: 009
+:
+cat <<EOI >=test.ops;
+-a 'abc
+EOI
+$* --file test.ops 2>>EOE
+unmatched quote in argument ''abc'
+EOE
+
+: 010
+:
+cat <<EOI >=test.ops;
+-a abc'
+EOI
+$* --file test.ops 2>>EOE
+unmatched quote in argument 'abc''
+EOE
+
+: 011
+:
+cat <<EOI >=test.ops;
+-a "abc'
+EOI
+$* --file test.ops 2>>EOE
+unmatched quote in argument '"abc''
+EOE
+
+: 012
+:
+cat <<EOI >=test.ops;
+-a 'abc"
+EOI
+$* --file test.ops 2>>EOE
+unmatched quote in argument ''abc"'
+EOE
+
+: quoted-argument
+:
+cat <<EOI >=test.ops;
+"'foo bar'"
+'"foo bar"'
+EOI
+$* --file test.ops >>EOO
+'foo bar'
+"foo bar"
+EOO
+
+: direct-file-load
+:
+cat <<EOI >=test.ops;
+-f
+-a 123
+EOI
+$* --- test.ops >>EOO
+-f
+-a
+123
+EOO
+
+: direct-file-empty
+:
+cat <<EOI >=test.ops;
+EOI
+$* --- test.ops
+
+: direct-file-load-nested
+:
+cat <<EOI >=test.ops;
+-f
+--file ../base.ops
+-a 123
+EOI
+$* ---- test.ops >>EOO
+-f
+-a
+21
+-b
+21
+-a
+123
+EOO
diff --git a/cli-tests/group/buildfile b/cli-tests/group/buildfile
new file mode 100644
index 0000000..30327e0
--- /dev/null
+++ b/cli-tests/group/buildfile
@@ -0,0 +1,9 @@
+# file : group/buildfile
+# license : MIT; see accompanying LICENSE file
+
+exe{driver}: {hxx cxx}{* -test} cli.cxx{test} testscript
+
+cxx.poptions =+ "-I$out_base"
+
+cli.cxx{test}: cli{test}
+cli.options = --generate-group-scanner
diff --git a/cli-tests/group/driver.cxx b/cli-tests/group/driver.cxx
new file mode 100644
index 0000000..68f6107
--- /dev/null
+++ b/cli-tests/group/driver.cxx
@@ -0,0 +1,58 @@
+// file : group/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+// Test group_scanner.
+//
+
+#include <iostream>
+
+#include "test.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ using namespace cli;
+
+ // Mode flags.
+ //
+ // 'g' -- don't handle groups.
+ // 's' -- skip arguments.
+ //
+ string m (argv[1]);
+
+ argv_scanner as (--argc, ++argv);
+ group_scanner s (as);
+
+ while (s.more ())
+ {
+ if (m.find ('s') == string::npos)
+ {
+ const char* a (s.next ());
+ cout << "'" << a << "'";
+ }
+ else
+ s.skip ();
+
+ if (m.find ('g') == string::npos)
+ {
+ scanner& gs (s.group ());
+ while (gs.more ())
+ cout << " '" << gs.next () << "'";
+ }
+
+ cout << endl;
+ }
+
+ return 0;
+ }
+ catch (const cli::exception& e)
+ {
+ cerr << e << endl;
+ return 1;
+ }
+}
diff --git a/cli-tests/group/test.cli b/cli-tests/group/test.cli
new file mode 100644
index 0000000..8725791
--- /dev/null
+++ b/cli-tests/group/test.cli
@@ -0,0 +1,7 @@
+// file : group/test.cli
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+class options
+{
+};
diff --git a/cli-tests/group/testscript b/cli-tests/group/testscript
new file mode 100644
index 0000000..6269ca2
--- /dev/null
+++ b/cli-tests/group/testscript
@@ -0,0 +1,140 @@
+# file : group/testscript
+# license : MIT; see accompanying LICENSE file
+
+: no-args
+:
+$* ''
+
+: no-groups
+:
+$* '' --foo arg >>EOO
+'--foo'
+'arg'
+EOO
+
+: group-pre
+:
+$* '' { --foo --bar }+ arg1 arg2 >>EOO
+'arg1' '--foo' '--bar'
+'arg2'
+EOO
+
+: group-pre-multi
+:
+$* '' { --foo }+ { --bar }+ arg1 arg2 >>EOO
+'arg1' '--foo' '--bar'
+'arg2'
+EOO
+
+: group-post
+:
+$* '' arg1 arg2 +{ foo bar } >>EOO
+'arg1'
+'arg2' 'foo' 'bar'
+EOO
+
+: group-post-multi
+:
+$* '' arg1 arg2 +{ foo } +{ bar } >>EOO
+'arg1'
+'arg2' 'foo' 'bar'
+EOO
+
+: group-both
+:
+$* '' arg1 { --foo --bar }+ arg2 +{ foo bar } arg3 >>EOO
+'arg1'
+'arg2' '--foo' '--bar' 'foo' 'bar'
+'arg3'
+EOO
+
+: group-both-multi
+:
+$* '' arg1 { --foo }+ { --bar }+ arg2 +{ foo } +{ bar } arg3 >>EOO
+'arg1'
+'arg2' '--foo' '--bar' 'foo' 'bar'
+'arg3'
+EOO
+
+: multi-group
+:
+$* '' { --foo }+ arg1 arg2 +{ bar } >>EOO
+'arg1' '--foo'
+'arg2' 'bar'
+EOO
+
+: empty-group
+:
+$* '' { }+ arg1 arg2 +{ } >>EOO
+'arg1'
+'arg2'
+EOO
+
+: escape-arg
+:
+$* '' '\{' '\}' '\+{' '\}+' '{x' '}x' >>EOO
+'{'
+'}'
+'+{'
+'}+'
+'{x'
+'}x'
+EOO
+
+: escape-group
+:
+$* '' { '\{' '\}' '\+{' '\}+' '{x' '}x' }+ arg >>EOO
+'arg' '{' '}' '+{' '}+' '{x' '}x'
+EOO
+
+: not-group
+:
+$* '' { --foo } 2>>EOE != 0
+expected group separator '}+' instead of '}', use '\}' to escape
+EOE
+
+: no-arg-pre
+:
+$* '' { --foo }+ 2>>EOE != 0
+unexpected group separator '{', use '\{' to escape
+EOE
+
+: no-arg-pre-empty
+:
+$* '' { }+ 2>>EOE != 0
+unexpected group separator '{', use '\{' to escape
+EOE
+
+: no-arg-post
+:
+$* '' +{ --foo } 2>>EOE != 0
+unexpected group separator '+{', use '\+{' to escape
+EOE
+
+: no-arg-post-empty
+:
+$* '' +{ } 2>>EOE != 0
+unexpected group separator '+{', use '\+{' to escape
+EOE
+
+: unhandled-group-pre
+:
+$* 'g' { --foo }+ arg >>EOO 2>>EOE != 0
+'arg'
+EOO
+unexpected grouped argument '--foo' for argument 'arg'
+EOE
+
+: unhandled-group-post
+:
+$* 'g' arg +{ bar } >>EOO 2>>EOE != 0
+'arg'
+EOO
+unexpected grouped argument 'bar' for argument 'arg'
+EOE
+
+: unhandled-group-skip
+:
+$* 'sg' { --foo }+ arg +{ bar } >>EOO
+
+EOO
diff --git a/cli-tests/headings/buildfile b/cli-tests/headings/buildfile
new file mode 100644
index 0000000..af3ae75
--- /dev/null
+++ b/cli-tests/headings/buildfile
@@ -0,0 +1,6 @@
+# file : headings/buildfile
+# license : MIT; see accompanying LICENSE file
+
+./: testscript $cli
+
+testscript{*}: test = $cli
diff --git a/cli-tests/headings/testscript b/cli-tests/headings/testscript
new file mode 100644
index 0000000..0efb7ae
--- /dev/null
+++ b/cli-tests/headings/testscript
@@ -0,0 +1,36 @@
+# file : headings/testscript
+# license : MIT; see accompanying LICENSE file
+
+: auto-headings
+:
+: Note that auto-headings break if we split into multiple doc strings.
+:
+cat <<EOI >=map.cli;
+"
+\h1|Heading 1|
+
+\h|Heading 1.1|
+
+\h2|Heading 1.1.1|
+
+\h|Heading 1.2|
+
+\h2|Heading 1.2.1|
+
+\h1|Heading 2|
+"
+EOI
+$* --generate-html --stdout map.cli >>EOO
+ <h1>Heading 1</h1>
+
+ <h2>Heading 1.1</h2>
+
+ <h3>Heading 1.1.1</h3>
+
+ <h2>Heading 1.2</h2>
+
+ <h3>Heading 1.2.1</h3>
+
+ <h1>Heading 2</h1>
+
+EOO
diff --git a/cli-tests/inheritance/buildfile b/cli-tests/inheritance/buildfile
new file mode 100644
index 0000000..6fe1ecc
--- /dev/null
+++ b/cli-tests/inheritance/buildfile
@@ -0,0 +1,11 @@
+# file : inheritance/buildfile
+# license : MIT; see accompanying LICENSE file
+
+exe{driver}: {hxx cxx}{* -test} cli.cxx{test}
+exe{driver}: file{test.std}: test.stdout = true
+exe{driver}: test.arguments = --very-long-flag -s short -i 123 --string long
+
+cxx.poptions =+ "-I$out_base"
+
+cli.cxx{test}: cli{test}
+cli.options = --generate-description --option-length 17
diff --git a/cli-tests/inheritance/driver.cxx b/cli-tests/inheritance/driver.cxx
new file mode 100644
index 0000000..4acab0d
--- /dev/null
+++ b/cli-tests/inheritance/driver.cxx
@@ -0,0 +1,35 @@
+// file : inheritance/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+// Test option class inheritance.
+//
+
+#include <string>
+#include <cassert>
+#include <iostream>
+
+#include "test.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ const cli::options& d (options::description ());
+
+ assert (d.size () == 4);
+ assert (d[0].name () == "--very-long-flag");
+ assert (d[1].name () == "-i");
+ assert (d[2].name () == "-s");
+ assert (d[3].name () == "--string");
+
+ options o (argc, argv);
+
+ assert (o.very_long_flag ());
+ assert (o.s () == "short");
+ assert (o.i () == 123);
+ assert (o.string () == "long");
+
+ options::print_usage (cout);
+}
diff --git a/cli-tests/inheritance/test.cli b/cli-tests/inheritance/test.cli
new file mode 100644
index 0000000..3b73848
--- /dev/null
+++ b/cli-tests/inheritance/test.cli
@@ -0,0 +1,25 @@
+// file : inheritance/test.cli
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+include <string>;
+
+class base1 = 0
+{
+ bool --very-long-flag {"Long flag."};
+};
+
+class base2
+{
+ std::string -s {"<str>", "Short string."};
+};
+
+class interm: base1
+{
+ int -i = 1 {"<num>", "Integer."};
+};
+
+class options: interm, base2
+{
+ std::string --string {"<str>", "Long string."};
+};
diff --git a/cli-tests/inheritance/test.std b/cli-tests/inheritance/test.std
new file mode 100644
index 0000000..4c93225
--- /dev/null
+++ b/cli-tests/inheritance/test.std
@@ -0,0 +1,4 @@
+--very-long-flag Long flag.
+-i <num> Integer.
+-s <str> Short string.
+--string <str> Long string.
diff --git a/cli-tests/manifest b/cli-tests/manifest
new file mode 100644
index 0000000..a7898ce
--- /dev/null
+++ b/cli-tests/manifest
@@ -0,0 +1,15 @@
+: 1
+name: cli-tests
+version: 1.2.0-b.6.z
+project: cli
+summary: Tests for the CLI compiler for C++
+license: MIT
+description-file: README
+url: https://www.codesynthesis.com/projects/cli/
+doc-url: https://www.codesynthesis.com/projects/cli/doc/guide/
+src-url: https://git.codesynthesis.com/cgit/cli/cli/tree/cli-tests
+email: cli-users@codesynthesis.com ; Mailing list
+build-email: builds@codesynthesis.com
+requires: c++14
+depends: * build2 >= 0.13.0-
+depends: * bpkg >= 0.13.0-
diff --git a/cli-tests/merge/buildfile b/cli-tests/merge/buildfile
new file mode 100644
index 0000000..ed93cda
--- /dev/null
+++ b/cli-tests/merge/buildfile
@@ -0,0 +1,9 @@
+# file : merge/buildfile
+# license : MIT; see accompanying LICENSE file
+
+exe{driver}: {hxx cxx}{* -test} cli.cxx{test}
+
+cxx.poptions =+ "-I$out_base"
+
+cli.cxx{test}: cli{test}
+cli.options = --generate-merge
diff --git a/cli-tests/merge/driver.cxx b/cli-tests/merge/driver.cxx
new file mode 100644
index 0000000..43b1c59
--- /dev/null
+++ b/cli-tests/merge/driver.cxx
@@ -0,0 +1,55 @@
+// file : merge/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+// Test parsed options merging.
+//
+
+#include <string>
+#include <cassert>
+
+#include "test.hxx"
+
+using namespace std;
+
+template <typename T, int N1, int N2>
+static T
+merge (const char* (&av1)[N1], const char* (&av2)[N2])
+{
+ int ac1 (N1);
+ int ac2 (N2);
+ T o1 (ac1, const_cast<char**> (av1));
+ T o2 (ac2, const_cast<char**> (av2));
+ o1.merge (o2);
+ return o1;
+}
+
+int
+main ()
+{
+ // Basics.
+ //
+ {
+ const char* a1[] = {"", "-i=123", "-v=1", "-v=2"};
+ const char* a2[] = {"", "-b", "-i=456", "-s=xyz", "-v=3", "-v=4"};
+ derived r (merge<derived> (a1, a2));
+
+ assert (r.b ());
+ assert (r.i_specified () && r.i () == 456);
+ assert (r.s_specified () && r.s () == "xyz");
+ assert (r.v_specified () && r.v ().size () == 4 &&
+ r.v ()[0] == 1 &&
+ r.v ()[1] == 2 &&
+ r.v ()[2] == 3 &&
+ r.v ()[3] == 4);
+ }
+
+ // Default value does not override.
+ //
+ {
+ const char* a1[] = {"", "-i=456"};
+ const char* a2[] = {"" };
+ derived r (merge<derived> (a1, a2));
+ assert (r.i_specified () && r.i () == 456);
+ }
+}
diff --git a/cli-tests/merge/test.cli b/cli-tests/merge/test.cli
new file mode 100644
index 0000000..67f50c6
--- /dev/null
+++ b/cli-tests/merge/test.cli
@@ -0,0 +1,18 @@
+// file : merge/test.cli
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+include <string>;
+include <vector>;
+
+class base
+{
+ bool -b;
+ int -i = -1;
+ std::string -s;
+};
+
+class derived: base
+{
+ std::vector<int> -v;
+};
diff --git a/cli-tests/note/buildfile b/cli-tests/note/buildfile
new file mode 100644
index 0000000..c8cf49b
--- /dev/null
+++ b/cli-tests/note/buildfile
@@ -0,0 +1,6 @@
+# file : note/buildfile
+# license : MIT; see accompanying LICENSE file
+
+./: testscript $cli
+
+testscript{*}: test = $cli
diff --git a/cli-tests/note/testscript b/cli-tests/note/testscript
new file mode 100644
index 0000000..9f00811
--- /dev/null
+++ b/cli-tests/note/testscript
@@ -0,0 +1,197 @@
+# file : note/testscript
+# license : MIT; see accompanying LICENSE file
+
+: block-basics
+:
+cat <<EOI >=test.cli;
+"
+Leading paragraph.
+
+\N|This is a note block one.|
+
+Interleaving paragraph that is quite long and therefore it may span many
+lines in order to make text easy to read.
+
+\N|This is a note block two that is quite long and therefore it may span many
+lines in order to make text easy to read.|
+
+Trailing paragraph.
+"
+EOI
+$* --generate-html --stdout test.cli >>EOO;
+ <p>Leading paragraph.</p>
+
+ <div class="note">
+ <p>This is a note block one.</p>
+ </div>
+
+ <p>Interleaving paragraph that is quite long and therefore it may span many
+ lines in order to make text easy to read.</p>
+
+ <div class="note">
+ <p>This is a note block two that is quite long and therefore it may span
+ many lines in order to make text easy to read.</p>
+ </div>
+
+ <p>Trailing paragraph.</p>
+
+EOO
+ $* --generate-txt --stdout test.cli >>EOO
+Leading paragraph.
+
+| This is a note block one.
+
+Interleaving paragraph that is quite long and therefore it may span many lines
+in order to make text easy to read.
+
+| This is a note block two that is quite long and therefore it may span many
+| lines in order to make text easy to read.
+
+Trailing paragraph.
+EOO
+
+
+: block-multi-para
+:
+cat <<EOI >=test.cli;
+"
+\N|
+This is a note para one that is quite long and therefore it may span many
+lines in order to make text easy to read.
+
+This is a note para two.
+|
+"
+EOI
+$* --generate-html --stdout test.cli >>EOO;
+ <div class="note">
+ <p>This is a note para one that is quite long and therefore it may span many
+ lines in order to make text easy to read.</p>
+
+ <p>This is a note para two.</p>
+ </div>
+
+EOO
+$* --generate-txt --stdout test.cli >>EOO
+| This is a note para one that is quite long and therefore it may span many
+| lines in order to make text easy to read.
+|
+| This is a note para two.
+EOO
+
+: block-pre
+:
+cat <<EOI >=test.cli;
+"
+
+\N|
+This is a note para one.
+
+\
+And this is a
+pre-formatter text fragment.
+\
+
+|
+"
+EOI
+$* --generate-html --stdout test.cli >>EOO;
+ <div class="note">
+ <p>This is a note para one.</p>
+
+ <pre>And this is a
+pre-formatter text fragment.</pre>
+ </div>
+
+EOO
+$* --generate-txt --stdout test.cli >>EOO
+| This is a note para one.
+|
+| And this is a
+| pre-formatter text fragment.
+EOO
+
+# This is not yet supported (see txt_wrap_lines()).
+#
+#\
+: block-list
+:
+cat <<EOI >=test.cli;
+"
+\N|This is a note para one followed by a list.
+
+\ul|
+
+\li|This is a list item that is quite long and therefore it may span many
+lines in order to make text easy to read.|||
+"
+EOI
+$* --generate-html --stdout test.cli >>EOO;
+EOO
+$* --generate-txt --stdout test.cli >>EOO
+EOO
+#\
+
+: block-in-list
+:
+cat <<EOI >=test.cli;
+"
+\ul|
+
+\li|Normal text para.
+
+\N|This is a note para one that is quite long and therefore it may span many
+lines in order to make text easy to read.|||
+"
+EOI
+$* --generate-html --stdout test.cli >>EOO;
+ <ul>
+ <li>Normal text para.
+
+ <div class="note">
+ <p>This is a note para one that is quite long and therefore it may span many
+ lines in order to make text easy to read.</p>
+ </div></li>
+ </ul>
+
+EOO
+$* --generate-txt --stdout test.cli >>EOO
+* Normal text para.
+
+ | This is a note para one that is quite long and therefore it may span many
+ | lines in order to make text easy to read.
+EOO
+
+
+: span-basics
+:
+cat <<EOI >=test.cli;
+"
+This is normal text. \N{This is a note.} And this is normal text again.
+"
+EOI
+$* --generate-html --stdout test.cli >>EOO;
+ <p>This is normal text. <span class="note">This is a note.</span> And this
+ is normal text again.</p>
+
+EOO
+ $* --generate-txt --stdout test.cli >>EOO
+This is normal text. [Note: This is a note.] And this is normal text again.
+EOO
+
+
+: span-nested-link
+:
+cat <<EOI >=test.cli;
+"
+\N{This is a note with a \l{https://example.com link} inside.}
+"
+EOI
+$* --generate-html --stdout test.cli >>EOO;
+ <p><span class="note">This is a note with a <a
+ href="https://example.com">link</a> inside.</span></p>
+
+EOO
+$* --generate-txt --stdout test.cli >>EOO
+[Note: This is a note with a link (https://example.com) inside.]
+EOO
diff --git a/cli-tests/specifier/buildfile b/cli-tests/specifier/buildfile
new file mode 100644
index 0000000..935a002
--- /dev/null
+++ b/cli-tests/specifier/buildfile
@@ -0,0 +1,10 @@
+# file : specifier/buildfile
+# license : MIT; see accompanying LICENSE file
+
+exe{driver}: {hxx cxx}{* -test} cli.cxx{test}
+exe{driver}: test.arguments = -a -c foo
+
+cxx.poptions =+ "-I$out_base"
+
+cli.cxx{test}: cli{test}
+cli.options = --generate-specifier --generate-modifier
diff --git a/cli-tests/specifier/driver.cxx b/cli-tests/specifier/driver.cxx
new file mode 100644
index 0000000..50b9cf5
--- /dev/null
+++ b/cli-tests/specifier/driver.cxx
@@ -0,0 +1,29 @@
+// file : specifier/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+// Test specifier functions.
+//
+
+#include <string>
+#include <cassert>
+
+#include "test.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ options o (argc, argv);
+
+ assert (o.a ());
+ assert (o.b () == 1 && !o.b_specified ());
+ assert (o.c () == "foo" && o.c_specified ());
+
+ o.b_specified (true);
+ o.c_specified (false);
+
+ assert (o.b_specified ());
+ assert (!o.c_specified ());
+}
diff --git a/cli-tests/specifier/test.cli b/cli-tests/specifier/test.cli
new file mode 100644
index 0000000..c11ebb7
--- /dev/null
+++ b/cli-tests/specifier/test.cli
@@ -0,0 +1,12 @@
+// file : specifier/test.cli
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+include <string>;
+
+class options
+{
+ bool -a;
+ int -b = 1;
+ std::string -c;
+};
diff --git a/cli-tests/toc/buildfile b/cli-tests/toc/buildfile
new file mode 100644
index 0000000..3be6359
--- /dev/null
+++ b/cli-tests/toc/buildfile
@@ -0,0 +1,6 @@
+# file : toc/buildfile
+# license : MIT; see accompanying LICENSE file
+
+./: testscript $cli
+
+testscript{*}: test = $cli
diff --git a/cli-tests/toc/testscript b/cli-tests/toc/testscript
new file mode 100644
index 0000000..70e9065
--- /dev/null
+++ b/cli-tests/toc/testscript
@@ -0,0 +1,155 @@
+# file : toc/testscript
+# license : MIT; see accompanying LICENSE file
+
+: toc
+:
+cat <<EOI >=toc.cli;
+"\h1|Table of Contents|"
+"\$TOC$"
+
+"
+\h0#preface|Preface|
+
+This document describes something awesome.
+
+\h#about-document|About This Document|
+
+And this document is also awesome.
+
+\h#more-information|More Information|
+
+It is so awesome that no further information will be required."
+
+"
+\H#part1|PART I|
+
+Start of part one.
+
+\h1#intro|Introduction|
+
+Beginning of the first chapter.
+
+\h#arch-flow|Architecture and Workflow|
+
+Some basics.
+
+\h#benefits|Benefits|
+
+You will like them.
+
+\h1#hello|Hello World|
+
+Beginning of the second chapter.
+
+\h#hell-setup|Setup|
+
+More basics.
+
+\h#hello-compile|Compiling|
+
+How to build the example
+
+\h2#hello-compile-gcc|Compiling with GCC|
+
+GCC. For Clang see \l{#hello-compile-clang Compiling with Clang}.
+
+\h2#hello-compile-clang|Compiling with Clang|
+
+Clang. For GCC see \l{#hello-compile-gcc Compiling with GCC}.
+
+\h#hello-conclusion|Conclusion|
+
+Some remarks.
+"
+EOI
+$* --generate-html --stdout toc.cli >>EOO
+ <h1>Table of Contents</h1>
+
+ <table class="toc">
+ <tr><td class="preface" colspan="2"><a href="#preface">Preface</a>
+ <table class="toc">
+ <tr><td class="preface" colspan="2"><a href="#about-document">About
+This Document</a></td></tr>
+ <tr><td class="preface" colspan="2"><a href="#more-information">More
+Information</a></td></tr>
+ </table>
+ </td></tr>
+ <tr><th colspan="2"><a href="#part1">PART I</a></th></tr>
+ <tr><th>1</th><td><a href="#intro">Introduction</a>
+ <table class="toc">
+ <tr><th>1.1</th><td><a href="#arch-flow">Architecture and
+Workflow</a></td></tr>
+ <tr><th>1.2</th><td><a href="#benefits">Benefits</a></td></tr>
+ </table>
+ </td></tr>
+ <tr><th>2</th><td><a href="#hello">Hello World</a>
+ <table class="toc">
+ <tr><th>2.1</th><td><a href="#hell-setup">Setup</a></td></tr>
+ <tr><th>2.2</th><td><a href="#hello-compile">Compiling</a>
+ <table class="toc">
+ <tr><th>2.2.1</th><td><a href="#hello-compile-gcc">Compiling with
+GCC</a></td></tr>
+ <tr><th>2.2.2</th><td><a href="#hello-compile-clang">Compiling
+with Clang</a></td></tr>
+ </table>
+ </td></tr>
+ <tr><th>2.3</th><td><a href="#hello-conclusion">Conclusion</a></td></tr>
+ </table>
+ </td></tr>
+ </table>
+
+ <h1 id="preface" class="preface">Preface</h1>
+
+ <p>This document describes something awesome.</p>
+
+ <h2 id="about-document">About This Document</h2>
+
+ <p>And this document is also awesome.</p>
+
+ <h2 id="more-information">More Information</h2>
+
+ <p>It is so awesome that no further information will be required.</p>
+
+ <h1 id="part1" class="part">PART I</h1>
+
+ <p>Start of part one.</p>
+
+ <h1 id="intro">1 Introduction</h1>
+
+ <p>Beginning of the first chapter.</p>
+
+ <h2 id="arch-flow">1.1 Architecture and Workflow</h2>
+
+ <p>Some basics.</p>
+
+ <h2 id="benefits">1.2 Benefits</h2>
+
+ <p>You will like them.</p>
+
+ <h1 id="hello">2 Hello World</h1>
+
+ <p>Beginning of the second chapter.</p>
+
+ <h2 id="hell-setup">2.1 Setup</h2>
+
+ <p>More basics.</p>
+
+ <h2 id="hello-compile">2.2 Compiling</h2>
+
+ <p>How to build the example</p>
+
+ <h3 id="hello-compile-gcc">2.2.1 Compiling with GCC</h3>
+
+ <p>GCC. For Clang see <a href="#hello-compile-clang">Compiling with
+ Clang</a>.</p>
+
+ <h3 id="hello-compile-clang">2.2.2 Compiling with Clang</h3>
+
+ <p>Clang. For GCC see <a href="#hello-compile-gcc">Compiling with
+ GCC</a>.</p>
+
+ <h2 id="hello-conclusion">2.3 Conclusion</h2>
+
+ <p>Some remarks.</p>
+
+EOO