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