]> git.donarmstrong.com Git - lilypond.git/blob - src/sourcefile.cc
release: 0.0.34
[lilypond.git] / src / sourcefile.cc
1 //
2 // sourcefile.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 "sourcefile.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     filename_str = name_str_;
38 }
39
40 Source_file::~Source_file()
41 {
42     delete istream_p_;
43     istream_p_ = 0;
44     unmap();
45     close();
46 }
47
48 char const*
49 Source_file::ch_c_l()
50 {
51     assert( this );
52     return (char const*)data_caddr_;
53 }
54
55 void
56 Source_file::close()
57 {
58     if ( fildes_i_ ) {
59         ::close( fildes_i_ );
60         fildes_i_ = 0;
61     }
62 }
63
64 String
65 Source_file::error_str( char const* pos_ch_c_l )
66 {
67     assert( this );
68     if ( !in_b( pos_ch_c_l ) )
69         return "";
70
71     char const* begin_ch_c_l = pos_ch_c_l;
72     char const* data_ch_c_l = ch_c_l();
73     while ( begin_ch_c_l > data_ch_c_l )
74         if ( *--begin_ch_c_l == '\n' ) {
75             begin_ch_c_l++;
76             break;
77         }
78
79     char const* end_ch_c_l = pos_ch_c_l;
80     while ( end_ch_c_l < data_ch_c_l + size_off_ )
81         if ( *end_ch_c_l++ == '\n' ) {
82             break;
83         }
84     end_ch_c_l--;
85
86 // String( char const* p, int length ) is missing!?
87 //    String line_str( begin_ch_c_l, end_ch_c_l - begin_ch_c_l );
88
89     int length_i = end_ch_c_l - begin_ch_c_l;
90     char* ch_p = new char[ length_i + 1 ];
91     strncpy( ch_p, begin_ch_c_l, length_i );
92     ch_p[ length_i ] = 0;
93     String line_str( ch_p );
94     delete ch_p;
95
96     int error_col_i = 0;
97     char const* scan_ch_c_l = begin_ch_c_l;
98     while ( scan_ch_c_l < pos_ch_c_l )
99         if ( *scan_ch_c_l++ == '\t' )
100             error_col_i = ( error_col_i / 8 + 1 ) * 8;
101         else
102             error_col_i++;
103
104     String str = line_str.left( pos_ch_c_l - begin_ch_c_l ) 
105         + String( '\n' )
106         + String( ' ', error_col_i ) 
107         + line_str.mid( pos_ch_c_l - begin_ch_c_l + 1, INT_MAX ); // String::mid should take 0 arg..
108     return str;
109 }
110
111 bool
112 Source_file::in_b( char const* pos_ch_c_l )
113 {
114     return ( pos_ch_c_l && ( pos_ch_c_l >= ch_c_l() ) && ( pos_ch_c_l < ch_c_l() + size_off_ ) );
115 }
116
117 istream*
118 Source_file::istream_l()
119 {
120     assert( fildes_i_ );
121     if ( !istream_p_ ) {
122         if ( size_off_ ) // can-t this be done without such a hack?
123             istream_p_ = new istrstream( ch_c_l(), size_off_ );
124         else {
125             istream_p_ = new istrstream( "", 0 );
126             istream_p_->set(ios::eofbit);
127         }
128     }
129     return istream_p_;
130 }
131
132 int
133 Source_file::line_i( char const* pos_ch_c_l )
134 {
135     if ( !in_b( pos_ch_c_l ) )
136         return 0;
137
138     int i = 1;
139     char const* scan_ch_c_l = ch_c_l();
140     while ( scan_ch_c_l < pos_ch_c_l )
141         if ( *scan_ch_c_l++ == '\n' )
142                 i++;
143     return i;
144 }
145
146 void
147 Source_file::map()
148 {
149     if ( fildes_i_ == -1 )
150         return;
151
152     data_caddr_ = (caddr_t)mmap( (void*)0, size_off_, PROT_READ, MAP_SHARED, fildes_i_, 0 );
153
154     if ( (int)data_caddr_ == -1 )
155         // ugh: defined_ch_c_l...
156         warning( String( "can't map: " ) + name_str_ + String( ": " ) + strerror( errno ), defined_ch_c_l ); //lexer->here_ch_c_l() );
157 }
158
159 String
160 Source_file::name_str()
161 {
162     return name_str_;
163 }
164
165 void
166 Source_file::open()
167 {
168     String name_str = find_file( name_str_ );
169     if ( name_str != "" ) 
170         name_str_ = name_str;
171
172     fildes_i_ = ::open( name_str_, O_RDONLY );  
173             
174     if ( fildes_i_ == -1 ) {
175         warning( String( "can't open: " ) + name_str_ + String( ": " ) + strerror( errno ), defined_ch_c_l ); // lexer->here_ch_c_l() );
176         return;
177     }
178
179     struct stat file_stat;
180     fstat( fildes_i_, &file_stat );
181     size_off_ = file_stat.st_size;
182 }
183
184 void
185 Source_file::unmap()
186 {
187     if ( data_caddr_ ) {
188         munmap( data_caddr_, size_off_ );
189         data_caddr_ = 0;
190         size_off_ = 0;
191     }
192 }
193 String
194 Source_file::file_line_no_str(const char *cch_c_l )
195 {
196     return name_str() + ": "
197         + String( line_i( cch_c_l ) );
198 }