229 #include <csspp/assembler.h>
230 #include <csspp/compiler.h>
231 #include <csspp/exception.h>
232 #include <csspp/parser.h>
237 #include <advgetopt/advgetopt.h>
238 #include <advgetopt/exception.h>
243 #include <boost/preprocessor/stringize.hpp>
260 #include <snapdev/poison.h>
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>())
283 ,
"define values in the $_csspp_args variable map"
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")
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 -\")")
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")
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.")
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.")
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.")
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.")
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.")
339 advgetopt::define_option(
340 advgetopt::Name(
"Werror")
341 , advgetopt::Flags(advgetopt::standalone_command_flags<>())
342 , advgetopt::Help(
"make warnings count as errors.")
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.")
352 advgetopt::end_options()
356 #pragma GCC diagnostic ignored "-Wpedantic"
359 .f_project_name =
"csspp",
360 .f_group_name =
nullptr,
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",
387 pp(
int argc,
char * argv[]);
397 pp::pp(
int argc,
char * argv[])
400 if(
f_opt.is_defined(
"quiet"))
402 csspp::error::instance().set_hide_all(
true);
405 if(
f_opt.is_defined(
"debug"))
407 csspp::error::instance().set_show_debug(
true);
410 if(
f_opt.is_defined(
"Werror"))
412 csspp::error::instance().set_count_warnings_as_errors(
true);
415 if(
f_opt.is_defined(
"precision"))
423 csspp::lexer::pointer_t l;
424 csspp::position::pointer_t pos;
425 std::unique_ptr<std::stringstream> ss;
427 csspp::safe_precision_t safe_precision(
f_precision);
429 if(
f_opt.is_defined(
"--"))
432 int const arg_count(
f_opt.size(
"--"));
434 &&
f_opt.get_string(
"--") ==
"-")
437 pos.reset(
new csspp::position(
"-"));
438 l.reset(
new csspp::lexer(std::cin, *pos));
442 std::unique_ptr<char, void (*)(
char *)> cwd(get_current_dir_name(),
free_char);
443 ss.reset(
new std::stringstream);
444 pos.reset(
new csspp::position(
"csspp.css"));
445 for(
int idx(0); idx < arg_count; ++idx)
448 std::string filename(
f_opt.get_string(
"--", idx));
451 csspp::error::instance() << *pos
452 <<
"You cannot include a file with an empty name."
453 << csspp::error_mode_t::ERROR_WARNING;
458 csspp::error::instance() << *pos
459 <<
"You cannot currently mix files and stdin. You may use @import \"filename\"; in your stdin data though."
460 << csspp::error_mode_t::ERROR_WARNING;
463 if(filename[0] ==
'/')
466 *ss <<
"@import \"" << filename <<
"\";\n";
471 *ss <<
"@import \"" << cwd.get() <<
"/" << filename <<
"\";\n";
474 l.reset(
new csspp::lexer(*ss, *pos));
480 pos.reset(
new csspp::position(
"-"));
481 l.reset(
new csspp::lexer(std::cin, *pos));
485 csspp::error_happened_t error_tracker;
487 csspp::node::pointer_t root(p.stylesheet());
488 if(error_tracker.error_happened())
493 csspp::node::pointer_t csspp_args(
new csspp::node(csspp::node_type_t::LIST, root->get_position()));
494 csspp::node::pointer_t args_var(
new csspp::node(csspp::node_type_t::VARIABLE, root->get_position()));
495 args_var->set_string(
"_csspp_args");
496 csspp::node::pointer_t wrapper(
new csspp::node(csspp::node_type_t::LIST, root->get_position()));
497 csspp::node::pointer_t array(
new csspp::node(csspp::node_type_t::ARRAY, root->get_position()));
498 wrapper->add_child(array);
499 csspp_args->add_child(args_var);
500 csspp_args->add_child(wrapper);
501 if(
f_opt.is_defined(
"args"))
503 int const count(
f_opt.size(
"args"));
504 for(
int idx(0); idx < count; ++idx)
506 csspp::node::pointer_t arg(
new csspp::node(csspp::node_type_t::STRING, root->get_position()));
507 arg->set_string(
f_opt.get_string(
"args", idx));
508 array->add_child(arg);
511 root->set_variable(
"_csspp_args", csspp_args);
516 c.set_date_time_variables(time(
nullptr));
519 if(
f_opt.is_defined(
"include"))
521 std::size_t
const count(
f_opt.size(
"include"));
522 for(std::size_t idx(0); idx < count; ++idx)
524 std::string
const path(
f_opt.get_string(
"include", idx));
536 if(
f_opt.is_defined(
"no-logo"))
541 if(
f_opt.is_defined(
"empty-on-undefined-variable"))
543 c.set_empty_on_undefined_variable(
true);
547 if(error_tracker.error_happened())
552 csspp::output_mode_t output_mode(csspp::output_mode_t::COMPRESSED);
553 if(
f_opt.is_defined(
"style"))
555 std::string
const mode(
f_opt.get_string(
"style"));
556 if(mode ==
"compressed")
558 output_mode = csspp::output_mode_t::COMPRESSED;
560 else if(mode ==
"tidy")
562 output_mode = csspp::output_mode_t::TIDY;
564 else if(mode ==
"compact")
566 output_mode = csspp::output_mode_t::COMPACT;
568 else if(mode ==
"expanded")
570 output_mode = csspp::output_mode_t::EXPANDED;
574 csspp::error::instance() << root->get_position()
575 <<
"The output mode \""
577 <<
"\" is not supported. Try one of: compressed, tidy, compact, expanded instead."
578 << csspp::error_mode_t::ERROR_WARNING;
583 std::ostream * out(
nullptr);
584 bool user_output(
false);
585 std::string output_filename;
586 if(
f_opt.is_defined(
"output"))
588 output_filename =
f_opt.get_string(
"output");
589 user_output = output_filename !=
"-";
593 out =
new std::ofstream(output_filename);
599 csspp::assembler a(*out);
600 a.output(c.get_root(), output_mode);
605 if(error_tracker.error_happened())
617 int main(
int argc,
char *argv[])
621 pp preprocessor(argc, argv);
622 return preprocessor.compile();
624 catch(advgetopt::getopt_exit
const & except)
626 return except.code();
628 catch(csspp::csspp_exception_exit
const & e)
631 return e.exit_code();
633 catch(csspp::csspp_exception_logic
const & e)
635 std::cerr <<
"fatal error: a logic exception, which should NEVER occur, occurred: " << e.what() << std::endl;
638 catch(csspp::csspp_exception_overflow
const & e)
640 std::cerr <<
"fatal error: an overflow exception occurred: " << e.what() << std::endl;
643 catch(csspp::csspp_exception_runtime
const & e)
645 std::cerr <<
"fatal error: a runtime exception occurred: " << e.what() << std::endl;
648 catch(advgetopt::getopt_undefined
const & e)
650 std::cerr <<
"fatal error: an undefined exception occurred because of your command line: " << e.what() << std::endl;
653 catch(advgetopt::getopt_invalid
const & e)
655 std::cerr <<
"fatal error: there is an error on your command line, an exception occurred: " << e.what() << std::endl;
658 catch(advgetopt::getopt_invalid_default
const & e)
660 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;
int main(int argc, char *argv[])
void free_char(char *ptr)
constexpr advgetopt::option g_options[]
advgetopt::options_environment const g_options_environment