/* G-Cows - scripting language for creation of web sites Copyright (C) 2002, 2003, 2004, 2005, 2006 Andrea Sozzi This file is part of G-Cows. G-Cows is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. G-Cows is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "cows-mkgen_options.H" #include #include // #include #include #include "utils.H" #include "file_utils.H" #include "error.H" #if HAVE_GETOPT_LONG # include #else /* ! HAVE_GETOPT_LONG */ # include #endif using namespace std; string yytmpllval; typedef std::vector string_cont; typedef string_cont::iterator string_iter; extern FILE *yytmplin; extern int yytmpllex (); Mkgen_opt::Mkgen_opt (int argc, char *argv[]) { int parsed_opt; int exit_mode, verbosity; bool set_never_exit = false, set_exit_on_warning = false; bool set_silent = false, set_verbose = false; string prefix, root, source_extension, target_extension; #if HAVE_GETOPT_LONG static struct option const options[] = { { "accessibility", no_argument, NULL, 'A' }, { "brief", no_argument, NULL, 'b' }, { "root-dir", required_argument, NULL, 'd' }, { "fatal-warnings", no_argument, NULL, 'E' }, { "fast", no_argument, NULL, 'f' }, { "help", no_argument, NULL, 'h' }, { "ignore-errors", no_argument, NULL, 'i' }, { "cows-option", required_argument, NULL, 'O' }, { "prefix", required_argument, NULL, 'p' }, { "quiet", no_argument, NULL, 'q' }, { "source-extension", required_argument, NULL, 'S' }, { "silent", no_argument, NULL, 's' }, { "target-extension", required_argument, NULL, 't' }, { "version", no_argument, NULL, 'V' }, { "verbose", no_argument, NULL, 'v' }, {NULL, 0, NULL, 0} }; #endif Msg::inst()->set_program_name (argv[0]); program_name = argv[0]; /* Set some default values; they will be overwritten by command line options and template file */ exit_mode = Msg::exit_on_error; verbosity = Msg::standard; set_opt (Mkgen_opt::o_root_dir, "./" ); set_opt (Mkgen_opt::o_prefix, "./" ); set_opt (Mkgen_opt::o_source_extension, "cws" ); set_opt (Mkgen_opt::o_target_extension, "html" ); set_opt (Mkgen_opt::o_output, "Makefile"); set_opt (Mkgen_opt::o_fast_mode, "n" ); // Parse command line options #if HAVE_GETOPT_LONG while ((parsed_opt = getopt_long (argc, argv, "Ad:O:p:qS:st:EvbhiV", options, NULL)) != -1) #else /* ! HAVE_GETOPT_LONG */ while ((parsed_opt = getopt (argc, argv, "Ad:O:p:qS:st:EvbhiV")) != -1) #endif { switch (parsed_opt) { case 0: break; case 'A': accessibility (); break; case 'b': Msg::inst()->set_brief (true); break; case 'd': root = string (optarg); break; case 'f': set_opt (Mkgen_opt::o_fast_mode, "y"); break; case 'h': usage (EXIT_SUCCESS); break; case 'i': set_never_exit = true; exit_mode = Msg::never_exit; break; case 'q': case 's': verbosity = Msg::silent; set_silent = true; break; case 'O': add_opt (Mkgen_opt::o_cows_option, " " + string (optarg) + " " ); break; case 'E': set_exit_on_warning = true; exit_mode = Msg::exit_on_warning; break; case 'p': prefix = string (optarg); break; case 'S': source_extension = string (optarg); break; case 't': target_extension = string (optarg); break; case 'v': verbosity = Msg::verbose; set_verbose = true; break; case 'V': version (); break; default: usage (EXIT_FAILURE); } } if (set_verbose && set_silent) Msg::inst()->fatal ("incompatible options `verbose' and `silent'"); if (set_never_exit && set_exit_on_warning) Msg::inst()->fatal ( "incompatible options `fatal-warnings' and `ignore-errors'"); /* We have some knowledge about what user want so we set these preferences We'll override them after parsing */ Msg::inst()->set_verbosity (verbosity); Msg::inst()->set_exit_mode (exit_mode); if (argc - optind > 1) usage (EXIT_FAILURE); if (argc - optind == 1) { string out = opt_file_name (argv [optind]); if (out.find ("/") != string::npos) Msg::inst()->fatal ("makefile must be created within current directory"); set_opt (Mkgen_opt::o_output, argv [optind]); } // template file set_never_exit = set_exit_on_warning = false; set_silent = set_verbose = false; string template_name = add_slash (root) + get_opt (Mkgen_opt::o_output) + ".cm"; FILE *template_file = fopen (template_name.c_str(), "r"); string languages; if ( template_file ) { yytmplin = template_file; int token_type; while ((token_type = yytmpllex ())) { switch (token_type) { case Mkgen_opt::brief: Msg::inst()->set_brief (true); break; case Mkgen_opt::fatal_warnings: set_exit_on_warning = true; if (exit_mode == Msg::exit_on_error) exit_mode = Msg::exit_on_warning; break; case Mkgen_opt::fast: set_opt (Mkgen_opt::o_fast_mode, "y"); break; case Mkgen_opt::ignore_errors: set_never_exit = true; if (exit_mode == Msg::exit_on_error) exit_mode = Msg::never_exit; break; case Mkgen_opt::quiet: case Mkgen_opt::silent: set_silent = true; if (verbosity == Msg::standard) verbosity = Msg::silent; break; case Mkgen_opt::verbose: set_verbose = true; if (verbosity == Msg::standard) verbosity = Msg::verbose; break; case Mkgen_opt::prefix: if (prefix == "") prefix = string (yytmpllval); break; case Mkgen_opt::source: if (source_extension == "") source_extension = string (yytmpllval); break; case Mkgen_opt::target: if (target_extension == "") target_extension = string (yytmpllval); break; case Mkgen_opt::option: add_opt (Mkgen_opt::o_cows_option, " " + string(yytmpllval) + " "); break; case Mkgen_opt::new_branch: create_branch (yytmpllval); break; case Mkgen_opt::main_site: set_opt (Mkgen_opt::o_branch_option, yytmpllval); break; case Mkgen_opt::lang: languages = string (yytmpllval); break; } } fclose (template_file); } else { if ( errno == ENOENT) Msg::inst()->opt ("template file not found", "no template"); else Msg::inst()->sys_error ("can't open template file " + template_name, template_name); } if ( set_verbose && set_silent ) Msg::inst()->fatal ("template: both `verbose' and `silent' set"); if (set_never_exit && set_exit_on_warning) Msg::inst()->fatal ("template: both `fatal-warnings' and `ignore-errors' set"); Msg::inst()->set_verbosity (verbosity); Msg::inst()->set_exit_mode (exit_mode); /* IMPORTANT: if both prefix and root-dir have been specified, the former must be passed to Cows as its root directory */ string root_for_cows; if ( (root != "") && (root != ".") && (root != "./") ) { // User choose a root directory root = add_slash (root); set_opt (Mkgen_opt::o_root_dir, opt_file_name (root)); root_for_cows = opt_file_name (root); } if ( (prefix != "") && (prefix != ".") && (prefix != "./") ) { // User choose a prefix prefix = add_slash (prefix); set_opt (Mkgen_opt::o_prefix, opt_file_name (prefix)); root_for_cows = opt_file_name (prefix); } if (root_for_cows != "") add_opt (Mkgen_opt::o_cows_option, " -p -d " + root_for_cows + " "); if (source_extension != "") set_opt (Mkgen_opt::o_source_extension, source_extension); if (target_extension != "") set_opt (Mkgen_opt::o_target_extension, target_extension); set_opt (Mkgen_opt::o_branch_id, "main_OPTS"); translations.push_back (""); if (languages != "") { int beg_tok = 0; int sep_pos = -1; while ((sep_pos = languages.find (",", sep_pos + 1)) !=(int)string::npos) { translations.push_back (Utils::trim (languages.substr (beg_tok, sep_pos - beg_tok))); beg_tok = sep_pos + 1; } if (beg_tok) translations.push_back (Utils::trim (languages.substr (beg_tok, sep_pos - beg_tok))); else if (Utils::trim (languages) != "") translations.push_back (Utils::trim (languages)); } } void Mkgen_opt::create_src_file (string buffer) { string sources_name = get_opt (Mkgen_opt::o_output) + ".sources"; ofstream sources_stream (sources_name.c_str()); if ( ! sources_stream ) Msg::inst()->fatal ("Can't open sources file " + sources_name, sources_name); sources_stream << buffer << "\n"; sources_stream.close (); } /* void Mkgen_opt::create_makefile (string boilerplate, const char *dependencies, string epilogue) { string output_name = get_opt (Mkgen_opt::o_output); ofstream output_stream (output_name.c_str()); if ( ! output_stream ) Msg::inst()->fatal ("Can't open output file " + output_name, output_name); output_stream << boilerplate << "\n\n" << dependencies << "\n\n" << epilogue << endl; output_stream.close (); } */ void Mkgen_opt::create_empty_makefile () { string output_name = get_opt (Mkgen_opt::o_output); ofstream output_stream (output_name.c_str()); if ( ! output_stream ) Msg::inst()->fatal ("Can't open output file " + output_name, output_name); output_stream.close (); } void Mkgen_opt::create_branch (string desc) { int first = desc.find ("*"); int second = desc.find ("*", first + 1); Branch_options * opts = new Branch_options (desc.substr (0, first), desc.substr (first + 1, second - first - 1), desc.substr (second + 1, desc.length () - second - 1)); if (opts) branches.push_back (*opts); } bool Mkgen_opt::next_branch () { if ( branches.empty () ) return false; branches_iter iter = branches.end (); set_opt (Mkgen_opt::o_branch_root, (*(--iter)).root); string branch_id = (*(iter)).prefix; if (branch_id.at (branch_id.length () -1) == '/') branch_id = branch_id.substr (0, branch_id.length() - 1); set_opt (Mkgen_opt::o_branch_id, branch_id + "_OPTS"); set_opt (Mkgen_opt::o_branch_prefix, (*(iter)).prefix); set_opt (Mkgen_opt::o_branch_option, (*(iter)).cows_options); branches.erase (iter); return true; } void Mkgen_opt::usage (int status) { if (status != 0) { cerr << "Usage: " << program_name << " [OPTION] ... [Makefile]\n"; cerr << "Try `" << program_name << " --help' for more information.\n"; } else { cout << "Usage: " << program_name << " [OPTION] ... [Makefile]\n"; cout << "\ Generate makefiles for Cows.\n\n\ -A, --accessibility Display informations about accessibility issues\n\ related to Cows\n\ -b, --brief Display output in a compact format. The amount\n\ of messages won't change, they will only be\n\ shorter. Visually impaired users relying on a\n\ speech version of shell's output may find this\n\ flag useful since large amounts of output can\n\ slow down work. \n\ -d, --root-dir=DIRECTORY Set site's root directory; Cows-mkgen will look\n\ for Cows sources within this directory and \n\ its subdirectories. \n\ -E, --fatal-warnings Stop execution after first warning (default \n\ behavior is to give an advice and continue \n\ running).\n\ -f, --fast Use 'fast' scanning mode: cows-mkgen will be \n\ significantly faster. NOTE: this mode requires\n\ some precautions. SIMPLY USING THE '--fast' \n\ FLAG ON PREEXISTING PROJECTS CAN LEAD TO WRONG\n\ MAKEFILES. Read the documentation for details.\n\ -h, --help Display help message and exit. \n\ -i, --ignore-errors Keep running after errors. \n\ -O, --cows-option=OPTION When creating makefile, add OPTION to Cows\n\ command-line options. \n\ -p, --prefix=DIRECTORY Makefile is created so that output files will \n\ be created within DIRECTORY. \n\ -q, --quiet Same as `--silent' \n\ -S, --source-extension=EXTENSION Set the extension for input files; \n\ by default Cows-mkgen looks for files \n\ with `.cws' extension. \n\ -s, --silent Don't print informational messages \n\ -t, --target-extension=EXTENSION Set the extension for output files; \n\ by default the generated makefile creates\n\ output files with extension `.html'. \n\ -V, --version Display the version number of Cows-mkgen and\n\ exit.\n\ -v, --verbose Produce a more verbose description. \n\n\ Cows: n. pl. pl. of cow.\n\ domesticated mammals of the genus Bos, often raised for meat and dairy\n\ products; it's obviously a bad habit, since killing living beings for\n\ eating or wearing is __WRONG__\n\ Cows-mkgen: utility that examines a directory tree looking for Cows sources,\n\ parses them and automatically generates a makefile for easy \n\ site updating.\n\n\ Both Cows (cows --help for further informations) and Cows-mkgen come with \n\ the package `G-Cows'. See http://www.g-cows.org/ for documentation and \n\ latest release.\n\n\ Please report bugs to .\n\ "; } exit (status); } void Mkgen_opt::version () { cout << "Cows-mkgen for Cows version " << VERSION << "\n\ Copyright (C) 2002, 2003, 2004, 2005, 2006 Andrea Sozzi \n\ Cows-mkgen comes with ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY\n\ or FITNESS FOR A PARTICULAR PURPOSE.\n\ You may redistribute copies of Cows-mkgen under the terms of the \n\ GNU General Public License. \n\ For more information about these matters, see the files named COPYING. \n\ "; exit (EXIT_SUCCESS); } void Mkgen_opt::accessibility () { cout << "\ Cows-mkgen is a command line tool and its output is not visually formatted\n\ with ASCII characters so accessibility problems should be minimal.\n\ The --brief option forces Cows-mkgen to display output in a compact format.\n\ amount of messages won't change, they will only be shorter. Visually\n\ impaired users relying on a speech version of shell's output may find this\n\ flag useful since large amounts of output can slow down work. \n\ Also remember that when building your site with Make, you can use `make -s'\n\ instead of `make': the former won't print the commands as they are executed\n\ reducing the amount of output on your screen.\n\ "; exit (EXIT_SUCCESS); }