lilypond-1.0.8
[lilypond.git] / src / sourcefile.cc
blob5caa8545fa3ed86d8a4a678745e2de7f125a03da
1 //
2 // sourcefile.cc
3 //
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>
17 #include "string.hh"
18 #include "proto.hh"
19 #include "plist.hh"
20 #include "lexer.hh"
21 #include "debug.hh"
22 #include "parseconstruct.hh"
23 #include "main.hh" // find_file
25 #include "sourcefile.hh"
27 Source_file::Source_file( String &filename_str )
29 data_caddr_ = 0;
30 fildes_i_ = 0;
31 size_off_ = 0;
32 name_str_ = filename_str;
33 istream_p_ = 0;
35 open();
36 map();
37 // ugh!?, should call name_str() !
38 filename_str = name_str_;
41 Source_file::~Source_file()
43 delete istream_p_;
44 istream_p_ = 0;
45 unmap();
46 close();
49 char const*
50 Source_file::ch_c_l()
52 assert( this );
53 return (char const*)data_caddr_;
56 void
57 Source_file::close()
59 if ( fildes_i_ ) {
60 ::close( fildes_i_ );
61 fildes_i_ = 0;
65 String
66 Source_file::error_str( char const* pos_ch_c_l )
68 assert( this );
69 if ( !in_b( pos_ch_c_l ) )
70 return "";
72 char const* begin_ch_c_l = pos_ch_c_l;
73 char const* data_ch_c_l = ch_c_l();
74 while ( begin_ch_c_l > data_ch_c_l )
75 if ( *--begin_ch_c_l == '\n' ) {
76 begin_ch_c_l++;
77 break;
80 char const* end_ch_c_l = pos_ch_c_l;
81 while ( end_ch_c_l < data_ch_c_l + size_off_ )
82 if ( *end_ch_c_l++ == '\n' ) {
83 break;
85 end_ch_c_l--;
87 #if 1
88 // String( char const* p, int length ) is missing!?
89 String line_str( (Byte const*)begin_ch_c_l, end_ch_c_l - begin_ch_c_l );
90 #else
91 int length_i = end_ch_c_l - begin_ch_c_l;
92 char* ch_p = new char[ length_i + 1 ];
93 strncpy( ch_p, begin_ch_c_l, length_i );
94 ch_p[ length_i ] = 0;
95 String line_str( ch_p );
96 delete ch_p;
97 #endif
99 int error_col_i = 0;
100 char const* scan_ch_c_l = begin_ch_c_l;
101 while ( scan_ch_c_l < pos_ch_c_l )
102 if ( *scan_ch_c_l++ == '\t' )
103 error_col_i = ( error_col_i / 8 + 1 ) * 8;
104 else
105 error_col_i++;
107 String str = line_str.left_str( pos_ch_c_l - begin_ch_c_l )
108 + String( '\n' )
109 + String( ' ', error_col_i )
110 + line_str.mid_str( pos_ch_c_l - begin_ch_c_l + 1, INT_MAX ); // String::mid should take 0 arg..
111 return str;
114 bool
115 Source_file::in_b( char const* pos_ch_c_l )
117 return ( pos_ch_c_l && ( pos_ch_c_l >= ch_c_l() ) && ( pos_ch_c_l < ch_c_l() + size_off_ ) );
120 istream*
121 Source_file::istream_l()
123 assert( fildes_i_ );
124 if ( !istream_p_ ) {
125 if ( size_off_ ) // can-t this be done without such a hack?
126 istream_p_ = new istrstream( ch_c_l(), size_off_ );
127 else {
128 istream_p_ = new istrstream( "", 0 );
129 istream_p_->set(ios::eofbit);
132 return istream_p_;
135 off_t
136 Source_file::length_off()
138 return size_off_;
142 Source_file::line_i( char const* pos_ch_c_l )
144 if ( !in_b( pos_ch_c_l ) )
145 return 0;
147 int i = 1;
148 char const* scan_ch_c_l = ch_c_l();
149 while ( scan_ch_c_l < pos_ch_c_l )
150 if ( *scan_ch_c_l++ == '\n' )
151 i++;
152 return i;
155 void
156 Source_file::map()
158 if ( fildes_i_ == -1 )
159 return;
161 data_caddr_ = (caddr_t)mmap( (void*)0, size_off_, PROT_READ, MAP_SHARED, fildes_i_, 0 );
163 if ( (int)data_caddr_ == -1 )
164 // ugh: defined_ch_c_l...
165 warning( String( "can't map: " ) + name_str_ + String( ": " ) + strerror( errno ), defined_ch_c_l ); //lexer->here_ch_c_l() );
168 String
169 Source_file::name_str()
171 return name_str_;
174 void
175 Source_file::open()
177 String name_str = find_file( name_str_ );
178 if ( name_str != "" )
179 name_str_ = name_str;
181 fildes_i_ = ::open( name_str_, O_RDONLY );
183 if ( fildes_i_ == -1 ) {
184 warning( String( "can't open: " ) + name_str_ + String( ": " ) + strerror( errno ), defined_ch_c_l ); // lexer->here_ch_c_l() );
185 return;
188 struct stat file_stat;
189 fstat( fildes_i_, &file_stat );
190 size_off_ = file_stat.st_size;
193 void
194 Source_file::unmap()
196 if ( data_caddr_ ) {
197 munmap( data_caddr_, size_off_ );
198 data_caddr_ = 0;
199 size_off_ = 0;
202 String
203 Source_file::file_line_no_str(char const *ch_c_l )
205 return name_str() + ": "
206 + String( line_i( ch_c_l ) );