aboutsummaryrefslogtreecommitdiff
blob: e4a7c29b7d2b0d34935d1f207e422805d91e2fab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
   Please use git log for copyright holder and year information

   This file is part of libbash.

   libbash 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 of the License, or
   (at your option) any later version.

   libbash 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 libbash.  If not, see <http://www.gnu.org/licenses/>.
*/
///
/// \file cppbash_builtin.cpp
/// \brief Implementation of class to inherit builtins from
///

#include "cppbash_builtin.h"

#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

#include "builtins/boolean_builtins.h"
#include "builtins/builtin_exceptions.h"
#include "builtins/break_builtin.h"
#include "builtins/continue_builtin.h"
#include "builtins/declare_builtin.h"
#include "builtins/echo_builtin.h"
#include "builtins/eval_builtin.h"
#include "builtins/export_builtin.h"
#include "builtins/local_builtin.h"
#include "builtins/inherit_builtin.h"
#include "builtins/let_builtin.h"
#include "builtins/return_builtin.h"
#include "builtins/printf_builtin.h"
#include "builtins/shift_builtin.h"
#include "builtins/shopt_builtin.h"
#include "builtins/source_builtin.h"
#include "builtins/unset_builtin.h"
#include "builtins/read_builtin.h"
#include "builtins/set_builtin.h"

namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
namespace phoenix = boost::phoenix;

cppbash_builtin::cppbash_builtin(BUILTIN_ARGS): _out_stream(&out), _err_stream(&err), _inp_stream(&in), _walker(walker)
{
}

cppbash_builtin::builtins_type& cppbash_builtin::builtins() {
  static boost::scoped_ptr<builtins_type> p(new builtins_type {
      {"break", boost::factory<break_builtin*>()},
      {"continue", boost::factory<continue_builtin*>()},
      {"echo", boost::factory<echo_builtin*>()},
      {"eval", boost::factory<eval_builtin*>()},
      {"export", boost::factory<export_builtin*>()},
      {"local", boost::factory<local_builtin*>()},
      {"declare", boost::factory<declare_builtin*>()},
      {"source", boost::factory<source_builtin*>()},
      {"shift", boost::factory<shift_builtin*>()},
      {"shopt", boost::factory<shopt_builtin*>()},
      {"inherit", boost::factory<inherit_builtin*>()},
      {":", boost::factory<true_builtin*>()},
      {"true", boost::factory<true_builtin*>()},
      {"false", boost::factory<false_builtin*>()},
      {"return", boost::factory<return_builtin*>()},
      {"printf", boost::factory<printf_builtin*>()},
      {"let", boost::factory<let_builtin*>()},
      {"unset", boost::factory<unset_builtin*>()},
      {"read", boost::factory<read_builtin*>()},
      {"set", boost::factory<set_builtin*>()},
  });
  return *p;
}

void cppbash_builtin::transform_escapes(const std::string &string,
                                        std::ostream& output,
                                        bool ansi_c)
{
  using phoenix::val;
  using qi::lit;

  auto escape_parser =
  +(
    lit('\\') >>
    (
     lit('a')[output << val("\a")] |
     lit('b')[output << val("\b")] |
     // \e is a GNU extension
     lit('e')[output << val("\033")] |
     lit('E')[output << val("\033")] |
     lit('f')[output << val("\f")] |
     lit('n')[output << val("\n")] |
     lit('r')[output << val("\r")] |
     lit('t')[output << val("\t")] |
     lit('v')[output << val("\v")] |
     lit('\'')[output << val(ansi_c ? "'" : "\\'")] |
     lit('"')[output << val(ansi_c ? "\"" : "\\\"")] |
     lit('c')[phoenix::throw_(suppress_output())] |
     lit('\\')[output << val('\\')] |
     lit("0") >> qi::uint_parser<unsigned, 8, 1, 3>()[ output << phoenix::static_cast_<char>(qi::_1)] |
     lit("x") >> qi::uint_parser<unsigned, 16, 1, 2>()[ output << phoenix::static_cast_<char>(qi::_1)]

    ) |
    qi::char_[output << qi::_1]
  );

  auto begin = string.begin();
  qi::parse(begin, string.end(), escape_parser);
}