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