lilypond-1.2.15
[lilypond.git] / lib / source-file.cc
blobe6ea86aeb854a35c38bb2079d4e8b618b9c405b2
1 /*
2 source-file.cc -- implement Source_file
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--1999 Jan Nieuwenhuizen <janneke@gnu.org>
7 & Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
11 #include <assert.h>
12 #include <strstream.h>
14 #include "string.hh"
15 #include "proto.hh"
16 #include "warn.hh"
17 #include "thank-you-cygnus.hh"
18 #include "source-file.hh"
19 #include "simple-file-storage.hh"
20 #include "string-storage.hh"
22 Source_file::Source_file (String filename_str)
24 name_str_ = filename_str;
25 istream_p_ = 0;
26 storage_p_ = new Simple_file_storage (filename_str);
27 pos_ch_C_ = ch_C ();
30 Source_file::Source_file (String name_str, String data_str)
32 name_str_ = name_str;
33 istream_p_ = 0;
34 storage_p_ = new String_storage (data_str);
35 pos_ch_C_ = ch_C ();
38 istream*
39 Source_file::istream_l ()
42 if (!name_str_.length_i ())
43 return &cin;
46 if (!istream_p_)
48 if (length_i ()) // can-t this be done without such a hack?
49 istream_p_ = new istrstream (ch_C (), length_i ());
50 else
52 istream_p_ = new istrstream ("", 0);
53 istream_p_->set (ios::eofbit);
56 return istream_p_;
59 String
60 Source_file::file_line_column_str (char const *context_ch_C) const
62 if (!ch_C ())
63 return "(" + _ ("position unknown") + ")";
64 else
65 return name_str () + ":" + to_str (line_i (context_ch_C))
66 + ":" + to_str (char_i (context_ch_C));
69 String
70 Source_file::name_str () const
72 return name_str_;
75 Source_file::~Source_file ()
77 delete istream_p_;
78 istream_p_ = 0;
79 delete storage_p_;
82 Slice
83 Source_file::line_slice (char const* pos_ch_C) const
85 if (!in_b (pos_ch_C))
86 return Slice (0,0);
88 char const* data_ch_C = ch_C ();
89 char const * eof_C_ = data_ch_C + length_i ();
91 if (pos_ch_C == eof_C_)
92 pos_ch_C --;
93 char const* begin_ch_C = pos_ch_C;
94 while (begin_ch_C > data_ch_C)
95 if (*--begin_ch_C == '\n')
97 begin_ch_C++;
98 break;
101 char const* end_ch_C = pos_ch_C;
102 while (end_ch_C < eof_C_)
103 if (*end_ch_C++ == '\n')
105 end_ch_C--;
106 break;
109 return Slice (begin_ch_C - data_ch_C, end_ch_C - data_ch_C);
112 String
113 Source_file::line_str (char const* pos_ch_C) const
115 if (!in_b (pos_ch_C))
116 return "";
118 Slice line = line_slice (pos_ch_C);
119 char const* data_ch_C = ch_C ();
120 return String ((Byte const*)data_ch_C + line[LEFT], line.length ());
124 Source_file::char_i (char const* pos_ch_C) const
126 if (!in_b (pos_ch_C))
127 return 0;
129 char const* data_ch_C = ch_C ();
130 return pos_ch_C - (line_slice (pos_ch_C)[SMALLER] + data_ch_C);
134 Source_file::column_i (char const* pos_ch_C) const
136 if (!in_b (pos_ch_C))
137 return 0;
139 int ch_i = char_i (pos_ch_C);
140 String line = line_str (pos_ch_C);
142 int col_i = 0;
143 for (int i = 0; i < ch_i; i++)
144 if (line[i] == '\t')
145 col_i = (col_i / 8 + 1) * 8;
146 else
147 col_i++;
149 return col_i;
152 String
153 Source_file::error_str (char const* pos_ch_C) const
155 if (!in_b (pos_ch_C))
156 return "(" + _ ("position unknown") + ")";
158 int ch_i = char_i (pos_ch_C);
159 String line = line_str (pos_ch_C);
160 String context = line.left_str (ch_i)
161 + to_str ('\n')
162 + to_str (' ', column_i (pos_ch_C))
163 + line.cut_str (ch_i, INT_MAX);
165 return context;
168 bool
169 Source_file::in_b (char const* pos_ch_C) const
171 return (pos_ch_C && (pos_ch_C >= ch_C ()) && (pos_ch_C <= ch_C () + length_i ()));
175 Source_file::line_i (char const* pos_ch_C) const
177 if (!in_b (pos_ch_C))
178 return 0;
180 int i = 1;
181 char const* scan_ch_C = ch_C ();
182 if (!scan_ch_C)
183 return 0;
185 while (scan_ch_C < pos_ch_C)
186 if (*scan_ch_C++ == '\n')
187 i++;
188 return i;
192 Source_file::length_i () const
194 return storage_p_->length_i ();
197 char const *
198 Source_file::ch_C () const
200 return storage_p_->ch_C ();
203 void
204 Source_file::set_pos (char const * pos_ch_C)
206 if (in_b (pos_ch_C))
207 pos_ch_C_ = pos_ch_C;
208 else
209 error (error_str (pos_ch_C) + "invalid pos");
212 char const*
213 Source_file::seek_ch_C (int n)
215 char const* new_ch_C = ch_C () + n;
216 if (n < 0)
217 new_ch_C += length_i ();
218 if (in_b (new_ch_C))
219 pos_ch_C_ = new_ch_C;
220 else
221 error (error_str (new_ch_C) + "seek past eof");
223 return pos_ch_C_;
226 char const*
227 Source_file::forward_ch_C (int n)
229 char const* old_pos_C = pos_ch_C_;
230 char const* new_ch_C = pos_ch_C_ + n;
231 if (in_b (new_ch_C))
232 pos_ch_C_ = new_ch_C;
233 else
234 error (error_str (new_ch_C) + "forward past eof");
236 return old_pos_C;
239 String
240 Source_file::get_str (int n)
242 String str ((Byte const*)forward_ch_C (n), n);
243 return str;