]> git.donarmstrong.com Git - lilypond.git/blob - src/source-file.cc
partial: 0.0.39-1.jcn
[lilypond.git] / src / 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 #include "lexer.hh"
21 #include "debug.hh"
22 #include "parseconstruct.hh"
23 #include "main.hh"              // find_file
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     map();
37     // ugh!?, should call name_str() ! 
38     filename_str = name_str_;
39 }
40
41 Source_file::~Source_file()
42 {
43     delete istream_p_;
44     istream_p_ = 0;
45     unmap();
46     close();
47 }
48
49 char const*
50 Source_file::ch_c_l()
51 {
52     assert( this );
53     return (char const*)data_caddr_;
54 }
55
56 void
57 Source_file::close()
58 {
59     if ( fildes_i_ ) {
60         ::close( fildes_i_ );
61         fildes_i_ = 0;
62     }
63 }
64
65 String
66 Source_file::error_str( char const* pos_ch_c_l )
67 {
68     assert( this );
69     if ( !in_b( pos_ch_c_l ) )
70         return "";
71
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;
78         }
79
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;
84         }
85     end_ch_c_l--;
86
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
98
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++;
106
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;
112 }
113
114 bool
115 Source_file::in_b( char const* pos_ch_c_l )
116 {
117     return ( pos_ch_c_l && ( pos_ch_c_l >= ch_c_l() ) && ( pos_ch_c_l < ch_c_l() + size_off_ ) );
118 }
119
120 istream*
121 Source_file::istream_l()
122 {
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);
130         }
131     }
132     return istream_p_;
133 }
134
135 off_t
136 Source_file::length_off()
137 {
138     return size_off_;
139 }
140
141 int
142 Source_file::line_i( char const* pos_ch_c_l )
143 {
144     if ( !in_b( pos_ch_c_l ) )
145         return 0;
146
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;
153 }
154
155 void
156 Source_file::map()
157 {
158     if ( fildes_i_ == -1 )
159         return;
160
161     data_caddr_ = (caddr_t)mmap( (void*)0, size_off_, PROT_READ, MAP_SHARED, fildes_i_, 0 );
162
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() );
166 }
167
168 String
169 Source_file::name_str()
170 {
171     return name_str_;
172 }
173
174 void
175 Source_file::open()
176 {
177     String name_str = find_file( name_str_ );
178     if ( name_str != "" ) 
179         name_str_ = name_str;
180
181     fildes_i_ = ::open( name_str_, O_RDONLY );  
182             
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;
186     }
187
188     struct stat file_stat;
189     fstat( fildes_i_, &file_stat );
190     size_off_ = file_stat.st_size;
191 }
192
193 void
194 Source_file::unmap()
195 {
196     if ( data_caddr_ ) {
197         munmap( data_caddr_, size_off_ );
198         data_caddr_ = 0;
199         size_off_ = 0;
200     }
201 }
202 String
203 Source_file::file_line_no_str(char const *ch_c_l )
204 {
205     return name_str() + ": "
206         + String( line_i( ch_c_l ) );
207 }