]> git.donarmstrong.com Git - lilypond.git/blob - lib/source-file.cc
4a1a9a1c300ea92754467772387cdb80e6302569
[lilypond.git] / lib / 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--1999 Jan Nieuwenhuizen <janneke@gnu.org>
7   & Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
9
10
11 #include <assert.h>
12 #include <strstream.h>
13
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"
22
23 Source_file::Source_file (String filename_str)
24 {
25   name_str_ = filename_str;
26   istream_p_ = 0;
27   storage_p_ = new Simple_file_storage (filename_str);
28   pos_ch_C_ = ch_C ();
29 }
30
31 Source_file::Source_file (String name_str, String data_str)
32 {
33   name_str_ = name_str;
34   istream_p_ = 0;
35   storage_p_ = new String_storage (data_str);
36   pos_ch_C_ = ch_C ();
37 }
38
39 istream*
40 Source_file::istream_l ()
41 {
42   /*
43     if (!name_str_.length_i ())
44       return &cin;
45     */
46
47   if (!istream_p_)
48     {
49       if (length_i ()) // can-t this be done without such a hack?
50         istream_p_ = new istrstream (ch_C (), length_i ());
51       else
52         {
53           istream_p_ = new istrstream ("", 0);
54           istream_p_->set (ios::eofbit);
55         }
56     }
57   return istream_p_;
58 }
59
60 String
61 Source_file::file_line_column_str (char const *context_ch_C) const
62 {
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));
68 }
69
70 String
71 Source_file::name_str () const
72 {
73   return name_str_;
74 }
75
76 Source_file::~Source_file ()
77 {
78   delete istream_p_;
79   istream_p_ = 0;
80   delete storage_p_;
81 }
82
83 Slice
84 Source_file::line_slice (char const* pos_ch_C) const
85 {
86   if (!in_b (pos_ch_C))
87     return Slice (0,0);
88
89   char const* data_ch_C = ch_C ();
90   char const * eof_C_ = data_ch_C + length_i ();
91
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')
97       {
98         begin_ch_C++;
99         break;
100       }
101
102   char const* end_ch_C = pos_ch_C;
103   while (end_ch_C < eof_C_)
104     if (*end_ch_C++ == '\n')
105       {
106         end_ch_C--;
107         break;
108       }
109
110   return Slice (begin_ch_C - data_ch_C, end_ch_C - data_ch_C);
111 }
112
113 String
114 Source_file::line_str (char const* pos_ch_C) const
115 {
116   if (!in_b (pos_ch_C))
117     return "";
118
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[LEFT], line.length ());
122 }
123
124 int
125 Source_file::char_i (char const* pos_ch_C) const
126 {
127   if (!in_b (pos_ch_C))
128     return 0;
129
130   char const* data_ch_C = ch_C ();
131   return pos_ch_C - (line_slice (pos_ch_C)[SMALLER] + data_ch_C);
132 }
133
134 int
135 Source_file::column_i (char const* pos_ch_C) const
136 {
137   if (!in_b (pos_ch_C))
138     return 0;
139
140   int ch_i = char_i (pos_ch_C);
141   String line = line_str (pos_ch_C);
142
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++;
149
150   return col_i;
151 }
152
153 String
154 Source_file::error_str (char const* pos_ch_C) const
155 {
156   if (!in_b (pos_ch_C))
157     return "(" + _ ("position unknown") + ")";
158
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);
165
166   return context;
167 }
168
169 bool
170 Source_file::in_b (char const* pos_ch_C) const
171 {
172   return (pos_ch_C && (pos_ch_C >= ch_C ()) && (pos_ch_C <= ch_C () + length_i ()));
173 }
174
175 int
176 Source_file::line_i (char const* pos_ch_C) const
177 {
178   if (!in_b (pos_ch_C))
179     return 0;
180
181   int i = 1;
182   char const* scan_ch_C = ch_C ();
183   if (!scan_ch_C)
184     return 0;
185
186   while (scan_ch_C < pos_ch_C)
187     if (*scan_ch_C++ == '\n')
188       i++;
189   return i;
190 }
191
192 int
193 Source_file::length_i () const
194 {
195   return storage_p_->length_i ();
196 }
197
198 char const *
199 Source_file::ch_C () const
200 {
201   return storage_p_->ch_C ();
202 }
203
204 void
205 Source_file::set_pos (char const * pos_ch_C)
206 {
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");
211 }
212
213 char const*
214 Source_file::seek_ch_C (int n)
215 {
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");
223
224   return pos_ch_C_;
225 }
226
227 char const*
228 Source_file::forward_ch_C (int n)
229 {
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");
236
237   return old_pos_C;
238 }
239
240 String
241 Source_file::get_str (int n)
242 {
243   String str ((Byte const*)forward_ch_C (n), n);
244   return str;
245 }