]> git.donarmstrong.com Git - lilypond.git/blob - flower/source-file.cc
``slikken kreng''
[lilypond.git] / flower / source-file.cc
1 /*
2   source-file.cc -- implement Source_file
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--2000 Jan Nieuwenhuizen <janneke@gnu.org>
7   & Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
9
10
11 #include <assert.h>
12 #if HAVE_SSTREAM
13 #include <sstream>
14 #else
15 #include <strstream.h>
16 #define istringstream(x) istrstream(x, length ()) 
17 #endif
18
19 #include "string.hh"
20 #include "flower-proto.hh"
21 #include "warn.hh"
22 #include "source-file.hh"
23 #include "simple-file-storage.hh"
24 #include "string-storage.hh"
25
26 Source_file::Source_file (String filename_string)
27 {
28   name_string_ = filename_string;
29   istream_ = 0;
30   storage_ = new Simple_file_storage (filename_string);
31   pos_str0_ = to_str0 ();
32 }
33
34 Source_file::Source_file (String name_string, String data_string)
35 {
36   name_string_ = name_string;
37   istream_ = 0;
38   storage_ = new String_storage (data_string);
39   pos_str0_ = to_str0 ();
40 }
41
42 std::istream*
43 Source_file::get_istream ()
44 {
45   /*
46     if (!name_string_.length ())
47       return &cin;
48     */
49
50   if (!istream_)
51     {
52       if (length ()) // can-t this be done without such a hack?
53         istream_ = new std::istringstream (to_str0 ());
54       else
55         {
56           istream_ = new std::istringstream ("");
57           istream_->setstate (std::ios::eofbit);
58           //      istream_->set (ios::eofbit);
59         }
60     }
61   return istream_;
62 }
63
64 String
65 Source_file::file_line_column_string (char const *context_str0) const
66 {
67   if (!to_str0 ())
68     return " (" + _ ("position unknown") + ")";
69   else
70     return name_string () + ":" + to_string (get_line (context_str0))
71       + ":" + to_string (get_char (context_str0));
72 }
73
74 String
75 Source_file::name_string () const
76 {
77   return name_string_;
78 }
79
80 Source_file::~Source_file ()
81 {
82   delete istream_;
83   istream_ = 0;
84   delete storage_;
85 }
86
87 Slice
88 Source_file::line_slice (char const* pos_str0) const
89 {
90   if (!in_b (pos_str0))
91     return Slice (0,0);
92
93   char const* data_str0 = to_str0 ();
94   char const * eof_C_ = data_str0 + length ();
95
96   if (pos_str0 == eof_C_)
97     pos_str0 --;
98   char const* begin_str0 = pos_str0;
99   while (begin_str0 > data_str0)
100     if (*--begin_str0 == '\n')
101       {
102         begin_str0++;
103         break;
104       }
105
106   char const* end_str0 = pos_str0;
107   while (end_str0 < eof_C_)
108     if (*end_str0++ == '\n')
109       {
110         end_str0--;
111         break;
112       }
113
114   return Slice (begin_str0 - data_str0, end_str0 - data_str0);
115 }
116
117 String
118 Source_file::line_string (char const* pos_str0) const
119 {
120   if (!in_b (pos_str0))
121     return "";
122
123   Slice line = line_slice (pos_str0);
124   char const* data_str0 = to_str0 ();
125   return String ((Byte const*)data_str0 + line[LEFT], line.length ());
126 }
127
128 int
129 Source_file::get_char (char const* pos_str0) const
130 {
131   if (!in_b (pos_str0))
132     return 0;
133
134   char const* data_str0 = to_str0 ();
135   return pos_str0 - (line_slice (pos_str0)[SMALLER] + data_str0);
136 }
137
138 int
139 Source_file::get_column (char const* pos_str0) const
140 {
141   if (!in_b (pos_str0))
142     return 0;
143
144   int ch_i = get_char (pos_str0);
145   String line = line_string (pos_str0);
146
147   int col_i = 0;
148   for (int i = 0; i < ch_i; i++)
149     if (line[i] == '\t')
150       col_i = (col_i / 8 + 1) * 8;
151     else
152       col_i++;
153
154   return col_i;
155 }
156
157 String
158 Source_file::error_string (char const* pos_str0) const
159 {
160   if (!in_b (pos_str0))
161     return " (" + _ ("position unknown") + ")";
162
163   int ch_i = get_char (pos_str0);
164   String line = line_string (pos_str0);
165   String context = line.left_string (ch_i)
166     + to_string ('\n')
167     + to_string (' ', get_column (pos_str0))
168     + line.cut_string (ch_i, INT_MAX);
169
170   return context;
171 }
172
173 bool
174 Source_file::in_b (char const* pos_str0) const
175 {
176   return (pos_str0 && (pos_str0 >= to_str0 ()) && (pos_str0 <= to_str0 () + length ()));
177 }
178
179 int
180 Source_file::get_line (char const* pos_str0) const
181 {
182   if (!in_b (pos_str0))
183     return 0;
184
185   int i = 1;
186   char const* scan_str0 = to_str0 ();
187   if (!scan_str0)
188     return 0;
189
190   while (scan_str0 < pos_str0)
191     if (*scan_str0++ == '\n')
192       i++;
193   return i;
194 }
195
196 int
197 Source_file::length () const
198 {
199   return storage_->length ();
200 }
201
202 char const *
203 Source_file::to_str0 () const
204 {
205   return storage_->to_str0 ();
206 }
207
208 void
209 Source_file::set_pos (char const * pos_str0)
210 {
211   if (in_b (pos_str0))
212     pos_str0_ = pos_str0;
213   else
214     error (error_string (pos_str0) + "invalid pos");
215 }
216
217 char const*
218 Source_file::seek_str0 (int n)
219 {
220   char const* new_str0 = to_str0 () + n;
221   if (n < 0)
222     new_str0 += length ();
223   if (in_b (new_str0))
224     pos_str0_ = new_str0;
225   else
226     error (error_string (new_str0) + "seek past eof");
227
228   return pos_str0_;
229 }
230
231 char const*
232 Source_file::forward_str0 (int n)
233 {
234   char const* old_pos = pos_str0_;
235   char const* new_str0 = pos_str0_ + n;
236   if (in_b (new_str0))
237     pos_str0_ = new_str0;
238   else
239     error (error_string (new_str0)  + "forward past eof");
240
241   return old_pos;
242 }
243
244 String
245 Source_file::get_string (int n)
246 {
247   String str = String ((Byte const*)forward_str0 (n), n);
248   return str;
249 }