OILS / vendor / souffle / CompiledOptions.h View on Github | oilshell.org

270 lines, 133 significant
1/*
2 * Souffle - A Datalog Compiler
3 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved
4 * Licensed under the Universal Permissive License v 1.0 as shown at:
5 * - https://opensource.org/licenses/UPL
6 * - <souffle root>/licenses/SOUFFLE-UPL.txt
7 */
8
9/************************************************************************
10 *
11 * @file CompiledOptions.h
12 *
13 * A header file offering command-line option support for compiled
14 * RAM programs.
15 *
16 ***********************************************************************/
17
18#pragma once
19
20#include <cstdio>
21#include <cstdlib>
22#include <iostream>
23#include <string>
24#include <sys/stat.h>
25
26#ifdef USE_CUSTOM_GETOPTLONG
27#include "souffle/utility/GetOptLongImpl.h"
28#else
29#include <getopt.h>
30#endif
31
32namespace souffle {
33
34/**
35 * A utility class for parsing command line arguments within generated
36 * query programs.
37 */
38class CmdOptions {
39protected:
40 /**
41 * source file
42 */
43 std::string src;
44
45 /**
46 * fact directory
47 */
48 std::string input_dir;
49
50 /**
51 * output directory
52 */
53 std::string output_dir;
54
55 /**
56 * profiling flag
57 */
58 bool profiling;
59
60 /**
61 * profile filename
62 */
63 std::string profile_name;
64
65 /**
66 * number of threads
67 */
68 std::size_t num_jobs;
69
70public:
71 // all argument constructor
72 CmdOptions(const char* s, const char* id, const char* od, bool pe, const char* pfn, std::size_t nj)
73 : src(s), input_dir(id), output_dir(od), profiling(pe), profile_name(pfn), num_jobs(nj) {}
74
75 /**
76 * get source code name
77 */
78 const std::string& getSourceFileName() const {
79 return src;
80 }
81
82 /**
83 * get input directory
84 */
85 const std::string& getInputFileDir() const {
86 return input_dir;
87 }
88
89 /**
90 * get output directory
91 */
92 const std::string& getOutputFileDir() const {
93 return output_dir;
94 }
95
96 /**
97 * is profiling switched on
98 */
99 bool isProfiling() const {
100 return profiling;
101 }
102
103 /**
104 * get filename of profile
105 */
106 const std::string& getProfileName() const {
107 return profile_name;
108 }
109
110 /**
111 * get number of jobs
112 */
113 std::size_t getNumJobs() const {
114 return num_jobs;
115 }
116
117 /**
118 * Parses the given command line parameters, handles -h help requests or errors
119 * and returns whether the parsing was successful or not.
120 */
121 bool parse(int argc, char** argv) {
122 // get executable name
123 std::string exec_name = "analysis";
124 if (argc > 0) {
125 exec_name = argv[0];
126 }
127
128 // local options
129 std::string fact_dir = input_dir;
130 std::string out_dir = output_dir;
131
132 // long options
133 option longOptions[] = {{"facts", true, nullptr, 'F'}, {"output", true, nullptr, 'D'},
134 {"profile", true, nullptr, 'p'}, {"jobs", true, nullptr, 'j'}, {"index", true, nullptr, 'i'},
135 // the terminal option -- needs to be null
136 {nullptr, false, nullptr, 0}};
137
138 // check whether all options are fine
139 bool ok = true;
140
141 int c; /* command-line arguments processing */
142 while ((c = getopt_long(argc, argv, "D:F:hp:j:i:", longOptions, nullptr)) != EOF) {
143 switch (c) {
144 /* Fact directories */
145 case 'F':
146 if (!existDir(optarg)) {
147 printf("Fact directory %s does not exists!\n", optarg);
148 ok = false;
149 }
150 fact_dir = optarg;
151 break;
152 /* Output directory for resulting .csv files */
153 case 'D':
154 if (*optarg && !existDir(optarg) && !dirIsStdout(optarg)) {
155 printf("Output directory %s does not exists!\n", optarg);
156 ok = false;
157 }
158 out_dir = optarg;
159 break;
160 case 'p':
161 if (!profiling) {
162 std::cerr << "\nError: profiling was not enabled in compilation\n\n";
163 printHelpPage(exec_name);
164 exit(EXIT_FAILURE);
165 }
166 profile_name = optarg;
167 break;
168 case 'j':
169#ifdef _OPENMP
170 if (std::string(optarg) == "auto") {
171 num_jobs = 0;
172 } else {
173 int num = atoi(optarg);
174 if (num > 0) {
175 num_jobs = num;
176 } else {
177 std::cerr << "Invalid number of jobs [-j]: " << optarg << "\n";
178 ok = false;
179 }
180 }
181#else
182 std::cerr << "\nWarning: OpenMP was not enabled in compilation\n\n";
183#endif
184 break;
185 default: printHelpPage(exec_name); return false;
186 }
187 }
188
189 // update member fields
190 input_dir = fact_dir;
191 output_dir = out_dir;
192
193 // return success state
194 return ok;
195 }
196
197private:
198 /**
199 * Prints the help page if it has been requested or there was a typo in the command line arguments.
200 */
201 void printHelpPage(const std::string& exec_name) const {
202 std::cerr << "====================================================================\n";
203 std::cerr << " Datalog Program: " << src << "\n";
204 std::cerr << " Usage: " << exec_name << " [OPTION]\n\n";
205 std::cerr << " Options:\n";
206 std::cerr << " -D <DIR>, --output=<DIR> -- Specify directory for output relations\n";
207 std::cerr << " (default: " << output_dir << ")\n";
208 std::cerr << " (suppress output with \"\")\n";
209 std::cerr << " -F <DIR>, --facts=<DIR> -- Specify directory for fact files\n";
210 std::cerr << " (default: " << input_dir << ")\n";
211 if (profiling) {
212 std::cerr << " -p <file>, --profile=<file> -- Specify filename for profiling\n";
213 std::cerr << " (default: " << profile_name << ")\n";
214 }
215#ifdef _OPENMP
216 std::cerr << " -j <NUM>, --jobs=<NUM> -- Specify number of threads\n";
217 if (num_jobs > 0) {
218 std::cerr << " (default: " << num_jobs << ")\n";
219 } else {
220 std::cerr << " (default: auto)\n";
221 }
222#endif
223 std::cerr << " -h -- prints this help page.\n";
224 std::cerr << "--------------------------------------------------------------------\n";
225#ifdef SOUFFLE_GENERATOR_VERSION
226 std::cerr << " Version: " << SOUFFLE_GENERATOR_VERSION << std::endl;
227#endif
228 std::cerr << " Word size: " << RAM_DOMAIN_SIZE << " bits" << std::endl;
229 std::cerr << "--------------------------------------------------------------------\n";
230 std::cerr << " Copyright (c) 2016-22 The Souffle Developers." << std::endl;
231 std::cerr << " Copyright (c) 2013-16 Oracle and/or its affiliates." << std::endl;
232 std::cerr << " All rights reserved.\n";
233 std::cerr << "====================================================================\n";
234 }
235
236 /**
237 * Check whether a file exists in the file system
238 */
239 inline bool existFile(const std::string& name) const {
240 struct stat buffer;
241 if (stat(name.c_str(), &buffer) == 0) {
242 if ((buffer.st_mode & S_IFREG) != 0) {
243 return true;
244 }
245 }
246 return false;
247 }
248
249 /**
250 * Check whether a directory exists in the file system
251 */
252 bool existDir(const std::string& name) const {
253 struct stat buffer;
254 if (stat(name.c_str(), &buffer) == 0) {
255 if ((buffer.st_mode & S_IFDIR) != 0) {
256 return true;
257 }
258 }
259 return false;
260 }
261
262 /**
263 * Check whether the output is "-", for which the output should be stdout
264 */
265 bool dirIsStdout(const std::string& name) const {
266 return name == "-";
267 }
268};
269
270} // end of namespace souffle