Line data Source code
1 : // Copyright (c) 2024-2025 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/prinbee
4 : // contact@m2osw.com
5 : //
6 : // This program is free software: you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation, either version 3 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 :
19 :
20 : /** \file
21 : * \brief Location in the input.
22 : *
23 : * This object manages the current location in the input file or string.
24 : * (The CLI uses a string.)
25 : *
26 : * The object generates a string with the location which is often used
27 : * to display an error message if necessary. The location can also be
28 : * copied in each node so if the error is found at a later time (in the
29 : * parser or when executing the results) then it can be used with the
30 : * correct information.
31 : */
32 :
33 : // self
34 : //
35 : #include "prinbee/pbql/input.h"
36 :
37 : #include "prinbee/exception.h"
38 :
39 :
40 : // snapdev
41 : //
42 : #include <snapdev/file_contents.h>
43 :
44 :
45 : // snaplogger
46 : //
47 : #include <snaplogger/message.h>
48 :
49 :
50 : // last include
51 : //
52 : #include <snapdev/poison.h>
53 :
54 :
55 :
56 : namespace prinbee
57 : {
58 : namespace pbql
59 : {
60 :
61 :
62 :
63 65808 : input::input(std::string const & script, std::string const & filename)
64 65808 : : f_script(script)
65 65808 : , f_input(f_script)
66 : {
67 65808 : f_location.set_filename(filename);
68 65808 : }
69 :
70 :
71 741073 : char32_t input::getc()
72 : {
73 741073 : if(f_ungetc_pos > 0)
74 : {
75 5264 : --f_ungetc_pos;
76 5264 : return f_ungetc[f_ungetc_pos];
77 : }
78 735809 : char32_t c(*f_input);
79 735809 : if(c != libutf8::EOS)
80 : {
81 670137 : f_location.next_column();
82 : }
83 735809 : ++f_input;
84 735809 : if(c == '\r')
85 : {
86 40 : c = *f_input;
87 40 : if(c == '\n')
88 : {
89 36 : ++f_input;
90 : }
91 : else
92 : {
93 4 : c = '\n';
94 : }
95 : }
96 735809 : if(c == '\n')
97 : {
98 263 : f_location.next_line();
99 : }
100 :
101 735809 : return c;
102 : }
103 :
104 :
105 70592 : void input::ungetc(char32_t c)
106 : {
107 70592 : if(c == libutf8::EOS)
108 : {
109 65266 : return;
110 : }
111 10652 : if(f_ungetc_pos >= std::size(f_ungetc))
112 : {
113 3 : throw out_of_range("ungetc() called too many times.");
114 : }
115 5325 : f_ungetc[f_ungetc_pos] = c;
116 5325 : ++f_ungetc_pos;
117 : }
118 :
119 :
120 76054 : location const & input::get_location() const
121 : {
122 76054 : return f_location;
123 : }
124 :
125 :
126 2 : input::pointer_t create_input(std::string const & filename)
127 : {
128 2 : snapdev::file_contents file(filename);
129 2 : if(!file.read_all())
130 : {
131 : // "not found" may be wrong (i.e. it could be a permission error)
132 : //
133 1 : throw file_not_found("could not read \"" + filename + "\".");
134 : }
135 2 : return std::make_shared<input>(file.contents(), filename);
136 2 : }
137 :
138 :
139 :
140 : } // namespace pbql
141 : } // namespace prinbee
142 : // vim: ts=4 sw=4 et
|