| 1 | /*
 | 
| 2 |  * Souffle - A Datalog Compiler
 | 
| 3 |  * Copyright (c) 2016, The Souffle Developers. 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 | #pragma once
 | 
| 10 | 
 | 
| 11 | #include "souffle/profile/StringUtils.h"
 | 
| 12 | #include "souffle/profile/Tui.h"
 | 
| 13 | 
 | 
| 14 | #include <iostream>
 | 
| 15 | #include <map>
 | 
| 16 | #include <string>
 | 
| 17 | #include <vector>
 | 
| 18 | 
 | 
| 19 | #ifdef USE_CUSTOM_GETOPTLONG
 | 
| 20 | #include "souffle/utility/GetOptLongImpl.h"
 | 
| 21 | #else
 | 
| 22 | #include <getopt.h>
 | 
| 23 | #endif
 | 
| 24 | 
 | 
| 25 | namespace souffle {
 | 
| 26 | namespace profile {
 | 
| 27 | 
 | 
| 28 | /*
 | 
| 29 |  * CLI to parse command line arguments and start up the TUI to either run a single command,
 | 
| 30 |  * generate the GUI file or run the TUI
 | 
| 31 |  */
 | 
| 32 | class Cli {
 | 
| 33 | public:
 | 
| 34 |     std::map<char, std::string> args;
 | 
| 35 | 
 | 
| 36 |     Cli(int argc, char* argv[]) : args() {
 | 
| 37 |         int c;
 | 
| 38 |         option longOptions[1];
 | 
| 39 |         longOptions[0] = {nullptr, 0, nullptr, 0};
 | 
| 40 |         while ((c = getopt_long(argc, argv, "c:hj::", longOptions, nullptr)) != EOF) {
 | 
| 41 |             // An invalid argument was given
 | 
| 42 |             if (c == '?') {
 | 
| 43 |                 exit(EXIT_FAILURE);
 | 
| 44 |             }
 | 
| 45 |             if (optarg != nullptr) {
 | 
| 46 |                 if (*optarg == '=') {
 | 
| 47 |                     args[c] = optarg + 1;
 | 
| 48 |                 } else {
 | 
| 49 |                     args[c] = optarg;
 | 
| 50 |                 }
 | 
| 51 |             } else {
 | 
| 52 |                 args[c] = c;
 | 
| 53 |             }
 | 
| 54 |         }
 | 
| 55 |         if (optind < argc && args.count('f') == 0) {
 | 
| 56 |             args['f'] = argv[optind];
 | 
| 57 |         }
 | 
| 58 |     }
 | 
| 59 | 
 | 
| 60 |     int parse() {
 | 
| 61 |         if (args.size() == 0) {
 | 
| 62 |             std::cout << "No arguments provided.\nTry souffleprof -h for help.\n";
 | 
| 63 |             return (EXIT_FAILURE);
 | 
| 64 |         }
 | 
| 65 | 
 | 
| 66 |         if (args.count('h') != 0 || args.count('f') == 0) {
 | 
| 67 |             std::cout << "Souffle Profiler" << std::endl
 | 
| 68 |                       << "Usage: souffle-profile <log-file> [ -h | -c <command> [options] | -j ]" << std::endl
 | 
| 69 |                       << "<log-file>            The log file to profile." << std::endl
 | 
| 70 |                       << "-c <command>          Run the given command on the log file, try with  "
 | 
| 71 |                          "'-c help' for a list"
 | 
| 72 |                       << std::endl
 | 
| 73 |                       << "                      of commands." << std::endl
 | 
| 74 |                       << "-j[filename]          Generate a GUI (html/js) version of the profiler."
 | 
| 75 |                       << std::endl
 | 
| 76 |                       << "                      Default filename is profiler_html/[num].html" << std::endl
 | 
| 77 |                       << "-h                    Print this help message." << std::endl;
 | 
| 78 |             return (0);
 | 
| 79 |         }
 | 
| 80 |         std::string filename = args['f'];
 | 
| 81 | 
 | 
| 82 |         if (args.count('c') != 0) {
 | 
| 83 |             Tui tui(filename, false, false);
 | 
| 84 |             for (auto& command : Tools::split(args['c'], ";")) {
 | 
| 85 |                 tui.runCommand(Tools::split(command, " "));
 | 
| 86 |             }
 | 
| 87 |         } else if (args.count('j') != 0) {
 | 
| 88 |             if (args['j'] == "j") {
 | 
| 89 |                 return Tui(filename, false, true).outputHtml();
 | 
| 90 |             } else {
 | 
| 91 |                 return Tui(filename, false, true).outputHtml(args['j']);
 | 
| 92 |             }
 | 
| 93 |         } else {
 | 
| 94 |             Tui(filename, true, false).runProf();
 | 
| 95 |         }
 | 
| 96 | 
 | 
| 97 |         return 0;
 | 
| 98 |     }
 | 
| 99 | };
 | 
| 100 | 
 | 
| 101 | }  // namespace profile
 | 
| 102 | }  // namespace souffle
 |