lilypond-1.5.33
[lilypond.git] / lib / source-file.cc
blobc5e5b1dd347c2596b84f7efc3529ebc4c3a5cd01
1 /*
2 source-file.cc -- implement Source_file
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2000 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 "source-file.hh"
18 #include "simple-file-storage.hh"
19 #include "string-storage.hh"
21 Source_file::Source_file (String filename_str)
23 name_str_ = filename_str;
24 istream_p_ = 0;
25 storage_p_ = new Simple_file_storage (filename_str);
26 pos_ch_C_ = ch_C ();
29 Source_file::Source_file (String name_str, String data_str)
31 name_str_ = name_str;
32 istream_p_ = 0;
33 storage_p_ = new String_storage (data_str);
34 pos_ch_C_ = ch_C ();
37 istream*
38 Source_file::istream_l ()
41 if (!name_str_.length_i ())
42 return &cin;
45 if (!istream_p_)
47 if (length_i ()) // can-t this be done without such a hack?
48 istream_p_ = new istrstream (ch_C (), length_i ());
49 else
51 istream_p_ = new istrstream ("", 0);
52 istream_p_->set (ios::eofbit);
55 return istream_p_;
58 String
59 Source_file::file_line_column_str (char const *context_ch_C) const
61 if (!ch_C ())
62 return "(" + _ ("position unknown") + ")";
63 else
64 return name_str () + ":" + to_str (line_i (context_ch_C))
65 + ":" + to_str (char_i (context_ch_C));
68 String
69 Source_file::name_str () const
71 return name_str_;
74 Source_file::~Source_file ()
76 delete istream_p_;
77 istream_p_ = 0;
78 delete storage_p_;
81 Slice
82 Source_file::line_slice (char const* pos_ch_C) const
84 if (!in_b (pos_ch_C))
85 return Slice (0,0);
87 char const* data_ch_C = ch_C ();
88 char const * eof_C_ = data_ch_C + length_i ();
90 if (pos_ch_C == eof_C_)
91 pos_ch_C --;
92 char const* begin_ch_C = pos_ch_C;
93 while (begin_ch_C > data_ch_C)
94 if (*--begin_ch_C == '\n')
96 begin_ch_C++;
97 break;
100 char const* end_ch_C = pos_ch_C;
101 while (end_ch_C < eof_C_)
102 if (*end_ch_C++ == '\n')
104 end_ch_C--;
105 break;
108 return Slice (begin_ch_C - data_ch_C, end_ch_C - data_ch_C);
111 String
112 Source_file::line_str (char const* pos_ch_C) const
114 if (!in_b (pos_ch_C))
115 return "";
117 Slice line = line_slice (pos_ch_C);
118 char const* data_ch_C = ch_C ();
119 return String ((Byte const*)data_ch_C + line[LEFT], line.length ());
123 Source_file::char_i (char const* pos_ch_C) const
125 if (!in_b (pos_ch_C))
126 return 0;
128 char const* data_ch_C = ch_C ();
129 return pos_ch_C - (line_slice (pos_ch_C)[SMALLER] + data_ch_C);
133 Source_file::column_i (char const* pos_ch_C) const
135 if (!in_b (pos_ch_C))
136 return 0;
138 int ch_i = char_i (pos_ch_C);
139 String line = line_str (pos_ch_C);
141 int col_i = 0;
142 for (int i = 0; i < ch_i; i++)
143 if (line[i] == '\t')
144 col_i = (col_i / 8 + 1) * 8;
145 else
146 col_i++;
148 return col_i;
151 String
152 Source_file::error_str (char const* pos_ch_C) const
154 if (!in_b (pos_ch_C))
155 return "(" + _ ("position unknown") + ")";
157 int ch_i = char_i (pos_ch_C);
158 String line = line_str (pos_ch_C);
159 String context = line.left_str (ch_i)
160 + to_str ('\n')
161 + to_str (' ', column_i (pos_ch_C))
162 + line.cut_str (ch_i, INT_MAX);
164 return context;
167 bool
168 Source_file::in_b (char const* pos_ch_C) const
170 return (pos_ch_C && (pos_ch_C >= ch_C ()) && (pos_ch_C <= ch_C () + length_i ()));
174 Source_file::line_i (char const* pos_ch_C) const
176 if (!in_b (pos_ch_C))
177 return 0;
179 int i = 1;
180 char const* scan_ch_C = ch_C ();
181 if (!scan_ch_C)
182 return 0;
184 while (scan_ch_C < pos_ch_C)
185 if (*scan_ch_C++ == '\n')
186 i++;
187 return i;
191 Source_file::length_i () const
193 return storage_p_->length_i ();
196 char const *
197 Source_file::ch_C () const
199 return storage_p_->ch_C ();
202 void
203 Source_file::set_pos (char const * pos_ch_C)
205 if (in_b (pos_ch_C))
206 pos_ch_C_ = pos_ch_C;
207 else
208 error (error_str (pos_ch_C) + "invalid pos");
211 char const*
212 Source_file::seek_ch_C (int n)
214 char const* new_ch_C = ch_C () + n;
215 if (n < 0)
216 new_ch_C += length_i ();
217 if (in_b (new_ch_C))
218 pos_ch_C_ = new_ch_C;
219 else
220 error (error_str (new_ch_C) + "seek past eof");
222 return pos_ch_C_;
225 char const*
226 Source_file::forward_ch_C (int n)
228 char const* old_pos_C = pos_ch_C_;
229 char const* new_ch_C = pos_ch_C_ + n;
230 if (in_b (new_ch_C))
231 pos_ch_C_ = new_ch_C;
232 else
233 error (error_str (new_ch_C) + "forward past eof");
235 return old_pos_C;
238 String
239 Source_file::get_str (int n)
241 String str ((Byte const*)forward_ch_C (n), n);
242 return str;