2 source-file.cc -- implement Source_file
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2003 Jan Nieuwenhuizen <janneke@gnu.org>
7 Han-Wen Nienhuys <hanwen@cs.uu.nl>
17 #include <strstream.h>
18 #define istringstream(x) istrstream(x, length ())
22 #include "flower-proto.hh"
24 #include "source-file.hh"
28 Source_file::load_stdin ()
33 Array
<char> chs
; // ugh.
34 while ((c
= fgetc (stdin
)) != EOF
)
37 length_
= chs
.size ();
38 contents_str0_
= chs
.remove_array ();
44 gulp_file (String fn
, int* len
)
47 let's hope that "b" opens anything binary, and does not apply
50 FILE * f
= fopen (fn
.to_str0 (), "rb");
54 warning (_f ("can't open file: `%s'", fn
.to_str0 ()));
58 int ret
= fseek (f
, 0, SEEK_END
);
62 char * str
= new char[*len
+1];
64 ret
= fread (str
, sizeof (char), *len
, f
);
67 warning (_f ("Huh? Got %d, expected %d characters", ret
, *len
));
78 Source_file::Source_file (String filename
, String data
)
80 name_string_
= filename
;
82 contents_str0_
= data
.get_copy_str0();
83 length_
= data
.length();
84 pos_str0_
= to_str0 ();
88 Source_file::Source_file (String filename_string
)
90 name_string_
= filename_string
;
94 if (filename_string
== "-")
97 contents_str0_
= gulp_file (filename_string
, &length_
);
99 pos_str0_
= to_str0 ();
103 for (int i
= 0; i
< length_
; i
++)
104 if (contents_str0_
[i
] == '\n')
105 newline_locations_
.push (contents_str0_
+ i
);
109 Source_file::init_port ()
111 SCM str
=scm_makfrom0str (contents_str0_
);
113 str_port_
= scm_mkstrport (SCM_INUM0
, str
, SCM_OPN
| SCM_RDNG
,
115 scm_set_port_filename_x (str_port_
,
116 scm_makfrom0str (name_string_
.get_str0()));
120 Source_file::tell () const
122 return pos_str0_
- contents_str0_
;
126 Source_file::get_istream ()
130 if (length ()) // can-t this be done without such a hack?
131 istream_
= new std::istringstream (to_str0 ());
134 istream_
= new std::istringstream ("");
135 istream_
->setstate (std::ios::eofbit
);
136 // istream_->set (ios::eofbit);
143 Source_file::file_line_column_string (char const *context_str0
) const
146 return " (" + _ ("position unknown") + ")";
148 return name_string () + ":" + to_string (get_line (context_str0
))
149 + ":" + to_string (get_char (context_str0
));
153 Source_file::name_string () const
158 Source_file::~Source_file ()
162 delete[] contents_str0_
;
166 Source_file::line_slice (char const* pos_str0
) const
168 if (!in_b (pos_str0
))
171 char const* data_str0
= to_str0 ();
172 char const * eof_C_
= data_str0
+ length ();
174 if (pos_str0
== eof_C_
)
176 char const* begin_str0
= pos_str0
;
177 while (begin_str0
> data_str0
)
178 if (*--begin_str0
== '\n')
184 char const* end_str0
= pos_str0
;
185 while (end_str0
< eof_C_
)
186 if (*end_str0
++ == '\n')
192 return Slice (begin_str0
- data_str0
, end_str0
- data_str0
);
196 Source_file::line_string (char const* pos_str0
) const
198 if (!in_b (pos_str0
))
201 Slice line
= line_slice (pos_str0
);
202 char const* data_str0
= to_str0 ();
203 return String ((Byte
const*)data_str0
+ line
[LEFT
], line
.length ());
207 Source_file::get_char (char const* pos_str0
) const
209 if (!in_b (pos_str0
))
212 char const* data_str0
= to_str0 ();
213 return pos_str0
- (line_slice (pos_str0
)[SMALLER
] + data_str0
);
217 Source_file::get_column (char const* pos_str0
) const
219 if (!in_b (pos_str0
))
222 int ch_i
= get_char (pos_str0
);
223 String line
= line_string (pos_str0
);
226 for (int i
= 0; i
< ch_i
; i
++)
228 col_i
= (col_i
/ 8 + 1) * 8;
236 Source_file::error_string (char const* pos_str0
) const
238 if (!in_b (pos_str0
))
239 return " (" + _ ("position unknown") + ")";
241 int ch_i
= get_char (pos_str0
);
242 String line
= line_string (pos_str0
);
243 String context
= line
.left_string (ch_i
)
245 + to_string (' ', get_column (pos_str0
))
246 + line
.cut_string (ch_i
, INT_MAX
);
252 Source_file::in_b (char const* pos_str0
) const
254 return (pos_str0
&& (pos_str0
>= to_str0 ()) && (pos_str0
<= to_str0 () + length ()));
258 Source_file::get_line (char const* pos_str0
) const
260 if (!in_b (pos_str0
))
263 if (!newline_locations_
.size())
267 int hi
= newline_locations_
.size();
269 if (newline_locations_
[lo
] > pos_str0
)
272 if (newline_locations_
[hi
-1] < pos_str0
)
275 binary_search_bounds (newline_locations_
,
277 Link_array
<char>::default_compare
,
280 if (*pos_str0
== '\n')
286 Source_file::length () const
292 Source_file::to_str0 () const
294 return contents_str0_
;
298 Source_file::set_pos (char const * pos_str0
)
301 pos_str0_
= pos_str0
;
303 error (error_string (pos_str0
) + "invalid pos");
307 Source_file::seek_str0 (int n
)
309 char const* new_str0
= to_str0 () + n
;
311 new_str0
+= length ();
313 pos_str0_
= new_str0
;
315 error (error_string (new_str0
) + "seek past eof");
321 Source_file::forward_str0 (int n
)
323 char const* old_pos
= pos_str0_
;
324 char const* new_str0
= pos_str0_
+ n
;
326 pos_str0_
= new_str0
;
328 error (error_string (new_str0
) + "forward past eof");
334 Source_file::get_string (int n
)
336 String str
= String ((Byte
const*)forward_str0 (n
), n
);