├── .codecov.yml
├── .cproject
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── .gitmodules
├── .project
├── .settings
├── org.eclipse.cdt.codan.core.prefs
├── org.eclipse.cdt.core.prefs
├── org.eclipse.cdt.ui.prefs
└── org.eclipse.ltk.core.refactoring.prefs
├── CMakeLists.txt
├── LICENSE
├── README.md
├── api
└── ccs
│ ├── ccs.h
│ ├── context.h
│ ├── domain.h
│ ├── rule_builder.h
│ └── types.h
├── misc
├── CCS.xml
├── README.md
├── ccs.vim
└── grammar.txt
├── src
├── CMakeLists.txt
├── context.cpp
├── dag
│ ├── dag_builder.h
│ ├── key.cpp
│ ├── key.h
│ ├── node.h
│ ├── property.cpp
│ ├── property.h
│ ├── specificity.h
│ ├── tally.cpp
│ └── tally.h
├── domain.cpp
├── graphviz.cpp
├── graphviz.h
├── parser
│ ├── ast.cpp
│ ├── ast.h
│ ├── build_context.cpp
│ ├── build_context.h
│ ├── loader.h
│ ├── parser.cpp
│ └── parser.h
├── rule_builder.cpp
├── search_state.cpp
└── search_state.h
├── test
├── CMakeLists.txt
├── acceptance_tests.cpp
├── ccs_test.cpp
├── context_test.cpp
└── parser
│ └── parser_test.cpp
└── tests.txt
/.codecov.yml:
--------------------------------------------------------------------------------
1 | ignore:
2 | - "external/**/*"
3 | # seems like you shouldn't need both of these, but you do...
4 | - "test/*"
5 | - "test/**/*"
6 |
--------------------------------------------------------------------------------
/.cproject:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 | workflow_dispatch:
9 |
10 | jobs:
11 | build:
12 | name: ${{ matrix.name }}
13 | runs-on: ${{ matrix.os }}
14 | strategy:
15 | fail-fast: false
16 | matrix:
17 | include:
18 | - name: Linux GCC 10 Debug/Coverage
19 | os: ubuntu-latest
20 | env: BUILD_TYPE=Debug EXTRA_CMAKE=-DCOVERAGE=On GCOV=gcov-10 CC=gcc-10 CXX=g++-10
21 | - name: Linux GCC 10 Release
22 | os: ubuntu-latest
23 | env: BUILD_TYPE=Release LTO=On CC=gcc-10 CXX=g++-10
24 | - name: Linux GCC 9 Release
25 | os: ubuntu-latest
26 | env: BUILD_TYPE=Release LTO=On CC=gcc-9 CXX=g++-9
27 | - name: Linux Clang 14 Release
28 | os: ubuntu-latest
29 | env: BUILD_TYPE=Release LTO=On CC=clang-14 CXX=clang++-14
30 | - name: Linux Clang 13 Release
31 | os: ubuntu-latest
32 | env: BUILD_TYPE=Release LTO=On CC=clang-13 CXX=clang++-13
33 | - name: Linux Clang 12 Release
34 | os: ubuntu-latest
35 | env: BUILD_TYPE=Release LTO=On CC=clang-12 CXX=clang++-12
36 | - name: OSX GCC 11 Release
37 | os: macos-latest
38 | env: BUILD_TYPE=Release CC=gcc-11 CXX=g++-11
39 | - name: OSX Clang 12 Release
40 | os: macos-latest
41 | env: BUILD_TYPE=Release
42 | steps:
43 | - uses: actions/checkout@v2
44 | with:
45 | submodules: true
46 | - name: CMake Build
47 | run: |
48 | eval ${{ matrix.env }}
49 | export CC CXX
50 | mkdir out
51 | cd out
52 | cmake -Wno-dev -DCMAKE_BUILD_TYPE=${BUILD_TYPE} ${EXTRA_CMAKE} ..
53 | cmake --build . -- -j2
54 | ctest --output-on-failure -D ExperimentalBuild -j2
55 | ctest --output-on-failure -D ExperimentalTest -j2
56 | [[ -z "${GCOV}" ]] || find . -type f -name '*.gcno' -exec ${GCOV} -pabcfu '{}' +
57 | - name: Codecov Upload
58 | if: contains(matrix.name, 'Coverage')
59 | uses: codecov/codecov-action@v2
60 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /out
3 | /.vscode
4 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "external/googletest"]
2 | path = external/googletest
3 | url = https://github.com/google/googletest
4 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | ccs-cpp
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
10 |
11 |
12 | ?name?
13 |
14 |
15 |
16 | org.eclipse.cdt.make.core.append_environment
17 | true
18 |
19 |
20 | org.eclipse.cdt.make.core.autoBuildTarget
21 | all
22 |
23 |
24 | org.eclipse.cdt.make.core.buildArguments
25 | -j
26 |
27 |
28 | org.eclipse.cdt.make.core.buildCommand
29 | make
30 |
31 |
32 | org.eclipse.cdt.make.core.cleanBuildTarget
33 | clean
34 |
35 |
36 | org.eclipse.cdt.make.core.contents
37 | org.eclipse.cdt.make.core.activeConfigSettings
38 |
39 |
40 | org.eclipse.cdt.make.core.enableAutoBuild
41 | true
42 |
43 |
44 | org.eclipse.cdt.make.core.enableCleanBuild
45 | true
46 |
47 |
48 | org.eclipse.cdt.make.core.enableFullBuild
49 | true
50 |
51 |
52 | org.eclipse.cdt.make.core.fullBuildTarget
53 | all
54 |
55 |
56 | org.eclipse.cdt.make.core.stopOnError
57 | true
58 |
59 |
60 | org.eclipse.cdt.make.core.useDefaultBuildCmd
61 | true
62 |
63 |
64 |
65 |
66 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
67 | full,incremental,
68 |
69 |
70 |
71 |
72 |
73 | org.eclipse.cdt.core.cnature
74 | org.eclipse.cdt.core.ccnature
75 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
76 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
77 |
78 |
79 |
80 | 1331129850464
81 |
82 | 10
83 |
84 | org.eclipse.ui.ide.multiFilter
85 | 1.0-projectRelativePath-matches-false-false-dist
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.cdt.codan.core.prefs:
--------------------------------------------------------------------------------
1 | #Fri Aug 26 13:14:01 CDT 2011
2 | eclipse.preferences.version=1
3 | org.eclipse.cdt.codan.checkers.errnoreturn=Warning
4 | org.eclipse.cdt.codan.checkers.errnoreturn.params={implicit\=>false}
5 | org.eclipse.cdt.codan.checkers.errreturnvalue=Error
6 | org.eclipse.cdt.codan.checkers.errreturnvalue.params={}
7 | org.eclipse.cdt.codan.checkers.noreturn=Error
8 | org.eclipse.cdt.codan.checkers.noreturn.params={implicit\=>false}
9 | org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
10 | org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
11 | org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
12 | org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
13 | org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
14 | org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={}
15 | org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
16 | org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={}
17 | org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
18 | org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={no_break_comment\=>"no break",last_case_param\=>true,empty_case_param\=>false}
19 | org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
20 | org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={unknown\=>false,exceptions\=>()}
21 | org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
22 | org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
23 | org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
24 | org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
25 | org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
26 | org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
27 | org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
28 | org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
29 | org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
30 | org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
31 | org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
32 | org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
33 | org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
34 | org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
35 | org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
36 | org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
37 | org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
38 | org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
39 | org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
40 | org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={}
41 | org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
42 | org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
43 | org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
44 | org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
45 | org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
46 | org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
47 | org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
48 | org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={}
49 | org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
50 | org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={}
51 | org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
52 | org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={macro\=>true,exceptions\=>()}
53 | org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
54 | org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={paramNot\=>false}
55 | org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
56 | org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={else\=>false,afterelse\=>false}
57 | org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
58 | org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
59 | org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
60 | org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={}
61 | org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
62 | org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={}
63 | org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
64 | org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={exceptions\=>("@(\#)","$Id")}
65 | org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
66 | org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
67 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.cdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16
3 | org.eclipse.cdt.core.formatter.alignment_for_assignment=16
4 | org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80
5 | org.eclipse.cdt.core.formatter.alignment_for_binary_expression=16
6 | org.eclipse.cdt.core.formatter.alignment_for_compact_if=16
7 | org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=34
8 | org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain=18
9 | org.eclipse.cdt.core.formatter.alignment_for_constructor_initializer_list=0
10 | org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16
11 | org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48
12 | org.eclipse.cdt.core.formatter.alignment_for_expression_list=0
13 | org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16
14 | org.eclipse.cdt.core.formatter.alignment_for_member_access=0
15 | org.eclipse.cdt.core.formatter.alignment_for_overloaded_left_shift_chain=16
16 | org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=16
17 | org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
18 | org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=end_of_line
19 | org.eclipse.cdt.core.formatter.brace_position_for_block=end_of_line
20 | org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=end_of_line
21 | org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=end_of_line
22 | org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=end_of_line
23 | org.eclipse.cdt.core.formatter.brace_position_for_switch=end_of_line
24 | org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=end_of_line
25 | org.eclipse.cdt.core.formatter.comment.min_distance_between_code_and_line_comment=1
26 | org.eclipse.cdt.core.formatter.comment.never_indent_line_comments_on_first_column=true
27 | org.eclipse.cdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true
28 | org.eclipse.cdt.core.formatter.compact_else_if=true
29 | org.eclipse.cdt.core.formatter.continuation_indentation=2
30 | org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2
31 | org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false
32 | org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false
33 | org.eclipse.cdt.core.formatter.indent_access_specifier_extra_spaces=0
34 | org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true
35 | org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=false
36 | org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true
37 | org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=false
38 | org.eclipse.cdt.core.formatter.indent_empty_lines=false
39 | org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true
40 | org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true
41 | org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true
42 | org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=false
43 | org.eclipse.cdt.core.formatter.indentation.size=2
44 | org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
45 | org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=do not insert
46 | org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
47 | org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
48 | org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
49 | org.eclipse.cdt.core.formatter.insert_new_line_before_colon_in_constructor_initializer_list=do not insert
50 | org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
51 | org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=do not insert
52 | org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
53 | org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert
54 | org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert
55 | org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert
56 | org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert
57 | org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert
58 | org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert
59 | org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
60 | org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert
61 | org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert
62 | org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert
63 | org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
64 | org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
65 | org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert
66 | org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert
67 | org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
68 | org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert
69 | org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
70 | org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
71 | org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
72 | org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert
73 | org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert
74 | org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert
75 | org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert
76 | org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
77 | org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert
78 | org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
79 | org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
80 | org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification=do not insert
81 | org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
82 | org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
83 | org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
84 | org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
85 | org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
86 | org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
87 | org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
88 | org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert
89 | org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert
90 | org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert
91 | org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert
92 | org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert
93 | org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert
94 | org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert
95 | org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert
96 | org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert
97 | org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
98 | org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert
99 | org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
100 | org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
101 | org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification=do not insert
102 | org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
103 | org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
104 | org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
105 | org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
106 | org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
107 | org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
108 | org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
109 | org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=do not insert
110 | org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert
111 | org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert
112 | org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert
113 | org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
114 | org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
115 | org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert
116 | org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert
117 | org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
118 | org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert
119 | org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
120 | org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
121 | org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
122 | org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert
123 | org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert
124 | org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert
125 | org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert
126 | org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
127 | org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert
128 | org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
129 | org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert
130 | org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
131 | org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
132 | org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert
133 | org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
134 | org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification=insert
135 | org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert
136 | org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert
137 | org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
138 | org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
139 | org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
140 | org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
141 | org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert
142 | org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert
143 | org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert
144 | org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert
145 | org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert
146 | org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
147 | org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert
148 | org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
149 | org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert
150 | org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification=do not insert
151 | org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
152 | org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
153 | org.eclipse.cdt.core.formatter.join_wrapped_lines=true
154 | org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false
155 | org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false
156 | org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=false
157 | org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false
158 | org.eclipse.cdt.core.formatter.lineSplit=80
159 | org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1
160 | org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true
161 | org.eclipse.cdt.core.formatter.tabulation.char=space
162 | org.eclipse.cdt.core.formatter.tabulation.size=2
163 | org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false
164 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.cdt.ui.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | formatter_profile=_two spaces
3 | formatter_settings_version=1
4 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.ltk.core.refactoring.prefs:
--------------------------------------------------------------------------------
1 | #Wed Mar 07 08:16:33 CST 2012
2 | eclipse.preferences.version=1
3 | org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
4 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.9.1)
2 |
3 | project(Ccs VERSION 0.9.20 DESCRIPTION "CCS configuration library")
4 |
5 | option(COVERAGE "Build with code coverage enabled" OFF)
6 |
7 | message(STATUS "${PROJECT_NAME} ${PROJECT_VERSION}")
8 | message(STATUS "Coverage: ${COVERAGE}")
9 |
10 |
11 | set(CMAKE_CXX_STANDARD 14)
12 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
13 | set(CMAKE_CXX_EXTENSIONS OFF)
14 |
15 | # All the sanitizer flags in one place
16 | if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
17 | set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize=address")
18 | set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize=undefined")
19 | else ()
20 | set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -static-libasan")
21 | set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -static-libubsan")
22 | set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize=address")
23 | set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize=signed-integer-overflow")
24 | set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize=bounds-strict -fsanitize=undefined")
25 | endif ()
26 |
27 | # Common flags shared across all builds
28 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g")
29 | if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
30 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-mismatched-tags")
31 | endif()
32 |
33 | # Debug flags
34 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${SANITIZE_FLAGS}")
35 |
36 | include(CTest)
37 | include(GNUInstallDirs)
38 |
39 | # Enable libtooling support
40 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
41 |
42 | # External libraries/dependencies
43 | add_subdirectory(external/googletest EXCLUDE_FROM_ALL)
44 |
45 | include_directories(api src)
46 | link_directories(${PROJECT_BINARY_DIR}/lib)
47 |
48 | add_subdirectory(src)
49 | enable_testing()
50 | add_subdirectory(test)
51 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2011, 2018 Matt Hellige
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/hellige/ccs-cpp/actions?workflow=CI)
2 | [](https://codecov.io/gh/hellige/ccs-cpp)
3 | [](https://github.com/hellige/ccs-cpp/releases)
4 | [](https://github.com/hellige/ccs-cpp/blob/master/LICENSE)
5 |
6 |
7 | CCS for C++
8 | ===========
9 |
10 | This is the C++ implementation of [CCS][1].
11 |
12 | CCS is a language for config files, and libraries to read those files and
13 | configure applications. The documentation is currently quite poor, but the
14 | [Java][1] and C++ implementations are mature and have been used in production
15 | for many years.
16 |
17 | There's a presentation about the language [here][2], but it's a little sketchy
18 | without someone talking along with it.
19 |
20 | [1]: http://github.com/hellige/ccs
21 | [2]: http://hellige.github.io/ccs
22 |
23 |
24 | Building
25 | --------
26 |
27 | CCS is built with CMake. You can set the usual options to control your
28 | compiler, build type, etc., but the crash course is:
29 |
30 | $ git submodule update --init
31 | $ mkdir build
32 | $ cd build
33 | $ cmake ..
34 | $ make
35 |
36 | You can run unit tests with pretty output using:
37 |
38 | $ make unittest
39 |
40 | CMake can install everything for you, but in any case the client-facing
41 | headers are in the `api` directory.
42 |
43 |
44 | Syntax quick reference
45 | ----------------------
46 |
47 | #### @context (a.b c, d)
48 |
49 | Sets "context" for the rest of the ruleset. Must appear prior to any other
50 | rules. Equivalent to:
51 |
52 | a.b c, d { /* rest of file */ }
53 |
54 | #### name = 123
55 |
56 | Property definition. Property _name_ will have the specified value in the
57 | current context. The syntax of values is conventional: _true_, _false_,
58 | 64-bit signed integers (may be specified in hex as _0x1a2bc_), doubles,
59 | and strings.
60 |
61 | #### 'name with spaces' = 'value'
62 |
63 | _name_ may be enclosed in quotes and written as a string literal if it
64 | contains spaces or other non-identifier characters.
65 |
66 | #### @override name = 123
67 |
68 | Overriding property definition. For a given property, any definition marked
69 | _@override_ will take precedence over any normal definition, regardless of
70 | the relative specificities of the two definitions. If more than one
71 | _@override_ definition applies in a particular context, the most specific wins.
72 |
73 | #### 'VAR: ${VAR}'
"literal: \${VAR}"
74 |
75 | Strings may be enclosed in single or double quotes. Environment variables may
76 | be interpolated with ```${VAR}```. Special characters may be escaped with a
77 | backslash. Recognized escape sequences include: ```\t \n \r \' \" \\ \$```.
78 | A string may be broken across multiple lines by ending a line with a single
79 | backslash.
80 |
81 | #### 'double: ", single: \''
"double: \", single: '"
82 |
83 | The non-delimiting quote character need not be escaped.
84 |
85 | #### @import "..."
a b.c d : @import "..."
86 |
87 | Import a ruleset into the current ruleset. The entire imported ruleset will be
88 | nested in the current context, so for example the second example above further
89 | constrains all imported settings to the context ```a b.c d```.
90 |
91 | #### @constrain a/b.c/d.e.f
92 |
93 | Further constrain the context. This is equivalent to further constraining the
94 | context using the ```context.constrain(...)``` API call.
95 |
96 | Of course, this is most useful when applied only in a particular selected
97 | context, in which case it allows for some additional reuse and
98 | modularity within CCS rulesets (activating additional sets of rules in
99 | particular cases, for example).
100 |
101 | #### _selector_ : @import "..."
_selector_ : @constrain _..._
_selector_ : _name_ = _value_
_selector_ { _rules_ }
102 |
103 | Constrain rules to apply only in the selected context. _rule_ is any of:
104 | an import, a property setting, a constraint, or a selector and further nested
105 | rules. Selector syntax is documented below...
106 |
107 | #### a.b.c
108 |
109 | Matches a constraint of type ```a``` with values ```b``` and ```c```. Note
110 | that this matches only a single constraint with _both_ values. Multiple
111 | constraints of the same type are allowed (thus preserving monotonicity), so
112 | ```a.b.c``` is not equivalent to ```a.b a.c``` in every case.
113 |
114 | ### a/c
115 |
116 | _Rarely needed._
117 |
118 | Matches a simultaneous occurence of constraints of type ```a``` and type
119 | ```c```. Again, this is not generally equivalent to ```a c```, as it only
120 | matches when the two constraints are applied in the same single step.
121 |
122 | #### a.b c.d
a.b, c.d
a.b > c.d
123 |
124 | Conjunction, disjunction, and descendant selection, respectively. The first
125 | form matches in any context containing _both_ ```a.b``` and ```c.d```.
126 | The second matches in any context containing _either one_.
127 |
128 | The third form matches in any context containing ```c.d```, _itself_ in a
129 | context containing ```a.b```. This form is infrequently used in CCS (although it
130 | is of course the default operator in CSS).
131 |
132 | Precedence of operators is as follows, from highest to lowest:
133 |
134 | - ```>``` (descendant)
135 | - juxtaposition (conjunction)
136 | - ```,``` (disjunction)
137 |
138 | Parentheses may be used to enforce grouping. So, for example, ```a, c > d e```
139 | is equivalent to ```a, ((c > d) e)```. Since ```>``` is infrequently used,
140 | the rules are generally simple and intuitive.
141 |
142 |
143 | Note that rules may be separated by semicolons for clarity, but this is always
144 | completely optional and will never affect the way the ruleset is parsed.
145 |
146 |
147 | TODO
148 | ----
149 |
150 | * Aggregate values: lists, maps.
151 | * For aggregate values, allow modification of inherited value as well as
152 | replacement??
153 |
--------------------------------------------------------------------------------
/api/ccs/ccs.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /* Single all-in header, includes the entire CCS API. */
4 |
5 | #include "ccs/context.h"
6 | #include "ccs/domain.h"
7 | #include "ccs/types.h"
8 |
--------------------------------------------------------------------------------
/api/ccs/context.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include "ccs/types.h"
11 |
12 | namespace ccs {
13 |
14 | class CcsTracer;
15 | class CcsProperty;
16 | class Key;
17 | class Node;
18 | class SearchState;
19 |
20 | class CcsContext {
21 | std::shared_ptr searchState;
22 |
23 | friend class CcsDomain;
24 | CcsContext(std::shared_ptr root);
25 | CcsContext(const CcsContext &parent, const Key &key);
26 | CcsContext(const CcsContext &parent, const std::string &name);
27 | CcsContext(const CcsContext &parent, const std::string &name,
28 | const std::vector &values);
29 |
30 | public:
31 | CcsContext(const CcsContext &) = default;
32 | CcsContext &operator=(const CcsContext &) = default;
33 | ~CcsContext() = default;
34 |
35 | class Builder;
36 |
37 | void logRuleDag(std::ostream &os) const;
38 |
39 | Builder builder() const;
40 |
41 | CcsContext constrain(const std::string &name) const
42 | { return CcsContext(*this, name); }
43 |
44 | CcsContext constrain(const std::string &name,
45 | const std::vector &values) const
46 | { return CcsContext(*this, name, values); }
47 |
48 | const CcsProperty &getProperty(const std::string &propertyName) const;
49 |
50 | const std::string &getString(const std::string &propertyName) const;
51 | const std::string &getString(const std::string &propertyName,
52 | const std::string &defaultVal) const;
53 | bool getInto(std::string &dest, const std::string &propertyName) const;
54 |
55 | int getInt(const std::string &propertyName) const;
56 | int getInt(const std::string &propertyName, int defaultVal) const;
57 | bool getInto(int &dest, const std::string &propertyName) const;
58 |
59 | double getDouble(const std::string &propertyName) const;
60 | double getDouble(const std::string &propertyName, double defaultVal) const;
61 | bool getInto(double &dest, const std::string &propertyName) const;
62 |
63 | bool getBool(const std::string &propertyName) const;
64 | bool getBool(const std::string &propertyName, bool defaultVal) const;
65 | bool getInto(bool &dest, const std::string &propertyName) const;
66 |
67 | // these depend on operator>> for T
68 | template
69 | T get(const std::string &propertyName) const;
70 | template
71 | T get(const std::string &propertyName, const T &defaultVal) const;
72 | template
73 | bool getInto(T &dest, const std::string &propertyName) const;
74 |
75 | friend std::ostream &operator<<(std::ostream &, const CcsContext);
76 |
77 | template
78 | static bool coerceString(const std::string &s, T &dest);
79 |
80 | private:
81 | static bool checkEmpty(std::istream &stream);
82 | };
83 |
84 |
85 | struct no_such_property : public virtual std::exception {
86 | std::string msg;
87 | CcsContext context;
88 | no_such_property(const std::string &name, CcsContext context);
89 | virtual ~no_such_property() throw() {}
90 | virtual const char *what() const throw()
91 | { return msg.c_str(); }
92 | };
93 |
94 | struct bad_coercion : public virtual std::exception {
95 | std::string msg;
96 | bad_coercion(const std::string &name, const std::string &value) :
97 | msg(std::string("property cannot be coerced to requested type: ") + name
98 | + " with value " + value) {}
99 | virtual ~bad_coercion() throw() {}
100 | virtual const char *what() const throw()
101 | { return msg.c_str(); }
102 | };
103 |
104 |
105 | template
106 | bool CcsContext::coerceString(const std::string &s, T &dest) {
107 | std::istringstream ist(s);
108 | ist >> dest;
109 | return checkEmpty(ist);
110 | }
111 |
112 | template<>
113 | inline bool CcsContext::coerceString(const std::string &s,
114 | std::string &dest) {
115 | dest = s;
116 | return true;
117 | }
118 |
119 | template<>
120 | inline bool CcsContext::coerceString(const std::string &s,
121 | bool &dest) {
122 | // convert from a string to a bool: value must be exactly "true" or "false",
123 | // for maximum consistency with ccs boolean literals.
124 | if (s == std::string("true")) {
125 | dest = true;
126 | return true;
127 | }
128 | if (s == std::string("false")) {
129 | dest = false;
130 | return true;
131 | }
132 | return false;
133 | }
134 |
135 | template
136 | T CcsContext::get(const std::string &propertyName) const {
137 | auto &val = getString(propertyName);
138 | T t;
139 | if (!coerceString(val, t)) throw bad_coercion(propertyName, val);
140 | return t;
141 | }
142 |
143 | template
144 | T CcsContext::get(const std::string &propertyName, const T &defaultVal) const {
145 | std::string str;
146 | if (!getInto(str, propertyName)) return defaultVal;
147 | T t;
148 | if (!coerceString(str, t)) return defaultVal;
149 | return t;
150 | }
151 |
152 | template
153 | bool CcsContext::getInto(T &dest, const std::string &propertyName) const {
154 | std::string str;
155 | if (!getInto(str, propertyName)) return false;
156 | return coerceString(str, dest);
157 | }
158 |
159 |
160 | class CcsContext::Builder {
161 | class Impl;
162 | std::unique_ptr impl;
163 |
164 | public:
165 | explicit Builder(const CcsContext &context);
166 | Builder(const Builder &);
167 | Builder &operator=(const Builder &);
168 | ~Builder();
169 |
170 | CcsContext build() const;
171 |
172 | Builder &add(const std::string &name)
173 | { return add(name, {}); }
174 | Builder &add(const std::string &name,
175 | const std::vector &values);
176 | };
177 |
178 | }
179 |
--------------------------------------------------------------------------------
/api/ccs/domain.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "ccs/context.h"
9 | #include "ccs/rule_builder.h"
10 |
11 | namespace ccs {
12 |
13 | class DagBuilder;
14 |
15 | class CcsLogger {
16 | public:
17 | virtual ~CcsLogger() {}
18 | virtual void info(const std::string &msg) = 0;
19 | virtual void warn(const std::string &msg) = 0;
20 | virtual void error(const std::string &msg) = 0;
21 |
22 | static std::shared_ptr makeStdErrLogger();
23 | };
24 |
25 | class CcsTracer {
26 | public:
27 | virtual ~CcsTracer() {}
28 | virtual void onPropertyFound(
29 | const CcsContext &ccsContext,
30 | const std::string &propertyName,
31 | const CcsProperty &prop) = 0;
32 | virtual void onPropertyNotFound(
33 | const CcsContext &ccsContext,
34 | const std::string &propertyName) = 0;
35 | virtual void onConflict(
36 | const CcsContext &ccsContext,
37 | const std::string &propertyName,
38 | const std::vector values) = 0;
39 | virtual void onParseError(const std::string &msg) = 0;
40 |
41 | static std::shared_ptr makeLoggingTracer(
42 | std::shared_ptr logger, bool logAccesses = false);
43 | };
44 |
45 | class ImportResolver {
46 | public:
47 | static ImportResolver &None;
48 | virtual ~ImportResolver() {}
49 | virtual bool resolve(const std::string &location,
50 | std::function load) = 0;
51 | };
52 |
53 | class CcsDomain {
54 | std::unique_ptr dag;
55 |
56 | public:
57 | explicit CcsDomain(bool logAccesses = false);
58 | explicit CcsDomain(std::shared_ptr log, bool logAccesses = false);
59 | explicit CcsDomain(std::shared_ptr tracer);
60 | ~CcsDomain();
61 | CcsDomain(const CcsDomain &) = delete;
62 | CcsDomain &operator=(const CcsDomain &) = delete;
63 |
64 | CcsDomain &loadCcsStream(std::istream &stream, const std::string &fileName,
65 | ImportResolver &importResolver);
66 | RuleBuilder ruleBuilder();
67 |
68 | void logRuleDag(std::ostream &os) const;
69 |
70 | CcsContext build();
71 | };
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/api/ccs/rule_builder.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | namespace ccs {
8 |
9 | class DagBuilder;
10 |
11 | class RuleBuilder {
12 | friend class CcsDomain;
13 | class Impl;
14 | class Root;
15 | class Child;
16 | std::shared_ptr impl;
17 |
18 | RuleBuilder(DagBuilder &dag);
19 | RuleBuilder(const std::shared_ptr &impl) : impl(impl) {}
20 |
21 | public:
22 | RuleBuilder pop();
23 | RuleBuilder set(const std::string &name, const std::string &value);
24 |
25 | RuleBuilder select(const std::string &name);
26 | RuleBuilder select(const std::string &name,
27 | const std::vector &values);
28 | };
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/api/ccs/types.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace ccs {
7 |
8 | struct Origin {
9 | std::string fileName;
10 | unsigned line;
11 |
12 | Origin() : fileName(""), line(0) {}
13 | Origin(const std::string &fileName, unsigned line) :
14 | fileName(fileName), line(line) {}
15 | };
16 |
17 | static inline std::ostream &operator<<(std::ostream &str, const Origin &origin) {
18 | str << origin.fileName << ':' << origin.line;
19 | return str;
20 | }
21 |
22 | struct CcsProperty {
23 | virtual ~CcsProperty() {}
24 | virtual bool exists() const = 0;
25 | virtual Origin origin() const = 0;
26 | virtual const std::string &strValue() const = 0;
27 | virtual int intValue() const = 0;
28 | virtual double doubleValue() const = 0;
29 | virtual bool boolValue() const = 0;
30 | };
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/misc/CCS.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/misc/README.md:
--------------------------------------------------------------------------------
1 | ## Misc files
2 |
3 | Syntax highlighting for vim is in `ccs.vim`.
4 | Syntax highlighting for JetBrains products (e.g. CLion) is in CCS.xml - copy to the `filetypes` subdirectory of your
5 | `~/.CLion/config`.
6 |
--------------------------------------------------------------------------------
/misc/ccs.vim:
--------------------------------------------------------------------------------
1 | " Vim syntax file
2 | " Language: CCS
3 | " Maintainer: Matt Hellige , Matt Godbolt
4 | " Last change: 2015 February 9th
5 |
6 | if exists("b:current_syntax")
7 | finish
8 | endif
9 |
10 | syn clear
11 | syn case match
12 |
13 | syn match ccsError '@\w*'
14 | syn match ccsKeywords '@import\>' skipwhite nextgroup=ccsString
15 | syn match ccsKeywords '@constrain\>' skipwhite
16 | syn match ccsKeywords '@context\>' skipwhite nextgroup=ccsParens
17 | syn match ccsModifiers '@override\>' skipwhite
18 | " needs to be high up as it is spectacularly oversensitive
19 | syn match ccsConstraint '\<\w\+\>'
20 |
21 | syn region ccsBlock start="{" end="}" fold transparent
22 | syn match ccsComment "//.*$"
23 | syn region ccsComment start="/\*" end="\*/" contains=ccsComment
24 | syn region ccsParens start="(" end=")" transparent
25 |
26 | syn region ccsString start='"' end='"' contained contains=ccsInterpolant,ccsEscape
27 | syn region ccsString start='\'' end='\'' contained contains=ccsInterpolant,ccsEscape
28 | syn region ccsInterpolant start='${' end='}' contained
29 | syn match ccsEscape '\\[tnr'"\$]' contained
30 |
31 | syn region ccsConstraintString start='"' end='"'
32 | syn region ccsConstraintString start='\'' end='\''
33 |
34 | " Integer with - + or nothing in front
35 | syn match ccsNumber '\d\+' contained
36 | syn match ccsNumber '[-+]\d\+' contained
37 |
38 | " Floating point number with decimal no E or e (+,-)
39 | syn match ccsNumber '\d\+\.\d*' contained
40 | syn match ccsNumber '[-+]\d\+\.\d*' contained
41 |
42 | " Floating point like number with E and no decimal point (+,-)
43 | syn match ccsNumber '[-+]\=\d[[:digit:]]*[eE][\-+]\=\d\+' contained
44 | syn match ccsNumber '\d[[:digit:]]*[eE][\-+]\=\d\+' contained
45 |
46 | " Floating point like number with E and decimal point (+,-)
47 | syn match ccsNumber '[-+]\=\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+' contained
48 | syn match ccsNumber '\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+' contained
49 |
50 | syn keyword ccsBoolean true false skipwhite contained
51 |
52 | syn match ccsIdentifier '\<\w\+\>\(\s*=\)\@='
53 | syn match ccsDefId '\<\w\+\>' contained
54 |
55 | syn match ccsOperator '[.,>:|{}*()]'
56 |
57 | syn match ccsOperator '=' skipwhite nextgroup=ccsNumber,ccsBoolean,ccsString,ccsDefId
58 |
59 | let b:current_syntax = "ccs"
60 | hi def link ccsError Error
61 | hi def link ccsKeywords Statement
62 | hi def link ccsModifiers Type
63 | hi def link ccsConstraint Type
64 | hi def link ccsConstraintString Type
65 | hi def link ccsComment Comment
66 | hi def link ccsString Constant
67 | hi def link ccsNumber Constant
68 | hi def link ccsBoolean Constant
69 | hi def link ccsDefId Constant
70 | hi def link ccsIdentifier Identifier
71 | hi def link ccsOperator Operator
72 | hi def link ccsInterpolant PreProc
73 |
--------------------------------------------------------------------------------
/misc/grammar.txt:
--------------------------------------------------------------------------------
1 | terminals are in CAPS or 'single-quotes' below.
2 |
3 | ruleset ::= ('@context' '(' selector ')') ';'?)? rules
4 | | rules
5 | rules ::= rule rules
6 |
7 | // when parsing rule, the ambiguity is between ident as start of prule and
8 | // ident as start of selector... '=' can be used to disambiguate.
9 | rule ::= prule ';'?
10 | | selector ':' prule ';'?
11 | | selector '{' rules '}'
12 | prule ::= '@import' STRING
13 | | '@constrain' singlestep
14 | | '@override'? ident '=' val
15 |
16 | // stratified precedence...
17 | selector ::= sum '>'?
18 | sum ::= product (',' product)*
19 | // term* starts with ident or '(', which is enough to disambiguate...
20 | product ::= term term*
21 | // here we have to distinguish another step from a trailing '>'. again,
22 | // peeking for ident or '(' does the trick.
23 | term ::= step ('>' step)*
24 | step ::= singlestep
25 | | '(' sum ')'
26 | singlestep ::= ident ('.' ident)* ('/' singlestep)?
27 |
28 | ident ::= ID | STRING
29 | val ::= INT | DOUBLE | BOOL | STRING
30 |
31 |
32 | // without precedence...
33 | selector ::= step '>'?
34 | step ::= step op step
35 | | singlestep step
36 | | singlestep
37 | | '(' step ')'
38 | op ::= ',' | '>'
39 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | option(LTO "Use link-time optimization" OFF)
2 |
3 | if (LTO)
4 | message("Enabling link-time optimization")
5 | include(CheckIPOSupported)
6 | check_ipo_supported()
7 | set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
8 | endif ()
9 |
10 | if (COVERAGE)
11 | add_compile_options(--coverage -O0)
12 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
13 | endif ()
14 |
15 | set(CCS_SOURCE_FILES
16 | context.cpp
17 | dag/key.cpp
18 | dag/property.cpp
19 | dag/tally.cpp
20 | domain.cpp
21 | graphviz.cpp
22 | parser/ast.cpp
23 | parser/build_context.cpp
24 | parser/parser.cpp
25 | rule_builder.cpp
26 | search_state.cpp)
27 |
28 | add_library(ccs_obj OBJECT ${CCS_SOURCE_FILES})
29 | target_include_directories(ccs_obj PRIVATE .)
30 | target_include_directories(ccs_obj PUBLIC
31 | $
32 | $
33 | )
34 | set_property(TARGET ccs_obj PROPERTY POSITION_INDEPENDENT_CODE TRUE)
35 |
36 | add_library(ccs STATIC $)
37 | add_library(Ccs::ccs ALIAS ccs)
38 | target_include_directories(ccs PUBLIC
39 | $
40 | $
41 | )
42 |
43 | add_library(ccs_so SHARED $)
44 | add_library(Ccs::ccs_so ALIAS ccs_so)
45 | target_include_directories(ccs_so PUBLIC
46 | $
47 | $
48 | )
49 | set_target_properties(ccs_so PROPERTIES OUTPUT_NAME ccs VERSION ${PROJECT_VERSION})
50 |
51 | install(TARGETS ccs ccs_so EXPORT ${PROJECT_NAME}Config
52 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
53 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
54 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
55 | )
56 |
57 | install(DIRECTORY ../api/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
58 |
59 | include(CMakePackageConfigHelpers)
60 | write_basic_package_version_file(
61 | ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
62 | VERSION ${PROJECT_VERSION}
63 | COMPATIBILITY SameMajorVersion
64 | )
65 |
66 | install(FILES
67 | ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
68 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/
69 | )
70 |
71 | export(
72 | TARGETS ccs ccs_so
73 | NAMESPACE ${PROJECT_NAME}::
74 | FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
75 | )
76 |
77 | install(
78 | EXPORT ${PROJECT_NAME}Config
79 | FILE ${PROJECT_NAME}Config.cmake
80 | NAMESPACE ${PROJECT_NAME}::
81 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/
82 | )
83 |
--------------------------------------------------------------------------------
/src/context.cpp:
--------------------------------------------------------------------------------
1 | #include "ccs/context.h"
2 |
3 | #include