// systemtap translator driver // Copyright (C) 2005 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #include "config.h" #include "staptree.h" #include "parse.h" #include "elaborate.h" #include "translate.h" #include #include #include extern "C" { #include #include } using namespace std; bool verbose = false; void usage () { cerr << "SystemTap translator " << "(version " << VERSION << " built " << DATE << ")" << endl; cerr << "Copyright (C) 2005 Red Hat, Inc." << endl; cerr << "This is free software; see the source for copying conditions." << endl; cerr << endl; cerr << "Usage: stap [options] FILE [ARGS ...] Run script in file." << endl; cerr << " or: stap [options] - [ARGS ...] Run script on stdin." << endl; cerr << " or: stap [options] -e SCRIPT [ARGS ...] Run given script." << endl; cerr << endl; cerr << "Arguments:" << endl; cerr << " -- No more options after this" << endl; cerr << " -v verbose" << endl; cerr << " -p NUM Stop after pass NUM 1-3" << endl; cerr << " (parse, elaborate, translate)" << endl; cerr << " -I DIR Look in DIR for additional .stp script files." << endl; cerr << " -o FILE Send 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 include_path; // -I DIR vector args; // ARGS while (true) { int grc = getopt (argc, argv, "vp:I:e:o:"); if (grc < 0) break; switch (grc) { case 'v': verbose = true; break; 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 (cin); else 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; iline() << "# parse tree dump"; s.user_file->print (s.op->newline()); for (unsigned i=0; iprint (s.op->newline()); } // PASS 2: ELABORATION if (rc == 0 && last_pass > 1) rc = semantic_pass (s); if (last_pass == 2 && rc == 0) { if (s.globals.size() > 0) s.op->line() << "# globals"; for (unsigned i=0; iprintsig (s.op->newline()); } if (s.functions.size() > 0) s.op->newline() << "# functions"; for (unsigned i=0; iprintsig (s.op->newline()); s.op->indent(1); if (f->locals.size() > 0) s.op->newline(1) << "# locals"; for (unsigned j=0; jlocals.size(); j++) { vardecl* v = f->locals[j]; v->printsig (s.op->newline()); } s.op->indent(-1); } if (s.probes.size() > 0) s.op->newline() << "# probes"; for (unsigned i=0; iprintsig (s.op->newline()); s.op->indent(1); if (p->locals.size() > 0) s.op->newline() << "# locals"; for (unsigned j=0; jlocals.size(); j++) { vardecl* v = p->locals[j]; v->printsig (s.op->newline()); } s.op->indent(-1); } s.op->newline(); } // PASS 3: TRANSLATION if (rc == 0 && last_pass > 2) rc = translate_pass (s); s.op->line() << endl; delete s.op; return rc; }