diff options
Diffstat (limited to 'main.cxx')
-rw-r--r-- | main.cxx | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/main.cxx b/main.cxx new file mode 100644 index 00000000..94026001 --- /dev/null +++ b/main.cxx @@ -0,0 +1,196 @@ +// systemtap translator driver +// Copyright 2005 Red Hat Inc. +// GPL + +#include "config.h" +#include "staptree.h" +#include "parse.h" +#include "elaborate.h" +#include "translate.h" + +#include <iostream> +#include <fstream> +#include <sstream> + +extern "C" { +#include <glob.h> +#include <unistd.h> +} + +using namespace std; + + + +void usage () +{ + cerr << "Usage: stap [options] FILE [ARGS ...] \tRun script files." << endl; + cerr << " or: stap [options] -e PROGRAM [ARGS ...]\tRun script." << endl; + cerr << endl; + cerr << "Arguments:" << endl; + cerr << " --\tNo more options after this" << endl; + cerr << " -p NUM\tStop after pass NUM 1-3" << endl; + cerr << " \t(parse, elaborate, translate)" << endl; + cerr << " -I DIR\tLook in DIR for additional .stp script files." << endl; + cerr << " -o FILE\tSend translator output to file instead of stdout." << endl; + // XXX: other options: + // -s: safe mode + // -d: dump safety-related external references + + exit (0); +} + + +int +main (int argc, char * const argv []) +{ + int last_pass = 3; // -p NUM + string cmdline_script; // -e PROGRAM + string script_file; // FILE + bool have_script = false; + string output_file; // -o FILE + vector<string> include_path; // -I DIR + vector<string> args; // ARGS + while (true) + { + int grc = getopt (argc, argv, "p:I:e:o:"); + if (grc < 0) + break; + switch (grc) + { + case 'p': + last_pass = atoi (optarg); + if (last_pass < 1 || last_pass > 3) + { + cerr << "Invalid pass number." << endl; + usage (); + } + break; + + case 'I': + include_path.push_back (string (optarg)); + break; + + case 'e': + if (have_script) + usage (); + cmdline_script = string (optarg); + have_script = true; + break; + + case 'o': + if (output_file != "") + usage (); + output_file = string (optarg); + break; + + case '?': + case 'h': + default: + usage (); + } + } + + for (int i = optind; i < argc; i++) + { + if (! have_script) + { + script_file = string (argv[i]); + have_script = true; + } + else + args.push_back (string (argv[i])); + } + + // need a user file + if (! have_script) + usage(); + + // arguments parsed; get down to business + + int rc = 0; + systemtap_session s; + if (output_file != "") + s.op = new translator_output (output_file); + else + s.op = new translator_output (cout); + + + // PASS 1a: PARSING USER SCRIPT + // XXX: pass args vector, so parser (or lexer?) can substitute + // $1..$NN with actual arguments + if (script_file != "") + s.user_file = parser::parse (script_file); + else + { + istringstream ii (cmdline_script); + s.user_file = parser::parse (ii); + } + if (s.user_file == 0) + // syntax errors already printed + rc ++; + + // PASS 1b: PARSING LIBRARY SCRIPTS + for (unsigned i=0; i<include_path.size(); i++) + { + glob_t globbuf; + string dir = include_path[i] + "/*.stp"; + int r = glob(dir.c_str (), 0, NULL, & globbuf); + if (r == GLOB_NOSPACE || r == GLOB_ABORTED) + rc ++; + // GLOB_NOMATCH is acceptable + + for (unsigned j=0; j<globbuf.gl_pathc; j++) + { + stapfile* f = parser::parse (globbuf.gl_pathv[j]); + if (f == 0) + rc ++; + else + s.library_files.push_back (f); + } + + globfree (& globbuf); + } + + if (last_pass == 1 && rc == 0) + { + s.op->line() << "# parse tree dump"; + s.user_file->print (s.op->newline()); + for (unsigned i=0; i<s.library_files.size(); i++) + s.library_files[i]->print (s.op->newline()); + } + + // PASS 2: ELABORATION + if (rc == 0 && last_pass > 1) + rc = semantic_pass (s); + if (last_pass == 2 && rc == 0) + { + s.op->line() << "# globals"; + for (unsigned i=0; i<s.globals.size(); i++) + { + vardecl* v = s.globals[i]; + v->printsig (s.op->newline()); + } + + s.op->newline() << "# functions"; + for (unsigned i=0; i<s.functions.size(); i++) + { + functiondecl* f = s.functions[i]; + f->printsig (s.op->newline()); + } + + s.op->newline() << "# probes"; + for (unsigned i=0; i<s.probes.size(); i++) + { + derived_probe* p = s.probes[i]; + p->printsig (s.op->newline()); + } + } + + // PASS 3: TRANSLATION + if (rc == 0 && last_pass > 2) + rc = translate_pass (s); + + delete s.op; + + return rc; +} |