LCOV - code coverage report
Current view: top level - src - csspp.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 88 156 56.4 %
Date: 2023-11-01 21:56:19 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // This program is free software; you can redistribute it and/or modify
       4             : // it under the terms of the GNU General Public License as published by
       5             : // the Free Software Foundation; either version 2 of the License, or
       6             : // (at your option) any later version.
       7             : //
       8             : // This program is distributed in the hope that it will be useful,
       9             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      10             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      11             : // GNU General Public License for more details.
      12             : //
      13             : // You should have received a copy of the GNU General Public License along
      14             : // with this program; if not, write to the Free Software Foundation, Inc.,
      15             : // 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      16             : 
      17             : /** \file
      18             :  * \brief Implementation of the CSS Preprocessor command line tool.
      19             :  * \tableofcontents
      20             :  *
      21             :  * This tool can be used as a verification, compilation, and compression
      22             :  * tool depending on your needs.
      23             :  *
      24             :  * The Snap! Websites environment uses the tool for verification when
      25             :  * generating a layout. Later a Snap! Website plugin compresses the various
      26             :  * files. That way the website system includes the original file and not
      27             :  * just the minimized version.
      28             :  *
      29             :  * \section csspp-options Command Line Options
      30             :  *
      31             :  * The following are the options currently supported by csspp:
      32             :  *
      33             :  * \subsection arguments --args or -a -- specifying arguments
      34             :  *
      35             :  * The SCSS scripts expect some variables to be set. Some of these variables
      36             :  * can be set on the command line with the --args option. The arguments are
      37             :  * added to an array that can be accessed as the variable $_csspp_args.
      38             :  *
      39             :  * \code
      40             :  *      // command line
      41             :  *      csspp --args red -- my-file.scss
      42             :  *
      43             :  *      // reference to the command line argument
      44             :  *      .flowers
      45             :  *      {
      46             :  *          border: 1px solid rgb(identifier($_csspp_args[1]));
      47             :  *      }
      48             :  * \endcode
      49             :  *
      50             :  * \warning
      51             :  * This example does not work yet because I did not yet implement the
      52             :  * rgb() internal function to transform input in a COLOR token. However,
      53             :  * I intend to work on the colors soonish and thus it could be fully
      54             :  * functional by the time you read the example.
      55             :  *
      56             :  * At this time there is no other way to access command line arguments.
      57             :  *
      58             :  * There is no $_csspp_args[0] since arrays in SCSS start at 1. This
      59             :  * also means you do not (yet) have access to the name of the program
      60             :  * compiling the code.
      61             :  *
      62             :  * Multiple arguments can be specified one after another:
      63             :  *
      64             :  * \code
      65             :  *      csspp --args red green blue -- my-file.css
      66             :  * \endcode
      67             :  *
      68             :  * \subsection debug --debug or -d -- show all messages, including @debug messages
      69             :  *
      70             :  * When specified, the error output is setup to output everything,
      71             :  * including fatal errors, errors, warnings, informational messages,
      72             :  * and debug messages.
      73             :  *
      74             :  * \subsection help --help or -h -- show the available command line options
      75             :  *
      76             :  * The --help command line option can be used to request that the csspp
      77             :  * print out the complete list of supported command line options in
      78             :  * stdout.
      79             :  *
      80             :  * The tool then quits immediately.
      81             :  *
      82             :  * \subsection include -I -- specify paths to include files
      83             :  *
      84             :  * Specify paths to user defined directories that include SCSS scripts
      85             :  * one can include using the @import command.
      86             :  *
      87             :  * By default the system looks for system defined scripts (i.e. the
      88             :  * default validation, version, and other similar scripts) under
      89             :  * the following directory:
      90             :  *
      91             :  * \code
      92             :  *      /usr/lib/csspp/scripts
      93             :  * \endcode
      94             :  *
      95             :  * The system scripts (initialization, closure, version) appear under
      96             :  * a sub-directory named "system".
      97             :  *
      98             :  * The validation scripts (field names, pseudo names, etc.) appear
      99             :  * under a sub-directory named "validation".
     100             :  *
     101             :  * There are no specific rules for where include files will be found.
     102             :  * The @import can use a full path or a local path. When a local path
     103             :  * is used, then all the specified -I paths are prepended until a
     104             :  * file matches. The first match is used.
     105             :  *
     106             :  * You may specify any number of include paths one after another. You
     107             :  * must specify -I only once:
     108             :  *
     109             :  * \code
     110             :  *      csspp ... -I my-scripts alfred-scripts extension-scripts ...
     111             :  * \endcode
     112             :  *
     113             :  * \subsection no_logo --no-logo -- hide the "logo"
     114             :  *
     115             :  * This option prevents the "logo" comment from being added at the end
     116             :  * of the output.
     117             :  *
     118             :  * \subsection output --output or -o -- specify the output
     119             :  *
     120             :  * This option may be used to specify a filename used to save the
     121             :  * output of the compiler. By default the output is written to
     122             :  * stdout.
     123             :  *
     124             :  * You may explicitly use '-' to write the output to stdout.
     125             :  *
     126             :  * \code
     127             :  *      csspp --output file.css my-script.scss
     128             :  * \endcode
     129             :  *
     130             :  * \subsection precision --precision or -p -- specify the precision to use with decimal number
     131             :  *
     132             :  * The output is written as consice as possible. Only that can cause problems
     133             :  * with decimal numbers getting written with less precision than you need.
     134             :  *
     135             :  * By default decimal numbers are written with 3 decimal numbers after the
     136             :  * decimal point. You may use the --precision command line option to change
     137             :  * that default to another value.
     138             :  *
     139             :  * \code
     140             :  *      csspp ... --precision 5 ...
     141             :  * \endcode
     142             :  *
     143             :  * Note that numbers such as 3.5 are not written with ending zeroes (i.e.
     144             :  * 3.50000) even if you increase precision.
     145             :  *
     146             :  * \warning
     147             :  * The percent numbers, which are also decimal numbers, do not take this
     148             :  * value in account. All percent numbers are always written with 2 decimal
     149             :  * digits after the decimal point. We may change that behavior in the
     150             :  * future if someone sees a need for it.
     151             :  *
     152             :  * \subsection quiet --quiet or -q -- make the output as quite as possible
     153             :  *
     154             :  * By default csspp prints out all messages except debug messages.
     155             :  *
     156             :  * This option also turns off informational and warning messages. So in
     157             :  * effect all that's left are error and fatal error messages.
     158             :  *
     159             :  * Note that if you used the --Werror command line options, warning
     160             :  * are transformed to errors and thus they get printed in your output
     161             :  * anyway.
     162             :  *
     163             :  * \subsection style --style or -s -- define the output style
     164             :  *
     165             :  * By default the csspp compiler is expected to compress your CSS data
     166             :  * as much as possible (i.e. it removes non-required spaces, delete empty
     167             :  * rules, avoid new lines, etc.)
     168             :  *
     169             :  * The --style options let choose a different output style than the
     170             :  * compressed style:
     171             :  *
     172             :  * \li --style compressed -- this is the default, it outputs files as
     173             :  * compressed as possible
     174             :  * \li --style tidy -- this option writes one rule per line, each rule is
     175             :  * as compressed as possible
     176             :  * \li --compact -- this option writes one declaration per line, making it
     177             :  * a lot easier to edit if you were to do such a thing; this output is
     178             :  * already quite gentle on humans and can easily be used for debug purposes
     179             :  * \li expanded -- this option prints everything as neatly as possible
     180             :  * for human consumption; the output uses many newlines and indentation
     181             :  * for declarations
     182             :  *
     183             :  * The best to see how each style really looks like is for you to test
     184             :  * with a large existing CSS file and check the output of csspp against
     185             :  * that file.
     186             :  *
     187             :  * For example, you could use the \c expanded format before reading a
     188             :  * file you found on a website as in:
     189             :  *
     190             :  * \code
     191             :  *      csspp --style expanded compressed.css
     192             :  * \endcode
     193             :  *
     194             :  * \subsection version --version -- print out the version and exit
     195             :  *
     196             :  * This command line option prints out the version of the csspp compiler
     197             :  * in stdout and then exits.
     198             :  *
     199             :  * \subsection warnings-to-errors --Werror -- transform warnings into errors
     200             :  *
     201             :  * The --Werror requests the compiler to generate errors whenever
     202             :  * a warning message was to be printed. This also has the side effect
     203             :  * of incrementing the error counter by one each time a warning is
     204             :  * found. Note that as a result the warning counter will always
     205             :  * remains zero nin this case.
     206             :  *
     207             :  * \note
     208             :  * You may want to note that this option uses two dashes (--) to specify.
     209             :  * With GNU C/C++, the command line accepts -Werror, with a single dash.
     210             :  *
     211             :  * \subsection command-line-filenames Input files
     212             :  *
     213             :  * Other parameters specified on the command line, or parameters defined
     214             :  * after a "--", are taken as .scss filenames. The "--" is mandatory if
     215             :  * you have a preceeding argument that accepts multiple values like the
     216             :  * --args and -I options.
     217             :  *
     218             :  * \code
     219             :  *      // no need for "--" in this case:
     220             :  *      csspp -I scripts -p 2 my-script.scss
     221             :  *
     222             :  *      // "--" required in this case:
     223             :  *      csspp -p 2 -I scripts -- my-script.scss
     224             :  * \endcode
     225             :  */
     226             : 
     227             : // csspp
     228             : //
     229             : #include    <csspp/assembler.h>
     230             : #include    <csspp/compiler.h>
     231             : #include    <csspp/exception.h>
     232             : #include    <csspp/parser.h>
     233             : 
     234             : 
     235             : // advgetopt
     236             : //
     237             : #include    <advgetopt/advgetopt.h>
     238             : #include    <advgetopt/exception.h>
     239             : 
     240             : 
     241             : // boost
     242             : //
     243             : #include    <boost/preprocessor/stringize.hpp>
     244             : 
     245             : 
     246             : // C++
     247             : //
     248             : #include    <cstdlib>
     249             : #include    <fstream>
     250             : #include    <iostream>
     251             : 
     252             : 
     253             : // C
     254             : //
     255             : #include    <unistd.h>
     256             : 
     257             : 
     258             : // last include
     259             : //
     260             : #include    <snapdev/poison.h>
     261             : 
     262             : 
     263             : 
     264             : namespace
     265             : {
     266             : 
     267           1 : void free_char(char * ptr)
     268             : {
     269           1 :     free(ptr);
     270           1 : }
     271             : 
     272             : // TODO: add support for configuration files & the variable
     273             : 
     274             : constexpr advgetopt::option g_options[] =
     275             : {
     276             :     advgetopt::define_option(
     277             :           advgetopt::Name("args")
     278             :         , advgetopt::ShortName('a')
     279             :         , advgetopt::Flags(advgetopt::command_flags<
     280             :                   advgetopt::GETOPT_FLAG_REQUIRED
     281             :                 , advgetopt::GETOPT_FLAG_MULTIPLE>())
     282             :         , nullptr
     283             :         , "define values in the $_csspp_args variable map"
     284             :         , nullptr
     285             :     ),
     286             :     advgetopt::define_option(
     287             :           advgetopt::Name("debug")
     288             :         , advgetopt::ShortName('d')
     289             :         , advgetopt::Flags(advgetopt::standalone_command_flags<>())
     290             :         , advgetopt::Help("show all messages, including @debug messages")
     291             :     ),
     292             :     advgetopt::define_option(
     293             :           advgetopt::Name("include")
     294             :         , advgetopt::ShortName('I')
     295             :         , advgetopt::Flags(advgetopt::command_flags<
     296             :                   advgetopt::GETOPT_FLAG_REQUIRED
     297             :                 , advgetopt::GETOPT_FLAG_MULTIPLE>())
     298             :         , advgetopt::Help("specify one or more paths to various user defined CSS files; \"-\" to clear the list (i.e. \"-I -\")")
     299             :     ),
     300             :     advgetopt::define_option(
     301             :           advgetopt::Name("no-logo")
     302             :         , advgetopt::ShortName('\0')
     303             :         , advgetopt::Flags(advgetopt::standalone_command_flags<>())
     304             :         , advgetopt::Help("prevent the \"logo\" from appearing in the output file")
     305             :     ),
     306             :     advgetopt::define_option(
     307             :           advgetopt::Name("empty-on-undefined-variable")
     308             :         , advgetopt::ShortName('\0')
     309             :         , advgetopt::Flags(advgetopt::standalone_command_flags<>())
     310             :         , advgetopt::Help("if accessing an undefined variable, return an empty string, otherwise generate an error.")
     311             :     ),
     312             :     advgetopt::define_option(
     313             :           advgetopt::Name("output")
     314             :         , advgetopt::ShortName('o')
     315             :         , advgetopt::Flags(advgetopt::command_flags<
     316             :                   advgetopt::GETOPT_FLAG_REQUIRED>())
     317             :         , advgetopt::Help("save the results in the specified file if specified; otherwise send output to stdout.")
     318             :     ),
     319             :     advgetopt::define_option(
     320             :           advgetopt::Name("precision")
     321             :         , advgetopt::ShortName('p')
     322             :         , advgetopt::Flags(advgetopt::command_flags<
     323             :                   advgetopt::GETOPT_FLAG_REQUIRED>())
     324             :         , advgetopt::Help("define the number of digits to use after the decimal point, defaults to 3; note that for percent values, the precision is always 2.")
     325             :     ),
     326             :     advgetopt::define_option(
     327             :           advgetopt::Name("quiet")
     328             :         , advgetopt::ShortName('q')
     329             :         , advgetopt::Flags(advgetopt::standalone_command_flags<>())
     330             :         , advgetopt::Help("suppress @info and @warning messages.")
     331             :     ),
     332             :     advgetopt::define_option(
     333             :           advgetopt::Name("style")
     334             :         , advgetopt::ShortName('s')
     335             :         , advgetopt::Flags(advgetopt::command_flags<
     336             :                   advgetopt::GETOPT_FLAG_REQUIRED>())
     337             :         , advgetopt::Help("output style: compressed, tidy, compact, expanded.")
     338             :     ),
     339             :     advgetopt::define_option(
     340             :           advgetopt::Name("Werror")
     341             :         , advgetopt::Flags(advgetopt::standalone_command_flags<>())
     342             :         , advgetopt::Help("make warnings count as errors.")
     343             :     ),
     344             :     advgetopt::define_option(
     345             :           advgetopt::Name("--")
     346             :         , advgetopt::Flags(advgetopt::command_flags<
     347             :                   advgetopt::GETOPT_FLAG_MULTIPLE
     348             :                 , advgetopt::GETOPT_FLAG_DEFAULT_OPTION
     349             :                 , advgetopt::GETOPT_FLAG_SHOW_USAGE_ON_ERROR>())
     350             :         , advgetopt::Help("[file.css ...]; use stdin if no filename specified.")
     351             :     ),
     352             :     advgetopt::end_options()
     353             : };
     354             : 
     355             : // TODO: once we have stdc++20, remove all defaults
     356             : #pragma GCC diagnostic ignored "-Wpedantic"
     357             : advgetopt::options_environment const g_options_environment =
     358             : {
     359             :     .f_project_name = "csspp",
     360             :     .f_group_name = nullptr,
     361             :     .f_options = g_options,
     362             :     .f_options_files_directory = nullptr,
     363             :     .f_environment_variable_name = "CSSPPFLAGS",
     364             :     .f_environment_variable_intro = nullptr,
     365             :     .f_section_variables_name = nullptr,
     366             :     .f_configuration_files = nullptr,
     367             :     .f_configuration_filename = nullptr,
     368             :     .f_configuration_directories = nullptr,
     369             :     .f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_PROCESS_SYSTEM_PARAMETERS,
     370             :     .f_help_header = "Usage: %p [-<opt>] [file.css ...] [-o out.css]\n"
     371             :                      "where -<opt> is one or more of:",
     372             :     .f_help_footer = "%c",
     373             :     .f_version = CSSPP_VERSION,
     374             :     .f_license = "GNU GPL v2",
     375             :     .f_copyright = "Copyright (c) 2015-"
     376             :                    BOOST_PP_STRINGIZE(UTC_BUILD_YEAR)
     377             :                    " by Made to Order Software Corporation -- All Rights Reserved",
     378             :     //.f_build_date = UTC_BUILD_DATE,
     379             :     //.f_build_time = UTC_BUILD_TIME
     380             : };
     381             : 
     382             : 
     383             : 
     384             : class pp
     385             : {
     386             : public:
     387             :                         pp(int argc, char * argv[]);
     388             : 
     389             :     int                 compile();
     390             : 
     391             : private:
     392             :     advgetopt::getopt   f_opt;
     393             :     int                 f_precision = 3;
     394             : };
     395             : 
     396             : 
     397           1 : pp::pp(int argc, char * argv[])
     398           1 :     : f_opt(g_options_environment, argc, argv)
     399             : {
     400           1 :     if(f_opt.is_defined("quiet"))
     401             :     {
     402           0 :         csspp::error::instance().set_hide_all(true);
     403             :     }
     404             : 
     405           1 :     if(f_opt.is_defined("debug"))
     406             :     {
     407           1 :         csspp::error::instance().set_show_debug(true);
     408             :     }
     409             : 
     410           1 :     if(f_opt.is_defined("Werror"))
     411             :     {
     412           0 :         csspp::error::instance().set_count_warnings_as_errors(true);
     413             :     }
     414             : 
     415           1 :     if(f_opt.is_defined("precision"))
     416             :     {
     417           0 :         f_precision = f_opt.get_long("precision");
     418             :     }
     419           1 : }
     420             : 
     421           1 : int pp::compile()
     422             : {
     423           1 :     csspp::lexer::pointer_t l;
     424           1 :     csspp::position::pointer_t pos;
     425           1 :     std::unique_ptr<std::stringstream> ss;
     426             : 
     427           1 :     csspp::safe_precision_t safe_precision(f_precision);
     428             : 
     429           1 :     if(f_opt.is_defined("--"))
     430             :     {
     431             :         // one or more filename specified
     432           1 :         int const arg_count(f_opt.size("--"));
     433           2 :         if(arg_count == 1
     434           2 :         && f_opt.get_string("--") == "-")
     435             :         {
     436             :             // user asked for stdin
     437           0 :             pos.reset(new csspp::position("-"));
     438           0 :             l.reset(new csspp::lexer(std::cin, *pos));
     439             :         }
     440             :         else
     441             :         {
     442           1 :             std::unique_ptr<char, void (*)(char *)> cwd(get_current_dir_name(), free_char);
     443           1 :             ss.reset(new std::stringstream);
     444           1 :             pos.reset(new csspp::position("csspp.css"));
     445           2 :             for(int idx(0); idx < arg_count; ++idx)
     446             :             {
     447             :                 // full paths so the -I have no effects on those files
     448           3 :                 std::string filename(f_opt.get_string("--", idx));
     449           1 :                 if(filename.empty())
     450             :                 {
     451           0 :                     csspp::error::instance() << *pos
     452           0 :                             << "You cannot include a file with an empty name."
     453           0 :                             << csspp::error_mode_t::ERROR_WARNING;
     454           0 :                     return 1;
     455             :                 }
     456           1 :                 if(filename == "-")
     457             :                 {
     458           0 :                     csspp::error::instance() << *pos
     459           0 :                             << "You cannot currently mix files and stdin. You may use @import \"filename\"; in your stdin data though."
     460           0 :                             << csspp::error_mode_t::ERROR_WARNING;
     461           0 :                     return 1;
     462             :                 }
     463           1 :                 if(filename[0] == '/')
     464             :                 {
     465             :                     // already absolute
     466           1 :                     *ss << "@import \"" << filename << "\";\n";
     467             :                 }
     468             :                 else
     469             :                 {
     470             :                     // make absolute so we do not need to have a "." path
     471           0 :                     *ss << "@import \"" << cwd.get() << "/" << filename << "\";\n";
     472             :                 }
     473           1 :             }
     474           1 :             l.reset(new csspp::lexer(*ss, *pos));
     475           1 :         }
     476             :     }
     477             :     else
     478             :     {
     479             :         // default to stdin
     480           0 :         pos.reset(new csspp::position("-"));
     481           0 :         l.reset(new csspp::lexer(std::cin, *pos));
     482             :     }
     483             : 
     484             :     // run the lexer and parser
     485           1 :     csspp::error_happened_t error_tracker;
     486           2 :     csspp::parser p(l);
     487           1 :     csspp::node::pointer_t root(p.stylesheet());
     488           1 :     if(error_tracker.error_happened())
     489             :     {
     490           0 :         return 1;
     491             :     }
     492             : 
     493           1 :     csspp::node::pointer_t csspp_args(new csspp::node(csspp::node_type_t::LIST, root->get_position()));
     494           1 :     csspp::node::pointer_t args_var(new csspp::node(csspp::node_type_t::VARIABLE, root->get_position()));
     495           1 :     args_var->set_string("_csspp_args");
     496           1 :     csspp::node::pointer_t wrapper(new csspp::node(csspp::node_type_t::LIST, root->get_position()));
     497           1 :     csspp::node::pointer_t array(new csspp::node(csspp::node_type_t::ARRAY, root->get_position()));
     498           1 :     wrapper->add_child(array);
     499           1 :     csspp_args->add_child(args_var);
     500           1 :     csspp_args->add_child(wrapper);
     501           1 :     if(f_opt.is_defined("args"))
     502             :     {
     503           0 :         int const count(f_opt.size("args"));
     504           0 :         for(int idx(0); idx < count; ++idx)
     505             :         {
     506           0 :             csspp::node::pointer_t arg(new csspp::node(csspp::node_type_t::STRING, root->get_position()));
     507           0 :             arg->set_string(f_opt.get_string("args", idx));
     508           0 :             array->add_child(arg);
     509           0 :         }
     510             :     }
     511           1 :     root->set_variable("_csspp_args", csspp_args);
     512             : 
     513             :     // run the compiler
     514           1 :     csspp::compiler c;
     515           1 :     c.set_root(root);
     516           1 :     c.set_date_time_variables(time(nullptr));
     517             : 
     518             :     // add paths to the compiler (i.e. for the user and system @imports)
     519           1 :     if(f_opt.is_defined("include"))
     520             :     {
     521           1 :         std::size_t const count(f_opt.size("include"));
     522           3 :         for(std::size_t idx(0); idx < count; ++idx)
     523             :         {
     524           6 :             std::string const path(f_opt.get_string("include", idx));
     525           2 :             if(path == "-")
     526             :             {
     527           0 :                 c.clear_paths();
     528             :             }
     529             :             else
     530             :             {
     531           2 :                 c.add_path(path);
     532             :             }
     533           2 :         }
     534             :     }
     535             : 
     536           1 :     if(f_opt.is_defined("no-logo"))
     537             :     {
     538           0 :         c.set_no_logo();
     539             :     }
     540             : 
     541           1 :     if(f_opt.is_defined("empty-on-undefined-variable"))
     542             :     {
     543           0 :         c.set_empty_on_undefined_variable(true);
     544             :     }
     545             : 
     546           1 :     c.compile(false);
     547           1 :     if(error_tracker.error_happened())
     548             :     {
     549           0 :         return 1;
     550             :     }
     551             : 
     552           1 :     csspp::output_mode_t output_mode(csspp::output_mode_t::COMPRESSED);
     553           1 :     if(f_opt.is_defined("style"))
     554             :     {
     555           3 :         std::string const mode(f_opt.get_string("style"));
     556           1 :         if(mode == "compressed")
     557             :         {
     558           0 :             output_mode = csspp::output_mode_t::COMPRESSED;
     559             :         }
     560           1 :         else if(mode == "tidy")
     561             :         {
     562           0 :             output_mode = csspp::output_mode_t::TIDY;
     563             :         }
     564           1 :         else if(mode == "compact")
     565             :         {
     566           0 :             output_mode = csspp::output_mode_t::COMPACT;
     567             :         }
     568           1 :         else if(mode == "expanded")
     569             :         {
     570           1 :             output_mode = csspp::output_mode_t::EXPANDED;
     571             :         }
     572             :         else
     573             :         {
     574           0 :             csspp::error::instance() << root->get_position()
     575           0 :                     << "The output mode \""
     576           0 :                     << mode
     577           0 :                     << "\" is not supported. Try one of: compressed, tidy, compact, expanded instead."
     578           0 :                     << csspp::error_mode_t::ERROR_WARNING;
     579           0 :             return 1;
     580             :         }
     581           1 :     }
     582             : 
     583           1 :     std::ostream * out(nullptr);
     584           1 :     bool user_output(false);
     585           1 :     std::string output_filename;
     586           1 :     if(f_opt.is_defined("output"))
     587             :     {
     588           1 :         output_filename = f_opt.get_string("output");
     589           1 :         user_output = output_filename != "-";
     590             :     }
     591           1 :     if(user_output)
     592             :     {
     593           1 :         out = new std::ofstream(output_filename);
     594             :     }
     595             :     else
     596             :     {
     597           0 :         out = &std::cout;
     598             :     }
     599           1 :     csspp::assembler a(*out);
     600           1 :     a.output(c.get_root(), output_mode);
     601           1 :     if(user_output)
     602             :     {
     603           1 :         delete out;
     604             :     }
     605           1 :     if(error_tracker.error_happened())
     606             :     {
     607             :         // this should be rare as the assembler generally does not generate
     608             :         // errors (it may throw though.)
     609           0 :         return 1;
     610             :     }
     611             : 
     612           1 :     return 0;
     613           1 : }
     614             : 
     615             : } // no name namespace
     616             : 
     617           1 : int main(int argc, char *argv[])
     618             : {
     619             :     try
     620             :     {
     621           1 :         pp preprocessor(argc, argv);
     622           1 :         return preprocessor.compile();
     623           1 :     }
     624           0 :     catch(advgetopt::getopt_exit const & except)
     625             :     {
     626           0 :         return except.code();
     627           0 :     }
     628           0 :     catch(csspp::csspp_exception_exit const & e)
     629             :     {
     630             :         // something went wrong in the library
     631           0 :         return e.exit_code();
     632           0 :     }
     633           0 :     catch(csspp::csspp_exception_logic const & e)
     634             :     {
     635           0 :         std::cerr << "fatal error: a logic exception, which should NEVER occur, occurred: " << e.what() << std::endl;
     636           0 :         exit(1);
     637           0 :     }
     638           0 :     catch(csspp::csspp_exception_overflow const & e)
     639             :     {
     640           0 :         std::cerr << "fatal error: an overflow exception occurred: " << e.what() << std::endl;
     641           0 :         exit(1);
     642           0 :     }
     643           0 :     catch(csspp::csspp_exception_runtime const & e)
     644             :     {
     645           0 :         std::cerr << "fatal error: a runtime exception occurred: " << e.what() << std::endl;
     646           0 :         exit(1);
     647           0 :     }
     648           0 :     catch(advgetopt::getopt_undefined const & e)
     649             :     {
     650           0 :         std::cerr << "fatal error: an undefined exception occurred because of your command line: " << e.what() << std::endl;
     651           0 :         exit(1);
     652           0 :     }
     653           0 :     catch(advgetopt::getopt_invalid const & e)
     654             :     {
     655           0 :         std::cerr << "fatal error: there is an error on your command line, an exception occurred: " << e.what() << std::endl;
     656           0 :         exit(1);
     657           0 :     }
     658           0 :     catch(advgetopt::getopt_invalid_default const & e)
     659             :     {
     660           0 :         std::cerr << "fatal error: there is an error on your command line, you used a parameter without a value and there is no default. The exception says: " << e.what() << std::endl;
     661           0 :         exit(1);
     662           0 :     }
     663             : }
     664             : 
     665             : // Local Variables:
     666             : // mode: cpp
     667             : // indent-tabs-mode: nil
     668             : // c-basic-offset: 4
     669             : // tab-width: 4
     670             : // End:
     671             : 
     672             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14