]> git.donarmstrong.com Git - lilypond.git/blob - lib/source-file.cc
8f28f9b5f5bb857b5776f41c0f38da662f65426c
[lilypond.git] / lib / source-file.cc
1 //
2 // source-file.cc
3 //
4
5 #include <sys/types.h>          // open, mmap
6 #include <sys/stat.h>           // open
7 #include <sys/mman.h>           // mmap
8 #include <limits.h>             // INT_MAX
9 #include <fcntl.h>              // open 
10 #include <unistd.h>             // close, stat
11 #include <stdio.h>              // fdopen
12 #include <string.h>             // strerror
13 #include <errno.h>              // errno
14 #include <assert.h>
15 #include <strstream.h>
16
17 #include "string.hh"
18 #include "proto.hh"
19 #include "plist.hh"
20
21
22 #include "warn.hh"
23 #include "windhoos-suck-suck-suck-thank-you-cygnus.hh"
24
25 #include "source-file.hh"
26
27 Source_file::Source_file( String filename_str )
28 {
29     data_caddr_ = 0;
30     fildes_i_ = 0;
31     size_off_ = 0;
32     name_str_ = filename_str;
33     istream_p_ = 0;
34
35     open();
36     if ( fildes_i_ > 0 )
37         map();
38 }
39
40 istream*
41 Source_file::istream_l()
42 {
43     if ( !fildes_i_ )
44         return &cin;
45     if ( !istream_p_ ) {
46         if ( size_off_ ) // can-t this be done without such a hack?
47             istream_p_ = new istrstream( ch_C(), size_off_ );
48         else {
49             istream_p_ = new istrstream( "", 0 );
50             istream_p_->set(ios::eofbit);
51         }
52     }
53     return istream_p_;
54 }
55
56 Source_file::~Source_file()
57 {
58     delete istream_p_;
59     istream_p_ = 0;
60     unmap();
61     close();
62 }
63
64 char const*
65 Source_file::ch_C()
66 {
67     assert( this );
68     return (char const*)data_caddr_;
69 }
70
71 void
72 Source_file::close()
73 {
74     if ( fildes_i_ ) {
75         ::close( fildes_i_ );
76         fildes_i_ = 0;
77     }
78 }
79
80 String
81 Source_file::error_str( char const* pos_ch_C )
82 {
83     char const* data_ch_C = ch_C();
84     char const * eof_C_ = data_ch_C + size_off_;
85     if ( !in_b( pos_ch_C ) )
86         return "(position unknown)";
87
88     
89     if ( pos_ch_C == eof_C_)
90         pos_ch_C --;
91     char const* begin_ch_C = pos_ch_C;
92     while ( begin_ch_C > data_ch_C )
93         if ( *--begin_ch_C == '\n' ) {
94             begin_ch_C++;
95             break;
96         }
97
98     char const* end_ch_C = pos_ch_C;
99     while ( end_ch_C < eof_C_ )
100         if ( *end_ch_C++ == '\n' ) {
101           end_ch_C--;
102           break;
103         }
104   
105         //    String( char const* p, int length ) is missing!?
106     String line_str( (Byte const*)begin_ch_C, end_ch_C - begin_ch_C );
107
108     int error_col_i = 0;
109     char const* scan_ch_C = begin_ch_C;
110     while ( scan_ch_C < pos_ch_C )
111         if ( *scan_ch_C++ == '\t' )
112             error_col_i = ( error_col_i / 8 + 1 ) * 8;
113         else
114             error_col_i++;
115
116     String str = line_str.left_str( pos_ch_C - begin_ch_C ) 
117         + String( '\n' )
118         + String( ' ', error_col_i ) 
119         + line_str.mid_str( pos_ch_C - begin_ch_C, INT_MAX ); // String::mid should take 0 arg..
120     return str;
121 }
122
123 bool
124 Source_file::in_b( char const* pos_ch_C )
125 {
126     return ( pos_ch_C && ( pos_ch_C >= ch_C() ) && ( pos_ch_C <= ch_C() + size_off_ ) );
127 }
128
129 off_t
130 Source_file::length_off()
131 {
132     return size_off_;
133 }
134
135 int
136 Source_file::line_i( char const* pos_ch_C )
137 {
138     if ( !in_b( pos_ch_C ) )
139         return 0;
140
141     int i = 1;
142     char const* scan_ch_C = ch_C();
143     while ( scan_ch_C < pos_ch_C )
144         if ( *scan_ch_C++ == '\n' )
145                 i++;
146     return i;
147 }
148
149 void
150 Source_file::map()
151 {
152     if ( fildes_i_ == -1 )
153         return;
154
155     data_caddr_ = (caddr_t)mmap( (void*)0, size_off_, PROT_READ, MAP_SHARED, fildes_i_, 0 );
156
157     if ( (int)data_caddr_ == -1 )
158         warning( String( "can't map: " ) + name_str_ + String( ": " ) + strerror( errno ));
159 }
160
161 String
162 Source_file::name_str()
163 {
164     return name_str_;
165 }
166
167 void
168 Source_file::open()
169 {
170     if ( !name_str_.length_i() || ( name_str_ == "-" ) ) {
171         fildes_i_ = 0;
172         return;
173     }
174
175     fildes_i_ = ::open( name_str_, O_RDONLY );  
176             
177     if ( fildes_i_ == -1 ) {
178         warning( String( "can't open: " ) + name_str_ + String( ": " ) + strerror( errno )); 
179         return;
180     }
181
182     struct stat file_stat;
183     fstat( fildes_i_, &file_stat );
184     size_off_ = file_stat.st_size;
185 }
186
187 void
188 Source_file::unmap()
189 {
190     if ( data_caddr_ ) {
191         munmap( data_caddr_, size_off_ );
192         data_caddr_ = 0;
193         size_off_ = 0;
194     }
195 }
196 String
197 Source_file::file_line_no_str(char const *ch_C )
198 {
199     return name_str() + ": "
200         + String( line_i( ch_C ) );
201 }