]> git.donarmstrong.com Git - lilypond.git/blob - lib/source-file.cc
release: 0.1.64
[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 <jan@digicash.com>
7   & Han-Wen Nienhuys <hanwen@stack.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 "windhoos-suck-suck-suck-thank-you-cygnus.hh"
19 #include "source-file.hh"
20 #include "simple-file-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 }
28
29 istream*
30 Source_file::istream_l ()
31 {
32   /*
33     if (!name_str_.length_i ())
34       return &cin;
35     */
36
37   if (!istream_p_)
38     {
39       if (length_i ()) // can-t this be done without such a hack?
40         istream_p_ = new istrstream (ch_C (), length_i ());
41       else
42         {
43           istream_p_ = new istrstream ("", 0);
44           istream_p_->set (ios::eofbit);
45         }
46     }
47   return istream_p_;
48 }
49
50 String
51 Source_file::file_line_column_str (char const *context_ch_C) const
52 {
53   if  (!ch_C ())
54     return _ ("(unknown)");
55   else
56     return name_str () + ":" + String (line_i (context_ch_C))
57       + ":" + String (char_i (context_ch_C));
58 }
59
60 String
61 Source_file::name_str () const
62 {
63   return name_str_;
64 }
65
66 Source_file::~Source_file ()
67 {
68   delete istream_p_;
69   istream_p_ = 0;
70   delete storage_p_;
71 }
72
73 Slice
74 Source_file::line_slice (char const* pos_ch_C) const
75 {
76   if (!in_b (pos_ch_C))
77     return Slice (0,0);
78
79   char const* data_ch_C = ch_C ();
80   char const * eof_C_ = data_ch_C + length_i ();
81
82   if (pos_ch_C == eof_C_)
83     pos_ch_C --;
84   char const* begin_ch_C = pos_ch_C;
85   while (begin_ch_C > data_ch_C)
86     if (*--begin_ch_C == '\n')
87       {
88         begin_ch_C++;
89         break;
90       }
91
92   char const* end_ch_C = pos_ch_C;
93   while (end_ch_C < eof_C_)
94     if (*end_ch_C++ == '\n')
95       {
96         end_ch_C--;
97         break;
98       }
99
100   return Slice (begin_ch_C - data_ch_C, end_ch_C - data_ch_C);
101 }
102
103 String
104 Source_file::line_str (char const* pos_ch_C) const
105 {
106   if (!in_b (pos_ch_C))
107     return "";
108
109   Slice line = line_slice (pos_ch_C);
110   char const* data_ch_C = ch_C ();
111   return String ((Byte const*)data_ch_C + line.min (), line.length ());
112 }
113
114 int
115 Source_file::char_i (char const* pos_ch_C) const
116 {
117   if (!in_b (pos_ch_C))
118     return 0;
119
120   char const* data_ch_C = ch_C ();
121   return pos_ch_C - (line_slice (pos_ch_C).min () + data_ch_C);
122 }
123
124 int
125 Source_file::column_i (char const* pos_ch_C) const
126 {
127   if (!in_b (pos_ch_C))
128     return 0;
129
130   int ch_i = char_i (pos_ch_C);
131   String line = line_str (pos_ch_C);
132
133   int col_i = 0;
134   for (int i = 0; i < ch_i; i++)
135     if (line[i] == '\t')
136       col_i = (col_i / 8 + 1) * 8;
137     else
138       col_i++;
139
140   return col_i;
141 }
142
143 String
144 Source_file::error_str (char const* pos_ch_C) const
145 {
146   if (!in_b (pos_ch_C))
147     return _ ("(position unknown)");
148
149   int ch_i = char_i (pos_ch_C);
150   String line = line_str (pos_ch_C);
151   String context = line.left_str (ch_i)
152     + String ('\n')
153     + String (' ', column_i (pos_ch_C))
154     + line.cut (ch_i, INT_MAX);
155
156   return context;
157 }
158
159 bool
160 Source_file::in_b (char const* pos_ch_C) const
161 {
162   return (pos_ch_C && (pos_ch_C >= ch_C ()) && (pos_ch_C <= ch_C () + length_i ()));
163 }
164
165 int
166 Source_file::line_i (char const* pos_ch_C) const
167 {
168   if (!in_b (pos_ch_C))
169     return 0;
170
171   int i = 1;
172   char const* scan_ch_C = ch_C ();
173   if (!scan_ch_C)
174     return 0;
175
176   while (scan_ch_C < pos_ch_C)
177     if (*scan_ch_C++ == '\n')
178       i++;
179   return i;
180 }
181
182 int
183 Source_file::length_i () const
184 {
185   return storage_p_->length_i ();
186 }
187
188 char const *
189 Source_file::ch_C () const
190 {
191   return storage_p_->ch_C ();
192 }