]> git.donarmstrong.com Git - lilypond.git/blob - lib/source-file.cc
release: 1.0.1
[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--1998 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 }
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 }
36
37 istream*
38 Source_file::istream_l ()
39 {
40   /*
41     if (!name_str_.length_i ())
42       return &cin;
43     */
44
45   if (!istream_p_)
46     {
47       if (length_i ()) // can-t this be done without such a hack?
48         istream_p_ = new istrstream (ch_C (), length_i ());
49       else
50         {
51           istream_p_ = new istrstream ("", 0);
52           istream_p_->set (ios::eofbit);
53         }
54     }
55   return istream_p_;
56 }
57
58 String
59 Source_file::file_line_column_str (char const *context_ch_C) const
60 {
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));
66 }
67
68 String
69 Source_file::name_str () const
70 {
71   return name_str_;
72 }
73
74 Source_file::~Source_file ()
75 {
76   delete istream_p_;
77   istream_p_ = 0;
78   delete storage_p_;
79 }
80
81 Slice
82 Source_file::line_slice (char const* pos_ch_C) const
83 {
84   if (!in_b (pos_ch_C))
85     return Slice (0,0);
86
87   char const* data_ch_C = ch_C ();
88   char const * eof_C_ = data_ch_C + length_i ();
89
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')
95       {
96         begin_ch_C++;
97         break;
98       }
99
100   char const* end_ch_C = pos_ch_C;
101   while (end_ch_C < eof_C_)
102     if (*end_ch_C++ == '\n')
103       {
104         end_ch_C--;
105         break;
106       }
107
108   return Slice (begin_ch_C - data_ch_C, end_ch_C - data_ch_C);
109 }
110
111 String
112 Source_file::line_str (char const* pos_ch_C) const
113 {
114   if (!in_b (pos_ch_C))
115     return "";
116
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.min (), line.length ());
120 }
121
122 int
123 Source_file::char_i (char const* pos_ch_C) const
124 {
125   if (!in_b (pos_ch_C))
126     return 0;
127
128   char const* data_ch_C = ch_C ();
129   return pos_ch_C - (line_slice (pos_ch_C).min () + data_ch_C);
130 }
131
132 int
133 Source_file::column_i (char const* pos_ch_C) const
134 {
135   if (!in_b (pos_ch_C))
136     return 0;
137
138   int ch_i = char_i (pos_ch_C);
139   String line = line_str (pos_ch_C);
140
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++;
147
148   return col_i;
149 }
150
151 String
152 Source_file::error_str (char const* pos_ch_C) const
153 {
154   if (!in_b (pos_ch_C))
155     return "(" + _ ("position unknown") + ")";
156
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);
163
164   return context;
165 }
166
167 bool
168 Source_file::in_b (char const* pos_ch_C) const
169 {
170   return (pos_ch_C && (pos_ch_C >= ch_C ()) && (pos_ch_C <= ch_C () + length_i ()));
171 }
172
173 int
174 Source_file::line_i (char const* pos_ch_C) const
175 {
176   if (!in_b (pos_ch_C))
177     return 0;
178
179   int i = 1;
180   char const* scan_ch_C = ch_C ();
181   if (!scan_ch_C)
182     return 0;
183
184   while (scan_ch_C < pos_ch_C)
185     if (*scan_ch_C++ == '\n')
186       i++;
187   return i;
188 }
189
190 int
191 Source_file::length_i () const
192 {
193   return storage_p_->length_i ();
194 }
195
196 char const *
197 Source_file::ch_C () const
198 {
199   return storage_p_->ch_C ();
200 }