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