diff --git a/.github/workflows/CI-unixish.yml b/.github/workflows/CI-unixish.yml index 7a64ee14..3a604900 100644 --- a/.github/workflows/CI-unixish.yml +++ b/.github/workflows/CI-unixish.yml @@ -1,4 +1,4 @@ -name: CI Unixish +name: CI-unixish on: [push, pull_request] @@ -28,6 +28,10 @@ jobs: - name: make test run: make -j$(nproc) test CXX=${{ matrix.compiler }} + - name: selfcheck + run: | + make -j$(nproc) selfcheck CXX=${{ matrix.compiler }} + - name: Run valgrind if: matrix.os == 'ubuntu-22.04' run: | @@ -35,24 +39,25 @@ jobs: # this valgrind version doesn't support DWARF 5 yet make -j$(nproc) CXX=${{ matrix.compiler }} CXXFLAGS="-gdwarf-4" valgrind --leak-check=full --num-callers=50 --show-reachable=yes --track-origins=yes --gen-suppressions=all --error-exitcode=42 ./testrunner + valgrind --leak-check=full --num-callers=50 --show-reachable=yes --track-origins=yes --gen-suppressions=all --error-exitcode=42 ./simplecpp simplecpp.cpp -e - name: Run with libstdc++ debug mode if: matrix.os == 'ubuntu-22.04' && matrix.compiler == 'g++' run: | make clean - make -j$(nproc) test CXX=${{ matrix.compiler }} CXXFLAGS="-g3 -D_GLIBCXX_DEBUG" + make -j$(nproc) test selfcheck CXX=${{ matrix.compiler }} CXXFLAGS="-g3 -D_GLIBCXX_DEBUG" - name: Run with libc++ debug mode if: matrix.os == 'ubuntu-22.04' && matrix.compiler == 'clang++' run: | make clean - make -j$(nproc) test CXX=${{ matrix.compiler }} CXXFLAGS="-stdlib=libc++ -g3 -D_LIBCPP_ENABLE_ASSERTIONS=1" LDFLAGS="-lc++" + make -j$(nproc) test selfcheck CXX=${{ matrix.compiler }} CXXFLAGS="-stdlib=libc++ -g3 -D_LIBCPP_ENABLE_ASSERTIONS=1" LDFLAGS="-lc++" - name: Run AddressSanitizer if: matrix.os == 'ubuntu-22.04' run: | make clean - make -j$(nproc) test CXX=${{ matrix.compiler }} CXXFLAGS="-O2 -g3 -fsanitize=address" LDFLAGS="-fsanitize=address" + make -j$(nproc) test selfcheck CXX=${{ matrix.compiler }} CXXFLAGS="-O2 -g3 -fsanitize=address" LDFLAGS="-fsanitize=address" env: ASAN_OPTIONS: detect_stack_use_after_return=1 @@ -60,11 +65,11 @@ jobs: if: matrix.os == 'ubuntu-22.04' run: | make clean - make -j$(nproc) test CXX=${{ matrix.compiler }} CXXFLAGS="-O2 -g3 -fsanitize=undefined -fno-sanitize=signed-integer-overflow" LDFLAGS="-fsanitize=undefined -fno-sanitize=signed-integer-overflow" + make -j$(nproc) test selfcheck CXX=${{ matrix.compiler }} CXXFLAGS="-O2 -g3 -fsanitize=undefined -fno-sanitize=signed-integer-overflow" LDFLAGS="-fsanitize=undefined -fno-sanitize=signed-integer-overflow" # TODO: requires instrumented libc++ - name: Run MemorySanitizer if: false && matrix.os == 'ubuntu-22.04' && matrix.compiler == 'clang++' run: | make clean - make -j$(nproc) test CXX=${{ matrix.compiler }} CXXFLAGS="-O2 -g3 -stdlib=libc++ -fsanitize=memory" LDFLAGS="-lc++ -fsanitize=memory" + make -j$(nproc) test selfcheck CXX=${{ matrix.compiler }} CXXFLAGS="-O2 -g3 -stdlib=libc++ -fsanitize=memory" LDFLAGS="-lc++ -fsanitize=memory" diff --git a/.github/workflows/CI-windows.yml b/.github/workflows/CI-windows.yml index aca68c93..1c4e3404 100644 --- a/.github/workflows/CI-windows.yml +++ b/.github/workflows/CI-windows.yml @@ -46,4 +46,8 @@ jobs: - name: Test run: | .\${{ matrix.config }}\testrunner.exe || exit /b !errorlevel! + + - name: Selfcheck + run: | + .\${{ matrix.config }}\simplecpp.exe simplecpp.cpp -e || exit /b !errorlevel! diff --git a/Makefile b/Makefile index a209666e..db1ca257 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,9 @@ test: testrunner simplecpp ./testrunner python3 run-tests.py +selfcheck: simplecpp + ./selfcheck.sh + simplecpp: main.o simplecpp.o $(CXX) $(LDFLAGS) main.o simplecpp.o -o simplecpp diff --git a/appveyor.yml b/appveyor.yml index 00136602..ea8dd1df 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,3 +17,4 @@ build_script: test_script: - debug\testrunner.exe + - debug\simplecpp.exe simplecpp.cpp -e diff --git a/main.cpp b/main.cpp index 6592bf6c..7516085f 100644 --- a/main.cpp +++ b/main.cpp @@ -31,25 +31,34 @@ int main(int argc, char **argv) // Settings.. simplecpp::DUI dui; bool quiet = false; + bool error_only = false; for (int i = 1; i < argc; i++) { const char * const arg = argv[i]; if (*arg == '-') { bool found = false; const char c = arg[1]; - const char * const value = arg[2] ? (argv[i] + 2) : argv[++i]; switch (c) { case 'D': // define symbol + { + const char * const value = arg[2] ? (argv[i] + 2) : argv[++i]; dui.defines.push_back(value); found = true; break; + } case 'U': // undefine symbol + { + const char * const value = arg[2] ? (argv[i] + 2) : argv[++i]; dui.undefined.insert(value); found = true; break; + } case 'I': // include path + { + const char * const value = arg[2] ? (argv[i] + 2) : argv[++i]; dui.includePaths.push_back(value); found = true; break; + } case 'i': if (std::strncmp(arg, "-include=",9)==0) { dui.includes.push_back(arg+9); @@ -70,11 +79,18 @@ int main(int argc, char **argv) quiet = true; found = true; break; + case 'e': + error_only = true; + found = true; + break; } if (!found) { - std::cout << "Option '" << arg << "' is unknown." << std::endl; + std::cout << "error: option '" << arg << "' is unknown." << std::endl; error = true; } + } else if (filename) { + std::cout << "error: multiple filenames specified" << std::endl; + std::exit(1); } else { filename = arg; } @@ -83,6 +99,11 @@ int main(int argc, char **argv) if (error) std::exit(1); + if (quiet && error_only) { + std::cout << "error: -e cannot be used in conjunction with -q" << std::endl; + std::exit(1); + } + if (!filename) { std::cout << "Syntax:" << std::endl; std::cout << "simplecpp [options] filename" << std::endl; @@ -93,6 +114,7 @@ int main(int argc, char **argv) std::cout << " -std=STD Specify standard." << std::endl; std::cout << " -q Quiet mode (no output)." << std::endl; std::cout << " -is Use std::istream interface." << std::endl; + std::cout << " -e Output errors only." << std::endl; std::exit(0); } @@ -102,6 +124,10 @@ int main(int argc, char **argv) simplecpp::TokenList *rawtokens; if (use_istream) { std::ifstream f(filename); + if (!f.is_open()) { + std::cout << "error: could not open file '" << filename << "'" << std::endl; + std::exit(1); + } rawtokens = new simplecpp::TokenList(f, files,filename,&outputList); } else { @@ -118,7 +144,8 @@ int main(int argc, char **argv) // Output if (!quiet) { - std::cout << outputTokens.stringify() << std::endl; + if (!error_only) + std::cout << outputTokens.stringify() << std::endl; for (const simplecpp::Output &output : outputList) { std::cerr << output.location.file() << ':' << output.location.line << ": "; diff --git a/selfcheck.sh b/selfcheck.sh new file mode 100755 index 00000000..3518c654 --- /dev/null +++ b/selfcheck.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +output=$(./simplecpp simplecpp.cpp -e 2>&1) +ec=$? +echo "$output" | grep -v 'Header not found: <' +exit $ec \ No newline at end of file