ogma-cli-1.10.0/0000755000000000000000000000000015064246146011457 5ustar0000000000000000ogma-cli-1.10.0/ogma-cli.cabal0000644000000000000000000001562415064246146014143 0ustar0000000000000000-- Copyright 2020 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. cabal-version: 2.0 build-type: Simple name: ogma-cli version: 1.10.0 homepage: https://github.com/nasa/ogma bug-reports: https://github.com/nasa/ogma/issues license: Apache-2.0 license-file: LICENSE author: Ivan Perez, Alwyn Goodloe maintainer: ivan.perezdominguez@nasa.gov category: Aerospace extra-source-files: CHANGELOG.md synopsis: Ogma: Helper tool to interoperate between Copilot and other languages. description: Ogma is a tool to facilitate the integration of safe runtime monitors into other systems. Ogma extends , a high-level runtime verification framework that generates hard real-time C99 code. . Some use cases supported by Ogma include: . - Translating requirements defined in structured natural language into monitors in Copilot. . - Generating the glue code necessary to work with C structs in Copilot. . - Generating applications that use Copilot for monitoring data received from the message bus. . - Generating message handlers for NASA Core Flight System applications to make external data in structs available to a Copilot monitor. . - Generating applications that use Copilot for monitoring data received from different topics. . - Generating components that use Copilot for monitoring. . - Generating monitors from state diagrams specified using a graphical notation. . The main invocation with @--help@ lists sub-commands available. . >$ ogma --help >ogma - an anything-to-Copilot application generator > >Usage: ogma COMMAND > Generate complete or partial Copilot applications from multiple languages > >Available options: > -h,--help Show this help text > >Available commands: > overview Generate an overview of the input specification(s) > structs Generate Copilot structs from C structs > handlers Generate message handlers from C structs > cfs Generate a complete CFS/Copilot application > fprime Generate a complete F' monitoring component > ros Generate a ROS 2 monitoring application > standalone Generate a Copilot file from an input specification > diagram Generate a monitor from a state machine diagram . For further information, see: . - . . - . . - . . - . . - . . - "", Perez, Dedden and Goodloe. 2020. . - "", Dutle et al. 2020. extra-source-files: tests/fcs-example1.json tests/fdb-example1.json tests/reduced_geofence_msgs.h tests/reduced_geofence_msgs_bad.h -- Ogma packages should be uncurated so that only the official maintainers make -- changes. -- -- Because this is a NASA project, we want to make sure that users obtain -- exactly what we publish, unmodified by anyone external to our project. x-curation: uncurated source-repository head type: git location: git@github.com:nasa/ogma.git subdir: ogma-cli executable ogma main-is: Main.hs other-modules: CLI.CommandCFSApp CLI.CommandCStructs2Copilot CLI.CommandCStructs2MsgHandlers CLI.CommandDiagram CLI.CommandFPrimeApp CLI.CommandOverview CLI.CommandROSApp CLI.CommandStandalone CLI.CommandTop CLI.Result build-depends: base >= 4.11.0.0 && < 5 , aeson >= 2.0.0.0 && < 2.3 , optparse-applicative >= 0.14 && < 0.20 , microstache >= 1.0 && < 1.1 , text >= 1.2.3.1 && < 2.2 , ogma-core >= 1.10.0 && < 1.11 hs-source-dirs: src default-language: Haskell2010 ghc-options: -Wall test-suite test-ogma type: exitcode-stdio-1.0 main-is: Main.hs build-depends: base >= 4.11.0.0 && < 5 , HUnit >= 1.2.0.0 && < 1.7 , process >= 1.6 && < 1.7 , test-framework >= 0.8.2 && < 0.9 , test-framework-hunit >= 0.2.0 && < 0.4 , unix >= 2.7.2.2 && < 2.9 hs-source-dirs: tests default-language: Haskell2010 ghc-options: -Wall ogma-cli-1.10.0/LICENSE0000644000000000000000000002613715064246146012475 0ustar0000000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ogma-cli-1.10.0/CHANGELOG.md0000644000000000000000000001126415064246146013274 0ustar0000000000000000# Revision history for ogma-cli ## [1.10.0] - 2025-09-21 * Version bump 1.10.0 (#310). * Add example demonstrating the basics of ROS 2 backend (#289). * Add example demonstrating the basics of cFS backend (#305). * Add CI job to test cFS backend (#307). * Replace NOSA license with Apache license (#293). ## [1.9.0] - 2025-08-06 * Version bump 1.9.0 (#284). * Extend ROS command with flags to control testing package (#280). * Bump upper version constraint on optparse-applicative (#279). ## [1.8.0] - 2025-07-13 * Version bump 1.8.0 (#275). * Expose overview command (#272). * Extend code commands to accept expressions to monitor as CLI arguments (#121). ## [1.7.0] - 2025-03-21 * Version bump 1.7.0 (#269). * Add all auxiliary test files to distributable Cabal package (#216). * Remove extraneous EOL character (#224). * Update installation instructions to use cabal install (#149). * Update README with new cFS template variables (#229). * Expose handlers-file argument to cFS backend (#234). * Expose template-vars argument to cFS backend (#106). * Document new template variables in README (#237). * Fix formatting of template variables in README (#222). * Update README with new ROS template variables (#244). * Update README with new FPrime template variables (#246). * Adjust CLI to match new backend API (#248). * Expose template-vars argument to ROS, FPrime, standalone backends (#250). * Expose spec processing arguments to cFS backend in CLI (#252). * Use new sample spec with ROS backend in CI job (#107). * Update examples, Github Actions, README to use new variable DB format (#256). * Update README, ROS example with ability to pass data to handlers (#219). * Update README, Github Actions with new dependencies (#263). * Update to support boolean expressions in the Lustre language (#267). ## [1.6.0] - 2025-01-21 * Version bump 1.6.0 (#208). * Update contribution guidelines (#161). * Provide ability to customize template in fprime command (#185). * Provide ability to customize template in standalone command (#189). * Add repository information to cabal package (#148). * Add version bounds to all dependencies (#119). * Introduce new diagram command (#194). * Provide ability to preprocess properties via external command (#197). * Extend support for file, property formats across backends (#204). ## [1.5.0] - 2024-11-21 * Version bump 1.5.0 (#178). * Provide ability to customize template in cfs command (#157). * Provide ability to customize template in ros command (#162). * Introduce new standalone command (#170). * Update README to demonstrate robotics (#172). * Remove unused resources (#174). * Add version bounds to base (#180). ## [1.4.1] - 2024-09-21 * Version bump 1.4.1 (#155). * Constrain version of dependency in CI jobs (#151). * Replace homepage (#147). ## [1.4.0] - 2024-05-21 * Version bump 1.4.0 (#145). * Introduce CI test job (#139). * Introduce test job for ROS package generation (#136). * Add a float and a double input variable to ROS example (#138). * Document format of variable DB (#143). ## [1.3.0] - 2024-03-21 * Version bump 1.3.0 (#133). ## [1.2.0] - 2024-01-21 * Version bump 1.2.0 (#117). * Re-structure README around on backends (#75). ## [1.1.0] - 2023-11-21 * Version bump 1.1.0 (#112). * Document cabal update step in README (#100). ## [1.0.11] - 2023-09-21 * Version bump 1.0.11 (#103). ## [1.0.10] - 2023-07-21 * Version bump 1.0.10 (#98). * Correct test case (#96). ## [1.0.9] - 2023-05-21 * Version bump 1.0.9 (#93). * Rename ROS2 to ROS 2 (#83). * Allow customizing the names of the C files generated by Copilot (#80). * Re-order README's TOC to match order of contents (#88). * Fix rendering of quotes in URLs in package description (#72). * List FPrime backend as supported use case in package description (#91). ## [1.0.8] - 2023-03-21 * Version bump 1.0.8 (#81). * Introduce new F' (FPrime) backend (#77). * Mark package as uncurated (#74). ## [1.0.7] - 2023-01-21 * Version bump 1.0.7 (#69). * Replace tabs in cabal file (#69). * Introduce new ROS2 backend (#56). ## [1.0.6] - 2022-11-21 * Version bump 1.0.6 (#64). * Update license in cabal file to OtherLicense (#62). * Add empty file to keep directory structure in distributable package (#65). ## [1.0.5] - 2022-09-21 * Version bump 1.0.5 (#60). * Update README to reflect that GHC 9.2 is supported (#55). ## [1.0.4] - 2022-07-21 * Version bump 1.0.4 (#53). * Address all hlint suggestions (#51). ## [1.0.3] - 2022-05-21 * Version bump 1.0.3 (#49). * Enable CI (#47). * Conformance with style guide (partial) (#45). ## [1.0.2] - 2022-03-21 * Version bump 1.0.2 (#43). * Address HLint warning (#41). ## [1.0.1] - 2022-01-21 * Version bump 1.0.1 (#39). * Merge imports (#33). ## [1.0.0] - 2021-11-22 * Initial release. ogma-cli-1.10.0/Setup.hs0000644000000000000000000000005615064246146013114 0ustar0000000000000000import Distribution.Simple main = defaultMain ogma-cli-1.10.0/tests/0000755000000000000000000000000015064246146012621 5ustar0000000000000000ogma-cli-1.10.0/tests/Main.hs0000644000000000000000000001612415064246146014045 0ustar0000000000000000-- | Test Ogma module Main where import Data.List ( intercalate ) import Data.Monoid ( mempty ) import System.Exit ( ExitCode (ExitSuccess) ) import System.Process ( readProcessWithExitCode ) import Test.Framework ( Test, defaultMainWithOpts ) import Test.Framework.Providers.HUnit ( testCase ) import Test.HUnit ( assertBool ) -- | Run all unit tests on Ogma. main :: IO () main = defaultMainWithOpts tests mempty -- | All unit tests for Ogma tests :: [Test.Framework.Test] tests = [ testCase "cli-main-ok" (runErrorCode ["--help" ] True) -- Should pass , testCase "cli-main-fail" (runErrorCode ["hfdsafdkajdfaskl"] False) -- Should fail due to arguments being incorrect , testCase "cli-cmd-structs" (runErrorCode ["structs", "--help" ] True) -- Should pass , testCase "cli-cmd-structs-fail" (runErrorCode ["structs", "--incorrect-argument"] False) -- Should fail due to arguments being incorrect , testCase "cli-cmd-handlers" (runErrorCode ["handlers", "--help" ] True) -- Should pass , testCase "cli-cmd-handlers-fail" (runErrorCode ["handlers", "--incorrect-argument"] False) -- Should fail due to arguments being incorrect , testCase "cli-cmd-cfs" (runErrorCode ["cfs", "--help" ] True) -- Should pass , testCase "cli-cmd-cfs-fail" (runErrorCode ["cfs", "--incorrect-argument"] False) -- Should fail due to arguments being incorrect , testCase "cli-cmd-standalone" (runErrorCode ["standalone", "--help" ] True) -- Should pass , testCase "cli-cmd-standalone-fail" (runErrorCode ["standalone", "--incorrect-argument"] False) -- Should fail due to arguments being incorrect , testCase "cli-cmd-standalone-fcs" (parseStandaloneFCS "tests/fcs-example1.json" True) -- Should pass , testCase "cli-cmd-standalone-file-not-found" (parseStandaloneFCS "tests/file-invalid.json" False) -- Should fail because the file does not exist , testCase "cli-cmd-standalone-parse-fail-1" (parseStandaloneFCS "tests/commands-fcs-error-parsing-failed-1.json" False) -- Should fail because the opening bracket is [ and not { , testCase "cli-cmd-standalone-parse-fail-2" (parseStandaloneFCS "tests/commands-fcs-error-parsing-failed-2.json" False) -- Should fail because a field is missing in an external variable , testCase "cli-cmd-standalone-parse-fail-3" (parseStandaloneFCS "tests/commands-fcs-error-parsing-failed-3.json" False) -- Should fail because a field is missing in an internal variable , testCase "cli-cmd-standalone-fdb" (parseStandaloneFDB "tests/fdb-example1.json") -- Should pass , testCase "structs-parse-ok" (testCStructs2Copilot "tests/reduced_geofence_msgs.h" True) -- Should pass , testCase "structs-parse-fail-1" (testCStructs2Copilot "tests/reduced_geofence_msgs_bad.h" False) -- Should fail because a keyword is incorrect ] -- | Test C struct parser for a particular file. -- -- This test uses the Copilot backend for C header files, so it generates -- Copilot types and instances. It may be convenient to run this action in a -- temporary directory. -- -- This IO action fails if any of the following are true: -- * Ogma cannot be found in the current PATH. -- * Ogma cannot be executed. -- * The given file is not found or accessible. -- * The format in the given file is incorrect. -- * Ogma fails due to an internal error or bug. -- * The output file cannot be created due to lack of space or permissions. -- testCStructs2Copilot :: FilePath -- ^ Path to a C header file with structs -> Bool -> IO () testCStructs2Copilot file success = do (ec, _out, _err) <- readProcessWithExitCode "ogma" args "" -- True if success is expected and detected, or niether expected nor -- detected. let testPass = success == (ec == ExitSuccess) assertBool errorMsg testPass where args = ["structs", "--header-file-name", file] errorMsg = "Result of processing file " ++ file ++ " failed" -- | Test standalone backend for a FCS format and SVM. -- -- This test uses the standalone backend, so it generates a Copilot file. It -- may be convenient to run this action in a temporary directory. -- -- This IO action fails if any of the following are true: -- * Ogma cannot be found in the current PATH. -- * Ogma cannot be executed. -- * The given file is not found or accessible. -- * The format in the given file is incorrect. -- * Ogma fails due to an internal error or bug. -- * The output file cannot be created due to lack of space or permissions. -- parseStandaloneFCS :: FilePath -- ^ Path to an input file -> Bool -> IO () parseStandaloneFCS file success = do (ec, _out, _err) <- readProcessWithExitCode "ogma" args "" -- True if success is expected and detected, or niether expected nor -- detected. let testPass = success == (ec == ExitSuccess) assertBool errorMsg testPass where args = ["standalone", "--file-name", file] errorMsg = "Parsing file " ++ file ++ " result unexpected." -- | Test standalone backend for FDB format and Lustre. -- -- This test uses the standalone backend, so it generates a Copilot file. It -- may be convenient to run this action in a temporary directory. -- -- This IO action fails if any of the following are true: -- * Ogma cannot be found in the current PATH. -- * Ogma cannot be executed. -- * The given file is not found or accessible. -- * The format in the given file is incorrect. -- * Ogma fails due to an internal error or bug. -- * The output file cannot be created due to lack of space or permissions. -- parseStandaloneFDB :: FilePath -- ^ Path to an input file -> IO () parseStandaloneFDB file = do (ec, _out, _err) <- readProcessWithExitCode "ogma" args "" assertBool errorMsg (ec == ExitSuccess) where args = [ "standalone", "--file-name", file, "--input-format", "fdb" , "--prop-format", "lustre"] errorMsg = "Parsing file " ++ file ++ " failed" -- | Test ogma by running it and checking the error code. -- -- This tests just whether ogma finishes with an error code or not. If files -- may be generated for the command being tested, it may be convenient to run -- this action in a temporary directory. -- -- This IO action fails if any of the following are true: -- * Ogma cannot be found in the current PATH. -- * Ogma cannot be executed. -- * The given command is not valid. -- * Ogma fails due to an internal error or bug. -- * Output files cannot be created due to lack of space or permissions. -- runErrorCode :: [String] -- ^ Arguments to pass to ogma -> Bool -> IO () runErrorCode args success = do (ec, _out, _err) <- readProcessWithExitCode "ogma" args "" -- True if success is expected and detected, or niether expected nor -- detected. let testPass = success == (ec == ExitSuccess) assertBool errorMsg testPass where errorMsg = "Testing ogma's CLI parser with arguments " ++ intercalate "," args ++ " failed" ogma-cli-1.10.0/tests/fcs-example1.json0000644000000000000000000000502215064246146016000 0ustar0000000000000000{ "RTSASpec": { "Internal_variables": [], "Other_variables": [ {"name":"param_is_short", "type":"bool"}, {"name":"param_value_short", "type":"real"}, {"name":"param_value_long", "type":"real"}, {"name":"upper_param_limit", "type":"real"}, {"name":"lower_param_limit", "type":"real"}, {"name":"envelope_issue", "type":"bool"} ], "Requirements": [ { "name": "behnazOne", "CoCoSpecCode": "true", "ptLTL": "((H ((((! flight_mode) & (Y flight_mode)) & (Y TRUE)) -> (Y (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))))) & (! (( replanning_mode ))))) -> (O[<10] ((flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))) | (( replanning_mode ))))) S (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))))) & (! (( replanning_mode ))))) -> (O[<10] ((flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))) | (( replanning_mode ))))) & (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode))))))))) & (((! ((! flight_mode) & (Y flight_mode))) S ((! ((! flight_mode) & (Y flight_mode))) & (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))))) -> (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))))) & (! (( replanning_mode ))))) -> (O[<10] ((flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))) | (( replanning_mode ))))) S (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))))) & (! (( replanning_mode ))))) -> (O[<10] ((flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))) | (( replanning_mode ))))) & (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode))))))))", "fretish": "Meaning not specified" } ] } } ogma-cli-1.10.0/tests/reduced_geofence_msgs_bad.h0000644000000000000000000000051115064246146020074 0ustar0000000000000000/** * @struct geofence_parameters_t * @brief data structure containing information about the parameters used by the geofence app */ typeduuuef struct{ uint8_t TlmHeader[CFE_SB_TLM_HDR_SIZE]; double lookahead; double hthreshold; double vthreshold; double hstepback; double vstepback; }geofence_parameters_t; ogma-cli-1.10.0/tests/reduced_geofence_msgs.h0000644000000000000000000000050615064246146017272 0ustar0000000000000000/** * @struct geofence_parameters_t * @brief data structure containing information about the parameters used by the geofence app */ typedef struct{ uint8_t TlmHeader[CFE_SB_TLM_HDR_SIZE]; double lookahead; double hthreshold; double vthreshold; double hstepback; double vstepback; }geofence_parameters_t; ogma-cli-1.10.0/tests/fdb-example1.json0000644000000000000000000002257515064246146015774 0ustar0000000000000000[ { "reqid": "test_req1", "parent_reqid": "", "project": "Test", "rationale": "", "fulltext": "during flight_mode when conflict_detected planner_module shall within 10 seconds satisfy (replanning_mode).", "semantics": { "type": "nasa", "scope": { "type": "in" }, "condition": "regular", "timing": "within", "response": "satisfaction", "variables": { "regular": [ "conflict_detected", "replanning_mode" ], "modes": [ "flight_mode" ] }, "scope_mode": "flight_mode", "scopeTextRange": [ 0, 17 ], "regular_condition": "(conflict_detected)", "qualifier_word": "when", "pre_condition": "(conflict_detected)", "conditionTextRange": [ 19, 40 ], "component_name": "planner_module", "componentTextRange": [ 42, 55 ], "duration": [ "10" ], "timingTextRange": [ 63, 79 ], "post_condition": "(( replanning_mode ))", "responseTextRange": [ 81, 105 ], "ft": "((LAST V ((! (Fin_flight_mode & (! LAST))) | (X (((Lin_flight_mode | LAST) V (((! (conflict_detected)) & ((! LAST) & ((X (conflict_detected)) & (! (Lin_flight_mode | LAST))))) -> ((X ((F[<=10] (( replanning_mode ))) | (F[<10] (Lin_flight_mode | LAST)))) & (! (Lin_flight_mode | LAST))))) & ((conflict_detected) -> ((F[<=10] (( replanning_mode ))) | (F[<10] (Lin_flight_mode | LAST)))))))) & (flight_mode -> (((Lin_flight_mode | LAST) V (((! (conflict_detected)) & ((! LAST) & ((X (conflict_detected)) & (! (Lin_flight_mode | LAST))))) -> ((X ((F[<=10] (( replanning_mode ))) | (F[<10] (Lin_flight_mode | LAST)))) & (! (Lin_flight_mode | LAST))))) & ((conflict_detected) -> ((F[<=10] (( replanning_mode ))) | (F[<10] (Lin_flight_mode | LAST)))))))", "pt": "((H ((Lin_flight_mode & (! FTP)) -> (Y (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | Fin_flight_mode)) & (! (( replanning_mode ))))) -> (O[<10] (Fin_flight_mode | (( replanning_mode ))))) S (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | Fin_flight_mode)) & (! (( replanning_mode ))))) -> (O[<10] (Fin_flight_mode | (( replanning_mode ))))) & Fin_flight_mode))))) & (((! Lin_flight_mode) S ((! Lin_flight_mode) & Fin_flight_mode)) -> (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | Fin_flight_mode)) & (! (( replanning_mode ))))) -> (O[<10] (Fin_flight_mode | (( replanning_mode ))))) S (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | Fin_flight_mode)) & (! (( replanning_mode ))))) -> (O[<10] (Fin_flight_mode | (( replanning_mode ))))) & Fin_flight_mode))))", "ftExpanded": "((LAST V ((! ((((! flight_mode) & (! LAST)) & (X flight_mode)) & (! LAST))) | (X (((((flight_mode & (! LAST)) & (X (! flight_mode))) | LAST) V (((! (conflict_detected)) & ((! LAST) & ((X (conflict_detected)) & (! (((flight_mode & (! LAST)) & (X (! flight_mode))) | LAST))))) -> ((X ((F[<=10] (( replanning_mode ))) | (F[<10] (((flight_mode & (! LAST)) & (X (! flight_mode))) | LAST)))) & (! (((flight_mode & (! LAST)) & (X (! flight_mode))) | LAST))))) & ((conflict_detected) -> ((F[<=10] (( replanning_mode ))) | (F[<10] (((flight_mode & (! LAST)) & (X (! flight_mode))) | LAST)))))))) & (flight_mode -> (((((flight_mode & (! LAST)) & (X (! flight_mode))) | LAST) V (((! (conflict_detected)) & ((! LAST) & ((X (conflict_detected)) & (! (((flight_mode & (! LAST)) & (X (! flight_mode))) | LAST))))) -> ((X ((F[<=10] (( replanning_mode ))) | (F[<10] (((flight_mode & (! LAST)) & (X (! flight_mode))) | LAST)))) & (! (((flight_mode & (! LAST)) & (X (! flight_mode))) | LAST))))) & ((conflict_detected) -> ((F[<=10] (( replanning_mode ))) | (F[<10] (((flight_mode & (! LAST)) & (X (! flight_mode))) | LAST)))))))", "ptExpanded": "((H ((((! flight_mode) & (Y flight_mode)) & (Y TRUE)) -> (Y (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))))) & (! (( replanning_mode ))))) -> (O[<10] ((flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))) | (( replanning_mode ))))) S (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))))) & (! (( replanning_mode ))))) -> (O[<10] ((flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))) | (( replanning_mode ))))) & (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode))))))))) & (((! ((! flight_mode) & (Y flight_mode))) S ((! ((! flight_mode) & (Y flight_mode))) & (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))))) -> (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))))) & (! (( replanning_mode ))))) -> (O[<10] ((flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))) | (( replanning_mode ))))) S (((O[=10] (((conflict_detected) & ((Y (! (conflict_detected))) | (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))))) & (! (( replanning_mode ))))) -> (O[<10] ((flight_mode & ((! (Y TRUE)) | (Y (! flight_mode)))) | (( replanning_mode ))))) & (flight_mode & ((! (Y TRUE)) | (Y (! flight_mode))))))))", "component": "planner_module", "CoCoSpecCode": "((H(((( not flight_mode) and (pre (flight_mode))) and ( not FTP)) => (pre (SI( (flight_mode and (FTP or (pre ( not flight_mode)))), ((OT(10,10,( ( (conflict_detected) and ( ( Y ( not (conflict_detected) ) ) or ( flight_mode and ( FTP or ( Y not flight_mode ) ) ) ) ) and ( not (( replanning_mode )) ) ))) => (OT(10-1,0,( ( flight_mode and ( FTP or ( Y not flight_mode ) ) ) or (( replanning_mode )) )))) ))))) and ((SI( (flight_mode and (FTP or (pre ( not flight_mode)))), ( not (( not flight_mode) and (pre (flight_mode)))) )) => (SI( (flight_mode and (FTP or (pre ( not flight_mode)))), ((OT(10,10,( ( (conflict_detected) and ( ( Y ( not (conflict_detected) ) ) or ( flight_mode and ( FTP or ( Y not flight_mode ) ) ) ) ) and ( not (( replanning_mode )) ) ))) => (OT(10-1,0,( ( flight_mode and ( FTP or ( Y not flight_mode ) ) ) or (( replanning_mode )) )))) ))))", "diagramVariables": "M = flight_mode, TC = (conflict_detected), n = 10, Response = (( replanning_mode )).", "description": "ENFORCED: in every interval where flight_mode holds.\nTRIGGER: first point in the interval if (conflict_detected) is true and any point in the interval where (conflict_detected) becomes true (from false).\nREQUIRES: for every trigger, RES must hold at some point with distance <=10 from the trigger, except if the end of the interval occurs sooner.", "diagram": "_media/user-interface/examples/svgDiagrams/in_regular_within_satisfaction.svg" }, "_id": "fbc0a840-a04b-11ea-b135-098996762962" } ]ogma-cli-1.10.0/src/0000755000000000000000000000000015064246146012246 5ustar0000000000000000ogma-cli-1.10.0/src/Main.hs0000644000000000000000000000522315064246146013470 0ustar0000000000000000-- Copyright 2020 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. -- -- | Ogma: Tool to interoperate between -- and other languages. -- -- Ogma is a tool to facilitate integration of safe runtime monitors into other -- systems. It takes information from a system created in a language (e.g., -- Lustre) and produces specifications for the runtime verification -- framework . Currently, features -- supported are: -- -- * Translation properties defined in structured natural language into -- corresponding expressions in Copilot. -- -- * Translation of C headers declaring structs into the corresponding Copilot -- Struct definitions. -- -- * Translation of C headers declaring structs into CFS message handlers that -- copy data in global variables. -- -- * Generate NASA core Flight System (cFS) applications for runtime monitoring -- using Copilot. -- -- * Generate Robot Operating System (ROS) applications for runtime monitoring -- using Copilot. -- -- * Generate F' (FPrime) components for runtime monitoring using Copilot. -- -- More information can be obtained by calling ogma with the argument @--help@. module Main ( main ) where -- External imports import Options.Applicative (ParserInfo, execParser, fullDesc, header, helper, info, progDesc, (<**>)) -- Internal imports: CLI parsing, handling, and processing of results. import CLI.CommandTop ( CommandOpts, command, commandDesc, commandOptsParser ) import CLI.Result ( processResult ) -- | Ogma: Helper tool to interoperate between Copilot and other languages. main :: IO () main = execParser fullCLIOpts >>= command >>= processResult -- | Full program options. fullCLIOpts :: ParserInfo CommandOpts fullCLIOpts = info (commandOptsParser <**> helper) ( fullDesc <> progDesc commandDesc <> header strProgramSummary ) -- | Short program description strProgramSummary :: String strProgramSummary = "ogma - an anything-to-Copilot application generator" ogma-cli-1.10.0/src/CLI/0000755000000000000000000000000015064246146012655 5ustar0000000000000000ogma-cli-1.10.0/src/CLI/CommandROSApp.hs0000644000000000000000000002024415064246146015616 0ustar0000000000000000-- Copyright 2022 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. -- -- | CLI interface to the ROSApp subcommand. module CLI.CommandROSApp ( -- * Direct command access command , CommandOpts , ErrorCode -- * CLI , commandDesc , commandOptsParser ) where -- External imports import Options.Applicative ( Parser, help, long, metavar, many, optional, short, showDefault, strOption, value ) -- External imports: command results import Command.Result ( Result ) -- External imports: actions or commands supported import Command.ROSApp (ErrorCode) import qualified Command.ROSApp -- * Command -- | Options needed to generate the ROS application. data CommandOpts = CommandOpts { rosAppConditionExpr :: Maybe String , rosAppInputFile :: Maybe String , rosAppTarget :: String , rosAppTemplateDir :: Maybe String , rosAppVarNames :: Maybe String , rosAppVarDB :: Maybe String , rosAppHandlers :: Maybe String , rosAppFormat :: String , rosAppPropFormat :: String , rosAppPropVia :: Maybe String , rosAppTemplateVars :: Maybe String , rosAppTestingApps :: [String] , rosAppTestingVars :: [String] } -- | Create (ROS) applications -- that subscribe to obtain necessary data from topics and call Copilot when -- new data arrives. -- -- This is just a wrapper around "Command.ROSApp". command :: CommandOpts -> IO (Result ErrorCode) command c = Command.ROSApp.command options where options = Command.ROSApp.CommandOptions { Command.ROSApp.commandConditionExpr = rosAppConditionExpr c , Command.ROSApp.commandInputFile = rosAppInputFile c , Command.ROSApp.commandTargetDir = rosAppTarget c , Command.ROSApp.commandTemplateDir = rosAppTemplateDir c , Command.ROSApp.commandVariables = rosAppVarNames c , Command.ROSApp.commandVariableDB = rosAppVarDB c , Command.ROSApp.commandHandlers = rosAppHandlers c , Command.ROSApp.commandFormat = rosAppFormat c , Command.ROSApp.commandPropFormat = rosAppPropFormat c , Command.ROSApp.commandPropVia = rosAppPropVia c , Command.ROSApp.commandExtraVars = rosAppTemplateVars c , Command.ROSApp.commandTestingApps = appNames , Command.ROSApp.commandTestingVars = rosAppTestingVars c } -- Turn the qualified app names into tuples of package and node name. appNames = map splitAppName $ rosAppTestingApps c splitAppName name = Command.ROSApp.Node package (drop 1 nodeT) where (package, nodeT) = break (== ':') name -- * CLI -- | ROS command description commandDesc :: String commandDesc = "Generate a ROS 2 monitoring package" -- | Subparser for the @ros@ command, used to generate a Robot Operating System -- application connected to Copilot monitors. commandOptsParser :: Parser CommandOpts commandOptsParser = CommandOpts <$> optional ( strOption ( long "condition-expr" <> metavar "EXPRESSION" <> help strROSAppConditionExprArgDesc ) ) <*> optional ( strOption ( long "input-file" <> metavar "FILENAME" <> help strROSAppFileNameArgDesc ) ) <*> strOption ( long "app-target-dir" <> metavar "DIR" <> showDefault <> value "ros" <> help strROSAppDirArgDesc ) <*> optional ( strOption ( long "app-template-dir" <> metavar "DIR" <> help strROSAppTemplateDirArgDesc ) ) <*> optional ( strOption ( long "variable-file" <> metavar "FILENAME" <> help strROSAppVarListArgDesc ) ) <*> optional ( strOption ( long "variable-db" <> metavar "FILENAME" <> help strROSAppVarDBArgDesc ) ) <*> optional ( strOption ( long "handlers-file" <> metavar "FILENAME" <> help strROSAppHandlerListArgDesc ) ) <*> strOption ( long "input-format" <> short 'f' <> metavar "FORMAT_NAME" <> help strROSAppFormatDesc <> showDefault <> value "fcs" ) <*> strOption ( long "prop-format" <> short 'p' <> metavar "FORMAT_NAME" <> help strROSAppPropFormatDesc <> showDefault <> value "smv" ) <*> optional ( strOption ( long "parse-prop-via" <> metavar "COMMAND" <> help strROSAppPropViaDesc ) ) <*> optional ( strOption ( long "template-vars" <> metavar "FILENAME" <> help strROSAppTemplateVarsArgDesc ) ) <*> many (strOption ( long "testing-app" <> metavar "package:node" <> help strROSAppROSNodesTestingListArgDesc ) ) <*> many (strOption ( long "testing-vars" <> metavar "variable_name" <> showDefault <> help strROSAppHandlerListArgDesc ) ) -- | Argument target directory to ROS app generation command strROSAppDirArgDesc :: String strROSAppDirArgDesc = "Target directory" -- | Argument template directory to ROS app generation command strROSAppTemplateDirArgDesc :: String strROSAppTemplateDirArgDesc = "Directory holding ROS application source template" -- | Argument expression to ROS app generation command. strROSAppConditionExprArgDesc :: String strROSAppConditionExprArgDesc = "Expression used as guard or trigger condition" -- | Argument input file to ROS app generation command strROSAppFileNameArgDesc :: String strROSAppFileNameArgDesc = "File containing input specification" -- | Argument variable list to ROS app generation command strROSAppVarListArgDesc :: String strROSAppVarListArgDesc = "File containing list of ROS variables to make accessible" -- | Argument variable database to ROS app generation command strROSAppVarDBArgDesc :: String strROSAppVarDBArgDesc = "File containing a DB of known ROS variables" -- | Argument handler list to ROS app generation command strROSAppHandlerListArgDesc :: String strROSAppHandlerListArgDesc = "File containing list of Copilot handlers used in the specification" -- | Format flag description. strROSAppFormatDesc :: String strROSAppFormatDesc = "Format of the input file" -- | Property format flag description. strROSAppPropFormatDesc :: String strROSAppPropFormatDesc = "Format of temporal or boolean properties" -- | External command to pre-process individual properties. strROSAppPropViaDesc :: String strROSAppPropViaDesc = "Command to pre-process individual properties" -- | Additional template variable file flag description. strROSAppTemplateVarsArgDesc :: String strROSAppTemplateVarsArgDesc = "JSON file containing additional variables to expand in template" -- | Argument packages to tested list to ROS app generation command strROSAppROSNodesTestingListArgDesc :: String strROSAppROSNodesTestingListArgDesc = "Turn on ROS2 package node during testing" -- | Argument variables to be tested list to ROS app generation command strROSAppVarsTestingListArgDesc :: String strROSAppVarsTestingListArgDesc = "Limit random input generation to these variables" ogma-cli-1.10.0/src/CLI/CommandStandalone.hs0000644000000000000000000001533715064246146016611 0ustar0000000000000000-- Copyright 2020 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. -- -- | CLI interface to the Standalone subcommand module CLI.CommandStandalone ( -- * Direct command access command , CommandOpts , ErrorCode -- * CLI , commandDesc , commandOptsParser ) where -- External imports import Options.Applicative (Parser, help, long, many, metavar, optional, short, showDefault, strOption, switch, value) -- External imports: command results import Command.Result ( Result(..) ) import Data.Location ( Location(..) ) -- External imports: actions or commands supported import Command.Standalone (ErrorCode) import qualified Command.Standalone -- * Command -- | Options to generate Copilot from specification. data CommandOpts = CommandOpts { standaloneTargetDir :: FilePath , standaloneTemplateDir :: Maybe FilePath , standaloneConditionExpr :: Maybe String , standaloneFileName :: Maybe FilePath , standaloneFormat :: String , standalonePropFormat :: String , standaloneTypes :: [String] , standaloneTarget :: String , standalonePropVia :: Maybe String , standaloneTemplateVars :: Maybe String } -- | Transform an input specification into a Copilot specification. command :: CommandOpts -> IO (Result ErrorCode) command c = Command.Standalone.command internalCommandOpts where internalCommandOpts :: Command.Standalone.CommandOptions internalCommandOpts = Command.Standalone.CommandOptions { Command.Standalone.commandConditionExpr = standaloneConditionExpr c , Command.Standalone.commandInputFile = standaloneFileName c , Command.Standalone.commandTargetDir = standaloneTargetDir c , Command.Standalone.commandTemplateDir = standaloneTemplateDir c , Command.Standalone.commandFormat = standaloneFormat c , Command.Standalone.commandPropFormat = standalonePropFormat c , Command.Standalone.commandTypeMapping = types , Command.Standalone.commandFilename = standaloneTarget c , Command.Standalone.commandPropVia = standalonePropVia c , Command.Standalone.commandExtraVars = standaloneTemplateVars c } types :: [(String, String)] types = map splitTypeMapping (standaloneTypes c) splitTypeMapping :: String -> (String, String) splitTypeMapping s = (h, safeTail t) where (h, t) = span (/= ':') s safeTail xs = if null xs then xs else tail xs -- * CLI -- | Command description for CLI help. commandDesc :: String commandDesc = "Generate a standalone Copilot file from an input specification" -- | Subparser for the @standalone@ command, used to generate a Copilot -- specification from an input specification file. commandOptsParser :: Parser CommandOpts commandOptsParser = CommandOpts <$> strOption ( long "target-dir" <> metavar "DIR" <> showDefault <> value "copilot" <> help strStandaloneTargetDirDesc ) <*> optional ( strOption ( long "template-dir" <> metavar "DIR" <> help strStandaloneTemplateDirArgDesc ) ) <*> optional ( strOption ( long "condition-expr" <> metavar "FILENAME" <> help strStandaloneConditionExprDesc ) ) <*> optional ( strOption ( long "file-name" <> metavar "FILENAME" <> help strStandaloneFilenameDesc ) ) <*> strOption ( long "input-format" <> short 'f' <> metavar "FORMAT_NAME" <> help strStandaloneFormatDesc <> showDefault <> value "fcs" ) <*> strOption ( long "prop-format" <> short 'p' <> metavar "FORMAT_NAME" <> help strStandalonePropFormatDesc <> showDefault <> value "smv" ) <*> many (strOption ( long "map-type" <> short 'm' <> metavar "TYPE_NAME:TYPE_NAME" <> help strStandaloneMapTypeDesc ) ) <*> strOption ( long "target-file-name" <> metavar "FILENAME" <> help strStandaloneTargetDesc <> showDefault <> value "monitor" ) <*> optional ( strOption ( long "parse-prop-via" <> metavar "COMMAND" <> help strStandalonePropViaDesc ) ) <*> optional ( strOption ( long "template-vars" <> metavar "FILENAME" <> help strStandaloneTemplateVarsArgDesc ) ) -- | Target dir flag description. strStandaloneTargetDirDesc :: String strStandaloneTargetDirDesc = "Target directory" -- | Template dir flag description. strStandaloneTemplateDirArgDesc :: String strStandaloneTemplateDirArgDesc = "Directory holding standalone source template" -- | Condition flag description. strStandaloneConditionExprDesc :: String strStandaloneConditionExprDesc = "Condition upon which the monitor will fire or notify" -- | Filename flag description. strStandaloneFilenameDesc :: String strStandaloneFilenameDesc = "File with properties or requirements" -- | Format flag description. strStandaloneFormatDesc :: String strStandaloneFormatDesc = "Format of the input file" -- | Property format flag description. strStandalonePropFormatDesc :: String strStandalonePropFormatDesc = "Format of temporal or boolean properties" -- | Type mapping flag description. strStandaloneMapTypeDesc :: String strStandaloneMapTypeDesc = "Map a type to another type" -- | Target file name flag description. strStandaloneTargetDesc :: String strStandaloneTargetDesc = "Filename prefix for monitoring files in target language" -- | External command to pre-process individual properties. strStandalonePropViaDesc :: String strStandalonePropViaDesc = "Command to pre-process individual properties" -- | Additional template variable file flag description. strStandaloneTemplateVarsArgDesc :: String strStandaloneTemplateVarsArgDesc = "JSON file containing additional variables to expand in template" ogma-cli-1.10.0/src/CLI/CommandDiagram.hs0000644000000000000000000001732515064246146016064 0ustar0000000000000000-- Copyright 2024 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. -- -- | CLI interface to the diagram subcommand. module CLI.CommandDiagram ( -- * Direct command access command , CommandOpts , ErrorCode -- * CLI , commandDesc , commandOptsParser ) where -- External imports import Options.Applicative (Parser, help, long, metavar, optional, short, showDefault, strOption, value) -- External imports: command results import Command.Result ( Result(..) ) import Data.Location ( Location(..) ) -- External imports: actions or commands supported import Command.Diagram (diagram) import qualified Command.Diagram -- * Command -- | Options to generate Copilot from diagram. data CommandOpts = CommandOpts { diagramTargetDir :: FilePath , diagramTemplateDir :: Maybe FilePath , diagramFileName :: FilePath , diagramFormat :: String , diagramPropFormat :: String , diagramTarget :: String , diagramMode :: String , diagramStateVar :: String , diagramInputVar :: String } -- | Transform an input diagram into a Copilot specification. command :: CommandOpts -> IO (Result ErrorCode) command c | Nothing <- diagramFormatP = return $ Error ecFormatError "The diagram format specified is incorrect" LocationNothing | Nothing <- diagramModeP = return $ Error ecModeError "The mode specified is incorrect" LocationNothing | Nothing <- diagramPropFormatP = return $ Error ecPropFormatError "The format specified for transitions or edge properties is incorrect" LocationNothing | Just mode <- diagramModeP , Just format <- diagramFormatP , Just propFormat <- diagramPropFormatP = do let internalCommandOpts :: Command.Diagram.DiagramOptions internalCommandOpts = Command.Diagram.DiagramOptions { Command.Diagram.diagramTargetDir = diagramTargetDir c , Command.Diagram.diagramTemplateDir = diagramTemplateDir c , Command.Diagram.diagramFormat = format , Command.Diagram.diagramPropFormat = propFormat , Command.Diagram.diagramFilename = diagramTarget c , Command.Diagram.diagramMode = mode , Command.Diagram.diagramStateVar = diagramStateVar c , Command.Diagram.diagramInputVar = diagramInputVar c } diagram (diagramFileName c) internalCommandOpts where diagramFormatP = parseDiagramFormat (diagramFormat c) diagramModeP = parseDiagramMode (diagramMode c) diagramPropFormatP = parseDiagramPropFormat (diagramPropFormat c) parseDiagramFormat :: String -> Maybe Command.Diagram.DiagramFormat parseDiagramFormat "dot" = Just Command.Diagram.Dot parseDiagramFormat "graphviz" = Just Command.Diagram.Dot parseDiagramFormat "mermaid" = Just Command.Diagram.Mermaid parseDiagramFormat _ = Nothing parseDiagramMode :: String -> Maybe Command.Diagram.DiagramMode parseDiagramMode "check" = Just Command.Diagram.CheckState parseDiagramMode "calculate" = Just Command.Diagram.ComputeState parseDiagramMode "safeguard" = Just Command.Diagram.CheckMoves parseDiagramMode _ = Nothing parseDiagramPropFormat :: String -> Maybe Command.Diagram.DiagramPropFormat parseDiagramPropFormat "lustre" = Just Command.Diagram.Lustre parseDiagramPropFormat "cocospec" = parseDiagramPropFormat "lustre" parseDiagramPropFormat "inputs" = Just Command.Diagram.Inputs parseDiagramPropFormat "literal" = Just Command.Diagram.Literal parseDiagramPropFormat "smv" = Just Command.Diagram.SMV parseDiagramPropFormat _ = Nothing -- * CLI -- | Command description for CLI help. commandDesc :: String commandDesc = "Generate a monitor from state machine diagram" -- | Subparser for the @diagram@ command, used to generate a Copilot -- specification from an input diagram file. commandOptsParser :: Parser CommandOpts commandOptsParser = CommandOpts <$> strOption ( long "target-dir" <> metavar "DIR" <> showDefault <> value "copilot" <> help strDiagramTargetDirDesc ) <*> optional ( strOption ( long "template-dir" <> metavar "DIR" <> help strDiagramTemplateDirArgDesc ) ) <*> strOption ( long "file-name" <> metavar "FILENAME" <> help strDiagramFilenameDesc ) <*> strOption ( long "input-format" <> short 'f' <> metavar "FORMAT_NAME" <> help strDiagramFormatDesc <> showDefault <> value "mermaid" ) <*> strOption ( long "prop-format" <> short 'p' <> metavar "FORMAT_NAME" <> help strDiagramPropFormatDesc <> showDefault <> value "inputs" ) <*> strOption ( long "target-file-name" <> metavar "FILENAME" <> help strDiagramTargetDesc <> showDefault <> value "monitor" ) <*> strOption ( long "mode" <> metavar "MODE" <> help strDiagramModeDesc <> showDefault <> value "check" ) <*> strOption ( long "state-var" <> metavar "NAME" <> help strDiagramStateVarDesc <> showDefault <> value "state" ) <*> strOption ( long "input-var" <> metavar "NAME" <> help strDiagramInputVarDesc <> showDefault <> value "input" ) -- | Target dir flag description. strDiagramTargetDirDesc :: String strDiagramTargetDirDesc = "Target directory" -- | Template dir flag description. strDiagramTemplateDirArgDesc :: String strDiagramTemplateDirArgDesc = "Directory holding target source template" -- | Filename flag description. strDiagramFilenameDesc :: String strDiagramFilenameDesc = "File with diagram source" -- | Format flag description. strDiagramFormatDesc :: String strDiagramFormatDesc = "Format of the input file" -- | Property format flag description. strDiagramPropFormatDesc :: String strDiagramPropFormatDesc = "Format of temporal or boolean properties associated to diagram edges" -- | Target file name flag description. strDiagramTargetDesc :: String strDiagramTargetDesc = "Filename prefix for monitoring files in target language" -- | Mode name flag description. strDiagramModeDesc :: String strDiagramModeDesc = "Mode of operation (check, calculate, safeguard)" strDiagramInputVarDesc :: String strDiagramInputVarDesc = "Name of the input variable" strDiagramStateVarDesc :: String strDiagramStateVarDesc = "Name of the state variable" -- * Error codes -- | Encoding of reasons why the command can fail. -- -- The error code used is 1 for user error. type ErrorCode = Int -- | Error: unknown diagram format. ecFormatError :: ErrorCode ecFormatError = 2 -- | Error: unknown operation mode. ecModeError :: ErrorCode ecModeError = 3 -- | Error: unknown property format. ecPropFormatError :: ErrorCode ecPropFormatError = 4 ogma-cli-1.10.0/src/CLI/CommandFPrimeApp.hs0000644000000000000000000001613715064246146016343 0ustar0000000000000000-- Copyright 2022 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. -- -- | CLI interface to the FPrimeApp subcommand. module CLI.CommandFPrimeApp ( -- * Direct command access command , CommandOpts , ErrorCode -- * CLI , commandDesc , commandOptsParser ) where -- External imports import Options.Applicative ( Parser, help, long, metavar, optional, short, showDefault, strOption, value ) -- External imports: command results import Command.Result ( Result ) -- External imports: actions or commands supported import Command.FPrimeApp (ErrorCode) import qualified Command.FPrimeApp -- * Command -- | Options needed to generate the FPrime component. data CommandOpts = CommandOpts { fprimeAppConditionExpr :: Maybe String , fprimeAppInputFile :: Maybe String , fprimeAppTarget :: String , fprimeAppTemplateDir :: Maybe String , fprimeAppVariables :: Maybe String , fprimeAppVarDB :: Maybe String , fprimeAppHandlers :: Maybe String , fprimeAppFormat :: String , fprimeAppPropFormat :: String , fprimeAppPropVia :: Maybe String , fprimeAppTemplateVars :: Maybe String } -- | Create component that subscribe -- to obtain necessary data from the bus and call Copilot when new data -- arrives. -- -- This is just a wrapper around "Command.fprimeApp". command :: CommandOpts -> IO (Result ErrorCode) command c = Command.FPrimeApp.command options where options = Command.FPrimeApp.CommandOptions { Command.FPrimeApp.commandConditionExpr = fprimeAppConditionExpr c , Command.FPrimeApp.commandInputFile = fprimeAppInputFile c , Command.FPrimeApp.commandTargetDir = fprimeAppTarget c , Command.FPrimeApp.commandTemplateDir = fprimeAppTemplateDir c , Command.FPrimeApp.commandVariables = fprimeAppVariables c , Command.FPrimeApp.commandVariableDB = fprimeAppVarDB c , Command.FPrimeApp.commandHandlers = fprimeAppHandlers c , Command.FPrimeApp.commandFormat = fprimeAppFormat c , Command.FPrimeApp.commandPropFormat = fprimeAppPropFormat c , Command.FPrimeApp.commandPropVia = fprimeAppPropVia c , Command.FPrimeApp.commandExtraVars = fprimeAppTemplateVars c } -- * CLI -- | FPrime command description commandDesc :: String commandDesc = "Generate a complete F' monitoring component" -- | Subparser for the @fprime@ command, used to generate an FPrime component -- connected to Copilot monitors. commandOptsParser :: Parser CommandOpts commandOptsParser = CommandOpts <$> optional ( strOption ( long "condition-expr" <> metavar "EXPRESSION" <> help strFPrimeAppConditionExprArgDesc ) ) <*> optional ( strOption ( long "input-file" <> metavar "FILENAME" <> help strFPrimeAppFileNameArgDesc ) ) <*> strOption ( long "app-target-dir" <> metavar "DIR" <> showDefault <> value "fprime" <> help strFPrimeAppDirArgDesc ) <*> optional ( strOption ( long "app-template-dir" <> metavar "DIR" <> help strFPrimeAppTemplateDirArgDesc ) ) <*> optional ( strOption ( long "variable-file" <> metavar "FILENAME" <> help strFPrimeAppVarListArgDesc ) ) <*> optional ( strOption ( long "variable-db" <> metavar "FILENAME" <> help strFPrimeAppVarDBArgDesc ) ) <*> optional ( strOption ( long "handlers-file" <> metavar "FILENAME" <> help strFPrimeAppHandlerListArgDesc ) ) <*> strOption ( long "input-format" <> short 'f' <> metavar "FORMAT_NAME" <> help strFPrimeAppFormatDesc <> showDefault <> value "fcs" ) <*> strOption ( long "prop-format" <> short 'p' <> metavar "FORMAT_NAME" <> help strFPrimeAppPropFormatDesc <> showDefault <> value "smv" ) <*> optional ( strOption ( long "parse-prop-via" <> metavar "COMMAND" <> help strFPrimeAppPropViaDesc ) ) <*> optional ( strOption ( long "template-vars" <> metavar "FILENAME" <> help strFPrimeAppTemplateVarsArgDesc ) ) -- | Argument target directory to FPrime component generation command strFPrimeAppDirArgDesc :: String strFPrimeAppDirArgDesc = "Target directory" -- | Argument template directory to FPrime component generation command strFPrimeAppTemplateDirArgDesc :: String strFPrimeAppTemplateDirArgDesc = "Directory holding F' component source template" -- | Argument expression to FPrime app generation command. strFPrimeAppConditionExprArgDesc :: String strFPrimeAppConditionExprArgDesc = "Expression used as guard or trigger condition" -- | Argument input file to FPrime component generation command strFPrimeAppFileNameArgDesc :: String strFPrimeAppFileNameArgDesc = "File containing input specification" -- | Argument variable list to FPrime component generation command strFPrimeAppVarListArgDesc :: String strFPrimeAppVarListArgDesc = "File containing list of F' variables to make accessible" -- | Argument variable database to FPrime component generation command strFPrimeAppVarDBArgDesc :: String strFPrimeAppVarDBArgDesc = "File containing a DB of known F' variables" -- | Argument handler list to FPrime component generation command strFPrimeAppHandlerListArgDesc :: String strFPrimeAppHandlerListArgDesc = "File containing list of Copilot handlers used in the specification" -- | Format flag description. strFPrimeAppFormatDesc :: String strFPrimeAppFormatDesc = "Format of the input file" -- | Property format flag description. strFPrimeAppPropFormatDesc :: String strFPrimeAppPropFormatDesc = "Format of temporal or boolean properties" -- | External command to pre-process individual properties. strFPrimeAppPropViaDesc :: String strFPrimeAppPropViaDesc = "Command to pre-process individual properties" -- | Additional template variable file flag description. strFPrimeAppTemplateVarsArgDesc :: String strFPrimeAppTemplateVarsArgDesc = "JSON file containing additional variables to expand in template" ogma-cli-1.10.0/src/CLI/CommandOverview.hs0000644000000000000000000001042615064246146016321 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} -- Copyright 2020 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. -- -- | CLI interface to the Overview subcommand. module CLI.CommandOverview ( -- * Direct command access command , CommandOpts , ErrorCode -- * CLI , commandDesc , commandOptsParser ) where -- External imports import Data.Aeson (toJSON) import qualified Data.Text.Lazy as T import qualified Data.Text.Lazy.IO as T import Options.Applicative (Parser, help, long, metavar, optional, short, showDefault, strOption, value) import Text.Microstache -- External imports: command results import Command.Result ( Result(..) ) -- External imports: actions or commands supported import Command.Overview (ErrorCode) import qualified Command.Overview -- * Command -- | Options to generate an overview from the input specification(s). data CommandOpts = CommandOpts { overviewFileName :: FilePath , overviewFormat :: String , overviewPropFormat :: String , overviewPropVia :: Maybe String } -- | Print an overview of the input specification(s). command :: CommandOpts -> IO (Result ErrorCode) command c = do (mOutput, result) <- Command.Overview.command (overviewFileName c) internalCommandOpts case (mOutput, outputString) of (Just output, Right template) -> T.putStr $ renderMustache template (toJSON output) _ -> putStrLn "Error" return result where internalCommandOpts :: Command.Overview.CommandOptions internalCommandOpts = Command.Overview.CommandOptions { Command.Overview.commandFormat = overviewFormat c , Command.Overview.commandPropFormat = overviewPropFormat c , Command.Overview.commandPropVia = overviewPropVia c } outputString = compileMustacheText "output" $ T.unlines [ "The file has:" , " - {{commandExternalVariables}} external variables." , " - {{commandInternalVariables}} internal variables." , " - {{commandRequirements}} requirements." ] -- * CLI -- | Command description for CLI help. commandDesc :: String commandDesc = "Generate an overview of the input specification(s)" -- | Subparser for the @overview@ command, used to generate an overview -- of the input specifications. commandOptsParser :: Parser CommandOpts commandOptsParser = CommandOpts <$> strOption ( long "file-name" <> metavar "FILENAME" <> help strOverviewFilenameDesc ) <*> strOption ( long "input-format" <> short 'f' <> metavar "FORMAT_NAME" <> help strOverviewFormatDesc <> showDefault <> value "fcs" ) <*> strOption ( long "prop-format" <> short 'p' <> metavar "FORMAT_NAME" <> help strOverviewPropFormatDesc <> showDefault <> value "smv" ) <*> optional ( strOption ( long "parse-prop-via" <> metavar "COMMAND" <> help strOverviewPropViaDesc ) ) -- | Filename flag description. strOverviewFilenameDesc :: String strOverviewFilenameDesc = "File with properties or requirements" -- | Format flag description. strOverviewFormatDesc :: String strOverviewFormatDesc = "Format of the input file" -- | Property format flag description. strOverviewPropFormatDesc :: String strOverviewPropFormatDesc = "Format of temporal or boolean properties" -- | External command to pre-process individual properties. strOverviewPropViaDesc :: String strOverviewPropViaDesc = "Command to pre-process individual properties" ogma-cli-1.10.0/src/CLI/CommandTop.hs0000644000000000000000000002307015064246146015254 0ustar0000000000000000-- Copyright 2020 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. -- -- | CLI parsing, handling, and execution. -- -- The full module CLI is just a sum of all the subcommands with their -- respective CLI options. -- -- This module defines: -- -- - A 'CommandOpts' type that represents all options to the program, -- the subcommand executed, and any options for that subcommand. -- -- - A 'commandOptsParser' parser for the subcommands and their arguments, -- delegating the argument parsing to each subcommand's own CLI parser. -- -- - A 'command' function that dispatcher processing of the execution to the -- appropriate subcommand. -- -- - An 'ErrorCode' type that represents reasons why the program may have -- failed. -- -- Each of the subcommands is defined using the same standard interface. -- This module is merely a sum of all subcommands: -- -- - The type 'CommandOpts' is the sum of all respective subcommand options -- (whose types all share the same name but have different representations). -- -- - The parser is a sum of all subparsers, each attached to a specific -- command name defined in this module. -- -- - The command function is merely a dispatcher that detects the subcommand -- that must be executed, extracts the input, runs it, and translates the -- subcommands result into a top-level command result. -- -- - The error code is a plain representation that collapses the local -- subcommand error codes into a few possible values. module CLI.CommandTop ( -- * Direct command access CommandOpts , command , ErrorCode -- * CLI , commandDesc , commandOptsParser ) where -- External imports import Options.Applicative ( CommandFields, Mod, Parser, helper, info, progDesc, subparser, (<**>) ) import qualified Options.Applicative as OptParse -- External imports: command results import Command.Result ( Result ) -- Internal imports: subcommands import qualified CLI.CommandCFSApp import qualified CLI.CommandCStructs2Copilot import qualified CLI.CommandCStructs2MsgHandlers import qualified CLI.CommandDiagram import qualified CLI.CommandFPrimeApp import qualified CLI.CommandOverview import qualified CLI.CommandROSApp import qualified CLI.CommandStandalone -- * Command -- | Commands supported by Ogma and their arguments. -- All subcommands use the same interface, so they all use the type name -- @CommandOpts@ to capture their respective arguments. These types are -- different for each subcommand. data CommandOpts = CommandOptsCFSApp CLI.CommandCFSApp.CommandOpts | CommandOptsCStructs2Copilot CLI.CommandCStructs2Copilot.CommandOpts | CommandOptsCStructs2MsgHandlers CLI.CommandCStructs2MsgHandlers.CommandOpts | CommandOptsDiagram CLI.CommandDiagram.CommandOpts | CommandOptsFPrimeApp CLI.CommandFPrimeApp.CommandOpts | CommandOptsOverview CLI.CommandOverview.CommandOpts | CommandOptsROSApp CLI.CommandROSApp.CommandOpts | CommandOptsStandalone CLI.CommandStandalone.CommandOpts -- * CLI -- | Command description for CLI help. commandDesc :: String commandDesc = "Generate complete or partial Copilot applications from multiple languages" -- | Subparser for multiple subcommands. commandOptsParser :: Parser CommandOpts commandOptsParser = subparser ( subcommandOverview <> subcommandCStructs <> subcommandMsgHandlers <> subcommandCFSApp <> subcommandFPrimeApp <> subcommandROSApp <> subcommandStandalone <> subcommandDiagram ) -- | Modifier for the overview subcommand, linking the subcommand options and -- description to the command @overview@ at top level. subcommandOverview :: Mod CommandFields CommandOpts subcommandOverview = subcommand "overview" (CommandOptsOverview <$> CLI.CommandOverview.commandOptsParser) CLI.CommandOverview.commandDesc -- | Modifier for the CStruct to Copilot Struct generation subcommand, linking -- the subcommand options and description to the command @structs@ at top -- level. subcommandCStructs :: Mod CommandFields CommandOpts subcommandCStructs = subcommand "structs" (CommandOptsCStructs2Copilot <$> CLI.CommandCStructs2Copilot.commandOptsParser) CLI.CommandCStructs2Copilot.commandDesc -- | Modifier for the msg handler generation subcommand, linking the subcommand -- options and description to the command @handlers@ at top level. subcommandMsgHandlers :: Mod CommandFields CommandOpts subcommandMsgHandlers = subcommand "handlers" (CommandOptsCStructs2MsgHandlers <$> CLI.CommandCStructs2MsgHandlers.commandOptsParser) CLI.CommandCStructs2MsgHandlers.commandDesc -- | Modifier for the CFS app expansion subcommand, linking the subcommand -- options and description to the command @cfs@ at top level. subcommandCFSApp :: Mod CommandFields CommandOpts subcommandCFSApp = subcommand "cfs" (CommandOptsCFSApp <$> CLI.CommandCFSApp.commandOptsParser) CLI.CommandCFSApp.commandDesc -- | Modifier for the ROS app expansion subcommand, linking the subcommand -- options and description to the command @ros@ at top level. subcommandROSApp :: Mod CommandFields CommandOpts subcommandROSApp = subcommand "ros" (CommandOptsROSApp <$> CLI.CommandROSApp.commandOptsParser) CLI.CommandROSApp.commandDesc -- | Modifier for the FPrime app expansion subcommand, linking the subcommand -- options and description to the command @fprime@ at top level. subcommandFPrimeApp :: Mod CommandFields CommandOpts subcommandFPrimeApp = subcommand "fprime" (CommandOptsFPrimeApp <$> CLI.CommandFPrimeApp.commandOptsParser) CLI.CommandFPrimeApp.commandDesc -- | Modifier for the standalone subcommand, linking the subcommand options and -- description to the command @standalone@ at top level. subcommandStandalone :: Mod CommandFields CommandOpts subcommandStandalone = subcommand "standalone" (CommandOptsStandalone <$> CLI.CommandStandalone.commandOptsParser) CLI.CommandStandalone.commandDesc -- | Modifier for the diagram subcommand, linking the subcommand options and -- description to the command @diagram@ at top level. subcommandDiagram :: Mod CommandFields CommandOpts subcommandDiagram = subcommand "diagram" (CommandOptsDiagram <$> CLI.CommandDiagram.commandOptsParser) CLI.CommandDiagram.commandDesc -- * Command dispatcher -- | Command dispatcher that obtains the parameters from the command line and -- passes them as arguments to the actual function that will process them, -- transforming the local result into a global program result. -- This function is implemented as a combination of three processes or -- functions: one that adapts the input to the inner function (down), the -- actual function implementing the command, and a translation of the local -- result into a global result that can be reported to users (up). In this -- case, the commands are all using the same (and compatible) exit codes, but -- they might not do so. This is captured by the fmap of the function id on -- each processing command. -- -- The function that adapts the inputs simply passes the arguments obtained -- from the command line one by one. Composition with this function uncurries -- the next function to work over the product as defined by the record that -- accompanies each command definition in the type OgmaCLICommand. -- -- Neither this nor the internal commands not know, and need to know, that they -- run in CLI. command :: CommandOpts -> IO (Result ErrorCode) command (CommandOptsCFSApp c) = id <$> CLI.CommandCFSApp.command c command (CommandOptsCStructs2Copilot c) = id <$> CLI.CommandCStructs2Copilot.command c command (CommandOptsCStructs2MsgHandlers c) = id <$> CLI.CommandCStructs2MsgHandlers.command c command (CommandOptsFPrimeApp c) = id <$> CLI.CommandFPrimeApp.command c command (CommandOptsOverview c) = id <$> CLI.CommandOverview.command c command (CommandOptsROSApp c) = id <$> CLI.CommandROSApp.command c command (CommandOptsStandalone c) = id <$> CLI.CommandStandalone.command c command (CommandOptsDiagram c) = id <$> CLI.CommandDiagram.command c -- We indicate to HLint that the use of (id <$>) above should not trigger a -- warning. Conceptually, there is a transformation taking place, but no change -- is required because the types used by the internal functions and the -- top-level command to represent results are the same, and the error codes are -- non-overlapping. {-# ANN command "HLint: ignore Functor law" #-} -- * Error codes -- | Encoding of reasons why the command can fail. -- -- The error code used is 1 for user error, 2 for internal bug. type ErrorCode = Int -- * Auxiliary defs -- | Build a subcommand modifier from a command name, option parser and command -- description. subcommand :: String -> Parser CommandOpts -> String -> Mod CommandFields CommandOpts subcommand entry parser desc = OptParse.command entry (info (parser <**> helper) (progDesc desc)) ogma-cli-1.10.0/src/CLI/CommandCStructs2Copilot.hs0000644000000000000000000000443315064246146017702 0ustar0000000000000000-- Copyright 2020 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. -- -- | CLI interface to the CStructs2Copilot subcommand module CLI.CommandCStructs2Copilot ( -- * Direct command access command , CommandOpts , ErrorCode -- * CLI , commandDesc , commandOptsParser ) where -- External imports import Options.Applicative ( Parser, help, long, metavar, strOption ) -- External imports: command results import Command.Result ( Result ) -- External imports: actions or commands supported import Command.CStructs2Copilot ( ErrorCode, cstructs2Copilot ) -- * Command -- | A Copilot correspondence for a C struct can be generated by providing -- the path to the file that declares the struct. newtype CommandOpts = CommandOpts { cstructsFileName :: FilePath } -- | Generate Copilot struct definitions and instances from structs defined in -- a C header file. -- -- This is just an uncurried version of "Command.CStructs2Copilot". command :: CommandOpts -> IO (Result ErrorCode) command c = cstructs2Copilot (cstructsFileName c) -- * CLI -- | Command description for CLI help. commandDesc :: String commandDesc = "Generate Copilot structs from C structs" -- | Subparser for the @structs@ command, used to generate Copilot declarations -- from C structs. commandOptsParser :: Parser CommandOpts commandOptsParser = CommandOpts <$> strOption ( long "header-file-name" <> metavar "FILENAME" <> help strStructsHeaderArgDesc ) -- | Argument C header file to struct conversion command strStructsHeaderArgDesc :: String strStructsHeaderArgDesc = "C header file with struct definitions" ogma-cli-1.10.0/src/CLI/CommandCStructs2MsgHandlers.hs0000644000000000000000000000444015064246146020476 0ustar0000000000000000-- Copyright 2020 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. -- -- | CLI interface to the CStructs2Copilot subcommand module CLI.CommandCStructs2MsgHandlers ( -- * Direct command access command , CommandOpts , ErrorCode -- * CLI , commandDesc , commandOptsParser ) where -- External imports import Options.Applicative ( Parser, help, long, metavar, strOption ) -- External imports: command results import Command.Result ( Result ) -- External imports: actions or commands supported import Command.CStructs2MsgHandlers ( ErrorCode, cstructs2MsgHandlers ) -- * Command -- | Options to generate message handlers from C struct definitions. newtype CommandOpts = CommandOpts { msgHandlersFileName :: FilePath } -- | Generate C methods that process NASA Core Flight System messages dealing -- with the structs defined in a header file. -- -- This is just an uncurried version of "Command.CStructs2MsgHandlers". command :: CommandOpts -> IO (Result ErrorCode) command c = cstructs2MsgHandlers (msgHandlersFileName c) -- * CLI -- | Command description for CLI help. commandDesc :: String commandDesc = "Generate message handlers from C structs" -- | Subparser for the @handlers@ command, used to generate message handers -- from C structs. commandOptsParser :: Parser CommandOpts commandOptsParser = CommandOpts <$> strOption ( long "header-file-name" <> metavar "FILENAME" <> help strMsgHandlersHeaderArgDesc ) -- | Argument C header file to handler generation command strMsgHandlersHeaderArgDesc :: String strMsgHandlersHeaderArgDesc = "C header file with struct definitions" ogma-cli-1.10.0/src/CLI/CommandCFSApp.hs0000644000000000000000000001575415064246146015600 0ustar0000000000000000-- Copyright 2020 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. -- -- | CLI interface to the CFSApp subcommand. module CLI.CommandCFSApp ( -- * Direct command access command , CommandOpts , ErrorCode -- * CLI , commandDesc , commandOptsParser ) where -- External imports import Options.Applicative ( Parser, help, long, metavar, optional, short, showDefault, strOption, value ) -- External imports: command results import Command.Result ( Result ) -- External imports: actions or commands supported import Command.CFSApp ( ErrorCode ) import qualified Command.CFSApp -- * Command -- | Options needed to generate the cFS application. data CommandOpts = CommandOpts { cFSAppConditionExpr :: Maybe String , cFSAppInputFile :: Maybe String , cFSAppTarget :: String , cFSAppTemplateDir :: Maybe String , cFSAppVarNames :: Maybe String , cFSAppVarDB :: Maybe String , cFSAppHandlers :: Maybe String , cFSAppFormat :: String , cFSAppPropFormat :: String , cFSAppPropVia :: Maybe String , cFSAppTemplateVars :: Maybe String } -- | Create (cFS) -- applications that subscribe to the communication bus and call Copilot when -- new messages arrive. -- -- This is just an uncurried version of "Command.CFSApp". command :: CommandOpts -> IO (Result ErrorCode) command c = Command.CFSApp.command options where options = Command.CFSApp.CommandOptions { Command.CFSApp.commandConditionExpr = cFSAppConditionExpr c , Command.CFSApp.commandInputFile = cFSAppInputFile c , Command.CFSApp.commandTargetDir = cFSAppTarget c , Command.CFSApp.commandTemplateDir = cFSAppTemplateDir c , Command.CFSApp.commandVariables = cFSAppVarNames c , Command.CFSApp.commandVariableDB = cFSAppVarDB c , Command.CFSApp.commandHandlers = cFSAppHandlers c , Command.CFSApp.commandFormat = cFSAppFormat c , Command.CFSApp.commandPropFormat = cFSAppPropFormat c , Command.CFSApp.commandPropVia = cFSAppPropVia c , Command.CFSApp.commandExtraVars = cFSAppTemplateVars c } -- * CLI -- | cFS command description commandDesc :: String commandDesc = "Generate a complete cFS/Copilot application" -- | Subparser for the @cfs@ command, used to generate a NASA Core Flight -- System application connected to Copilot monitors. commandOptsParser :: Parser CommandOpts commandOptsParser = CommandOpts <$> optional ( strOption ( long "condition-expr" <> metavar "EXPRESSION" <> help strCFSAppConditionExprArgDesc ) ) <*> optional ( strOption ( long "input-file" <> metavar "FILENAME" <> help strCFSAppFileNameArgDesc ) ) <*> strOption ( long "app-target-dir" <> metavar "DIR" <> showDefault <> value "copilot-cfs-demo" <> help strCFSAppDirArgDesc ) <*> optional ( strOption ( long "app-template-dir" <> metavar "DIR" <> help strCFSAppTemplateDirArgDesc ) ) <*> optional ( strOption ( long "variable-file" <> metavar "FILENAME" <> help strCFSAppVarListArgDesc ) ) <*> optional ( strOption ( long "variable-db" <> metavar "FILENAME" <> help strCFSAppVarDBArgDesc ) ) <*> optional ( strOption ( long "handlers-file" <> metavar "FILENAME" <> help strCFSAppHandlerListArgDesc ) ) <*> strOption ( long "input-format" <> short 'f' <> metavar "FORMAT_NAME" <> help strCFSAppFormatDesc <> showDefault <> value "fcs" ) <*> strOption ( long "prop-format" <> short 'p' <> metavar "FORMAT_NAME" <> help strCFSAppPropFormatDesc <> showDefault <> value "smv" ) <*> optional ( strOption ( long "parse-prop-via" <> metavar "COMMAND" <> help strCFSAppPropViaDesc ) ) <*> optional ( strOption ( long "template-vars" <> metavar "FILENAME" <> help strCFSAppTemplateVarsArgDesc ) ) -- | Argument target directory to cFS app generation command strCFSAppDirArgDesc :: String strCFSAppDirArgDesc = "Target directory" -- | Argument template directory to cFS app generation command strCFSAppTemplateDirArgDesc :: String strCFSAppTemplateDirArgDesc = "Directory holding cFS application source template" -- | Argument expression to CFS app generation command. strCFSAppConditionExprArgDesc :: String strCFSAppConditionExprArgDesc = "Expression used as guard or trigger condition" -- | Argument input file to CFS app generation command strCFSAppFileNameArgDesc :: String strCFSAppFileNameArgDesc = "File containing input specification" -- | Argument variable list to cFS app generation command strCFSAppVarListArgDesc :: String strCFSAppVarListArgDesc = "File containing list of cFS/ICAROUS variables to make accessible" -- | Argument variable database to cFS app generation command strCFSAppVarDBArgDesc :: String strCFSAppVarDBArgDesc = "File containing a DB of known cFS/ICAROUS variables" -- | Argument handler list to cFS app generation command strCFSAppHandlerListArgDesc :: String strCFSAppHandlerListArgDesc = "File containing list of Copilot handlers used in the specification" -- | Format flag description. strCFSAppFormatDesc :: String strCFSAppFormatDesc = "Format of the input file" -- | Property format flag description. strCFSAppPropFormatDesc :: String strCFSAppPropFormatDesc = "Format of temporal or boolean properties" -- | External command to pre-process individual properties. strCFSAppPropViaDesc :: String strCFSAppPropViaDesc = "Command to pre-process individual properties" -- | Argument template variables to cFS app generation command strCFSAppTemplateVarsArgDesc :: String strCFSAppTemplateVarsArgDesc = "JSON file containing additional variables to expand in template" ogma-cli-1.10.0/src/CLI/Result.hs0000644000000000000000000000346215064246146014474 0ustar0000000000000000-- Copyright 2020 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may -- not use this file except in compliance with the License. You may obtain a -- copy of the License at -- -- https://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -- License for the specific language governing permissions and limitations -- under the License. -- -- | Process a result of a command in a way suitable for command-line -- interaction. module CLI.Result where -- External imports import System.Exit ( ExitCode (ExitFailure, ExitSuccess), exitWith ) import System.IO ( hPutStrLn, stderr ) -- External imports: command results import Command.Result ( Result (Error, Success) ) import Data.Location ( Location (..) ) {- HLINT ignore "Use exitSuccess" -} -- | Process a result, report any pending messages, and exit with an error code -- if necessary. processResult :: Result Int -> IO () processResult Success = exitWith ExitSuccess processResult (Error ec msg loc) = do hPutStrLn stderr $ showLocation loc ++ "error: " ++ msg exitWith (ExitFailure ec) where -- | Show locations in a standard way in user messages. showLocation :: Location -> String showLocation LocationNothing = ": " showLocation (LocationFile f) = f ++ ": " showLocation (LocationFileLine f l) = f ++ ":" ++ show l ++ ": " showLocation (LocationFileLC f l c) = f ++ ":" ++ show l ++ ":" ++ show c ++ ": "