LEFT | RIGHT |
1 /* | 1 /* |
2 This file is part of LilyPond, the GNU music typesetter. | 2 This file is part of LilyPond, the GNU music typesetter. |
3 | 3 |
4 Copyright (C) 1997--2020 Jan Nieuwenhuizen <janneke@gnu.org> | 4 Copyright (C) 1997--2020 Jan Nieuwenhuizen <janneke@gnu.org> |
5 Han-Wen Nienhuys <hanwen@xs4all.nl> | 5 Han-Wen Nienhuys <hanwen@xs4all.nl> |
6 | 6 |
7 LilyPond is free software: you can redistribute it and/or modify | 7 LilyPond is free software: you can redistribute it and/or modify |
8 it under the terms of the GNU General Public License as published by | 8 it under the terms of the GNU General Public License as published by |
9 the Free Software Foundation, either version 3 of the License, or | 9 the Free Software Foundation, either version 3 of the License, or |
10 (at your option) any later version. | 10 (at your option) any later version. |
(...skipping 17 matching lines...) Expand all Loading... |
28 #include "config.hh" | 28 #include "config.hh" |
29 | 29 |
30 #include <cstdio> | 30 #include <cstdio> |
31 #include <sstream> | 31 #include <sstream> |
32 | 32 |
33 | 33 |
34 #include "file-name-map.hh" | 34 #include "file-name-map.hh" |
35 #include "international.hh" | 35 #include "international.hh" |
36 #include "misc.hh" | 36 #include "misc.hh" |
37 #include "warn.hh" | 37 #include "warn.hh" |
| 38 #include "lily-imports.hh" |
38 | 39 |
39 using std::istream; | 40 using std::istream; |
40 using std::istringstream; | 41 using std::istringstream; |
41 using std::string; | 42 using std::string; |
42 using std::vector; | 43 using std::vector; |
43 | 44 |
44 void | 45 void |
45 Source_file::load_stdin () | 46 Source_file::load_stdin () |
46 { | 47 { |
47 characters_.clear (); | 48 data_.clear (); |
48 int c; | 49 int c; |
49 while ((c = fgetc (stdin)) != EOF) | 50 while ((c = fgetc (stdin)) != EOF) |
50 characters_.push_back ((char)c); | 51 data_.push_back ((char)c); |
51 } | 52 } |
52 | 53 |
53 /* | 54 /* |
54 return contents of FILENAME. *Not 0-terminated!* | 55 return contents of FILENAME. |
55 */ | 56 */ |
56 vector<char> | 57 string |
57 gulp_file (const string &filename, size_t desired_size) | 58 gulp_file (const string &filename, size_t desired_size) |
58 { | 59 { |
59 /* "b" must ensure to open literally, avoiding text (CR/LF) | 60 /* "b" must ensure to open literally, avoiding text (CR/LF) |
60 conversions. */ | 61 conversions. */ |
61 FILE *f = fopen (filename.c_str (), "rb"); // TODO: RAII | 62 FILE *f = fopen (filename.c_str (), "rb"); // TODO: RAII |
62 if (!f) | 63 if (!f) |
63 { | 64 { |
64 warning (_f ("cannot open file: `%s'", filename.c_str ())); | 65 warning (_f ("cannot open file: `%s'", filename.c_str ())); |
65 return {}; | 66 return {}; |
66 } | 67 } |
67 | 68 |
68 fseek (f, 0, SEEK_END); | 69 fseek (f, 0, SEEK_END); |
69 const auto real_size = ftell (f); | 70 const auto real_size = ftell (f); |
70 if (real_size < 0) | 71 if (real_size < 0) |
71 { | 72 { |
72 warning (_f ("failed to get file size: `%s'", filename.c_str ())); | 73 warning (_f ("failed to get file size: `%s'", filename.c_str ())); |
73 fclose (f); | 74 fclose (f); |
74 return {}; | 75 return {}; |
75 } | 76 } |
76 size_t read_count = real_size; | 77 size_t read_count = real_size; |
77 | 78 |
78 if (desired_size > 0) | 79 if (desired_size > 0) |
79 read_count = std::min (read_count, desired_size); | 80 read_count = std::min (read_count, desired_size); |
80 | 81 |
81 rewind (f); | 82 rewind (f); |
82 | 83 |
83 vector<char> cxx_arr (read_count); | 84 string dest (read_count, 0); |
84 size_t bytes_read = fread (cxx_arr.data (), sizeof (char), read_count, f); | 85 size_t bytes_read = fread (&dest[0], sizeof (char), read_count, f); |
85 if (bytes_read < read_count) | 86 if (bytes_read < read_count) |
86 { | 87 { |
87 warning (_f ("expected to read %zu characters, got %zu", read_count, | 88 warning (_f ("expected to read %zu characters, got %zu", read_count, |
88 bytes_read)); | 89 bytes_read)); |
89 cxx_arr.resize (bytes_read); | 90 dest.resize (bytes_read); |
90 } | 91 } |
91 fclose (f); | 92 fclose (f); |
92 return cxx_arr; | 93 return dest; |
93 } | 94 } |
94 | 95 |
95 void | 96 void |
96 Source_file::init () | 97 Source_file::init () |
97 { | 98 { |
98 istream_ = 0; | 99 istream_ = 0; |
99 line_offset_ = 0; | 100 line_offset_ = 0; |
100 smobify_self (); | 101 smobify_self (); |
101 } | 102 } |
102 | 103 |
103 Source_file::Source_file (const string &filename, const string &data) | 104 Source_file::Source_file (const string &filename, const string &data) |
104 { | 105 { |
105 init (); | 106 init (); |
106 | 107 |
107 name_ = filename; | 108 name_ = filename; |
108 | 109 |
109 characters_.resize (data.length ()); | 110 data_ = data; |
110 copy (data.begin (), data.end (), characters_.begin ()); | 111 |
111 | 112 init_newlines (); |
112 characters_.push_back (0); | 113 } |
113 | 114 |
114 for (vsize i = 0; i < characters_.size (); i++) | 115 void |
115 if (characters_[i] == '\n') | 116 Source_file::init_newlines () |
116 newline_locations_.push_back (&characters_[0] + i); | 117 { |
| 118 for (vsize i = 0; i < data_.size (); i++) |
| 119 if (data_[i] == '\n') |
| 120 newline_locations_.push_back (&data_[0] + i); |
117 } | 121 } |
118 | 122 |
119 Source_file::Source_file (const string &filename_string) | 123 Source_file::Source_file (const string &filename_string) |
120 { | 124 { |
121 init (); | 125 init (); |
122 | 126 |
123 name_ = filename_string; | 127 name_ = filename_string; |
124 | 128 |
125 if (filename_string == "-") | 129 if (filename_string == "-") |
126 load_stdin (); | 130 load_stdin (); |
127 else | 131 else |
128 { | 132 data_ = gulp_file (filename_string, -1); |
129 characters_ = gulp_file (filename_string, -1); | 133 |
130 } | 134 init_newlines (); |
131 | |
132 characters_.push_back (0); | |
133 | |
134 for (vsize i = 0; i < characters_.size (); i++) | |
135 if (characters_[i] == '\n') | |
136 newline_locations_.push_back (&characters_[0] + i); | |
137 } | 135 } |
138 | 136 |
139 istream * | 137 istream * |
140 Source_file::get_istream () | 138 Source_file::get_istream () |
141 { | 139 { |
142 if (!istream_) | 140 if (!istream_) |
143 { | 141 { |
144 if (length ()) // can-t this be done without such a hack? | 142 if (length ()) // can-t this be done without such a hack? |
145 istream_ = new istringstream (c_str ()); | 143 istream_ = new istringstream (c_str ()); |
146 else | 144 else |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 { | 229 { |
232 if (!contains (pos_str0)) | 230 if (!contains (pos_str0)) |
233 return ""; | 231 return ""; |
234 | 232 |
235 Slice line = line_slice (pos_str0); | 233 Slice line = line_slice (pos_str0); |
236 char const *data_str0 = c_str (); | 234 char const *data_str0 = c_str (); |
237 return string (data_str0 + line[LEFT], line.length ()); | 235 return string (data_str0 + line[LEFT], line.length ()); |
238 } | 236 } |
239 | 237 |
240 void | 238 void |
241 Source_file::get_counts (char const *pos_str0, | 239 Source_file::get_counts (char const *pos_str0, ssize_t *line_number, |
242 ssize_t *line_number, | 240 ssize_t *line_char, ssize_t *column, |
243 ssize_t *line_char, | 241 ssize_t *line_byte_offset) const |
244 ssize_t *column, | |
245 ssize_t *byte_offset) const | |
246 { | 242 { |
247 // Initialize arguments to defaults, needed if pos_str0 is not in source | 243 // Initialize arguments to defaults, needed if pos_str0 is not in source |
248 *line_number = 0; | 244 *line_number = 0; |
249 *line_char = 0; | 245 *line_char = 0; |
250 *column = 0; | 246 *column = 0; |
251 *byte_offset = 0; | 247 *line_byte_offset = 0; |
252 | 248 |
253 if (!contains (pos_str0)) | 249 if (!contains (pos_str0)) |
254 return; | 250 return; |
255 | 251 |
256 *line_number = get_line (pos_str0); | 252 *line_number = get_line (pos_str0); |
257 | 253 |
258 Slice line = line_slice (pos_str0); | 254 Slice line = line_slice (pos_str0); |
259 char const *data = c_str (); | 255 char const *data = c_str (); |
260 char const *line_start = (char const *)data + line[LEFT]; | 256 char const *line_start = (char const *)data + line[LEFT]; |
261 | 257 |
262 ssize left = (char const *) pos_str0 - line_start; | 258 ssize left = (char const *) pos_str0 - line_start; |
263 *byte_offset = left; | 259 *line_byte_offset = left; |
264 | 260 |
265 // TODO: copying into line_begin looks pointless and wasteful | 261 // TODO: copying into line_begin looks pointless and wasteful |
266 string line_begin (line_start, left); | 262 string line_begin (line_start, left); |
267 char const *line_chars = line_begin.c_str (); | 263 char const *line_chars = line_begin.c_str (); |
268 | 264 |
269 for (; left > 0; --left, ++line_chars) | 265 for (; left > 0; --left, ++line_chars) |
270 { | 266 { |
271 // Skip UTF-8 continuation bytes. This is simplistic but | 267 // Skip UTF-8 continuation bytes. This is simplistic but |
272 // robust, and we warn against non-UTF-8 input in the lexer | 268 // robust, and we warn against non-UTF-8 input in the lexer |
273 // already. In the case of non-UTF-8 or of this function being | 269 // already. In the case of non-UTF-8 or of this function being |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 | 315 |
320 assert (line == get_line (pos_str0)); | 316 assert (line == get_line (pos_str0)); |
321 } | 317 } |
322 else | 318 else |
323 line_offset_ = line; | 319 line_offset_ = line; |
324 } | 320 } |
325 | 321 |
326 size_t | 322 size_t |
327 Source_file::length () const | 323 Source_file::length () const |
328 { | 324 { |
329 return characters_.size (); | 325 return data_.size (); |
330 } | 326 } |
331 | 327 |
332 char const * | 328 char const * |
333 Source_file::c_str () const | 329 Source_file::c_str () const |
334 { | 330 { |
335 return &characters_[0]; | 331 return data_.c_str (); |
336 } | 332 } |
337 | 333 |
338 /****************************************************************/ | 334 /****************************************************************/ |
339 | 335 |
340 | 336 |
341 const char * const Source_file::type_p_name_ = "ly:source-file?"; | 337 const char * const Source_file::type_p_name_ = "ly:source-file?"; |
342 | 338 |
343 int | 339 int |
344 Source_file::print_smob (SCM port, scm_print_state *) const | 340 Source_file::print_smob (SCM port, scm_print_state *) const |
345 { | 341 { |
346 scm_puts ("#<Source_file ", port); | 342 scm_puts ("#<Source_file ", port); |
347 scm_puts (name_.c_str (), port); | 343 scm_puts (name_.c_str (), port); |
348 | 344 |
349 /* Do not print properties, that is too much hassle. */ | 345 /* Do not print properties, that is too much hassle. */ |
350 scm_puts (" >", port); | 346 scm_puts (" >", port); |
351 return 1; | 347 return 1; |
352 } | 348 } |
LEFT | RIGHT |