lilypond-1.1.36
[lilypond.git] / lib / source-file.cc
blob46d1f142387ae388bd54b03d4508df906b222bcd
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 "plist.hh"
17 #include "warn.hh"
18 #include "thank-you-cygnus.hh"
19 #include "source-file.hh"
20 #include "simple-file-storage.hh"
21 #include "string-storage.hh"
23 Source_file::Source_file (String filename_str)
25 name_str_ = filename_str;
26 istream_p_ = 0;
27 storage_p_ = new Simple_file_storage (filename_str);
28 pos_ch_C_ = ch_C ();
31 Source_file::Source_file (String name_str, String data_str)
33 name_str_ = name_str;
34 istream_p_ = 0;
35 storage_p_ = new String_storage (data_str);
36 pos_ch_C_ = ch_C ();
39 istream*
40 Source_file::istream_l ()
43 if (!name_str_.length_i ())
44 return &cin;
47 if (!istream_p_)
49 if (length_i ()) // can-t this be done without such a hack?
50 istream_p_ = new istrstream (ch_C (), length_i ());
51 else
53 istream_p_ = new istrstream ("", 0);
54 istream_p_->set (ios::eofbit);
57 return istream_p_;
60 String
61 Source_file::file_line_column_str (char const *context_ch_C) const
63 if (!ch_C ())
64 return "(" + _ ("position unknown") + ")";
65 else
66 return name_str () + ":" + to_str (line_i (context_ch_C))
67 + ":" + to_str (char_i (context_ch_C));
70 String
71 Source_file::name_str () const
73 return name_str_;
76 Source_file::~Source_file ()
78 delete istream_p_;
79 istream_p_ = 0;
80 delete storage_p_;
83 Slice
84 Source_file::line_slice (char const* pos_ch_C) const
86 if (!in_b (pos_ch_C))
87 return Slice (0,0);
89 char const* data_ch_C = ch_C ();
90 char const * eof_C_ = data_ch_C + length_i ();
92 if (pos_ch_C == eof_C_)
93 pos_ch_C --;
94 char const* begin_ch_C = pos_ch_C;
95 while (begin_ch_C > data_ch_C)
96 if (*--begin_ch_C == '\n')
98 begin_ch_C++;
99 break;
102 char const* end_ch_C = pos_ch_C;
103 while (end_ch_C < eof_C_)
104 if (*end_ch_C++ == '\n')
106 end_ch_C--;
107 break;
110 return Slice (begin_ch_C - data_ch_C, end_ch_C - data_ch_C);
113 String
114 Source_file::line_str (char const* pos_ch_C) const
116 if (!in_b (pos_ch_C))
117 return "";
119 Slice line = line_slice (pos_ch_C);
120 char const* data_ch_C = ch_C ();
121 return String ((Byte const*)data_ch_C + line.min (), line.length ());
125 Source_file::char_i (char const* pos_ch_C) const
127 if (!in_b (pos_ch_C))
128 return 0;
130 char const* data_ch_C = ch_C ();
131 return pos_ch_C - (line_slice (pos_ch_C).min () + data_ch_C);
135 Source_file::column_i (char const* pos_ch_C) const
137 if (!in_b (pos_ch_C))
138 return 0;
140 int ch_i = char_i (pos_ch_C);
141 String line = line_str (pos_ch_C);
143 int col_i = 0;
144 for (int i = 0; i < ch_i; i++)
145 if (line[i] == '\t')
146 col_i = (col_i / 8 + 1) * 8;
147 else
148 col_i++;
150 return col_i;
153 String
154 Source_file::error_str (char const* pos_ch_C) const
156 if (!in_b (pos_ch_C))
157 return "(" + _ ("position unknown") + ")";
159 int ch_i = char_i (pos_ch_C);
160 String line = line_str (pos_ch_C);
161 String context = line.left_str (ch_i)
162 + to_str ('\n')
163 + to_str (' ', column_i (pos_ch_C))
164 + line.cut_str (ch_i, INT_MAX);
166 return context;
169 bool
170 Source_file::in_b (char const* pos_ch_C) const
172 return (pos_ch_C && (pos_ch_C >= ch_C ()) && (pos_ch_C <= ch_C () + length_i ()));
176 Source_file::line_i (char const* pos_ch_C) const
178 if (!in_b (pos_ch_C))
179 return 0;
181 int i = 1;
182 char const* scan_ch_C = ch_C ();
183 if (!scan_ch_C)
184 return 0;
186 while (scan_ch_C < pos_ch_C)
187 if (*scan_ch_C++ == '\n')
188 i++;
189 return i;
193 Source_file::length_i () const
195 return storage_p_->length_i ();
198 char const *
199 Source_file::ch_C () const
201 return storage_p_->ch_C ();
204 void
205 Source_file::set_pos (char const * pos_ch_C)
207 if (in_b (pos_ch_C))
208 pos_ch_C_ = pos_ch_C;
209 else
210 error (error_str (pos_ch_C) + "invalid pos");
213 char const*
214 Source_file::seek_ch_C (int n)
216 char const* new_ch_C = ch_C () + n;
217 if (n < 0)
218 new_ch_C += length_i ();
219 if (in_b (new_ch_C))
220 pos_ch_C_ = new_ch_C;
221 else
222 error (error_str (new_ch_C) + "seek past eof");
224 return pos_ch_C_;
227 char const*
228 Source_file::forward_ch_C (int n)
230 char const* old_pos_C = pos_ch_C_;
231 char const* new_ch_C = pos_ch_C_ + n;
232 if (in_b (new_ch_C))
233 pos_ch_C_ = new_ch_C;
234 else
235 error (error_str (new_ch_C) + "forward past eof");
237 return old_pos_C;
240 String
241 Source_file::get_str (int n)
243 String str ((Byte const*)forward_ch_C (n), n);
244 return str;