-//
-// source-file.cc
-//
-
-#include <sys/types.h> // open, mmap
-#include <sys/stat.h> // open
-#include <sys/mman.h> // mmap
-#include <limits.h> // INT_MAX
-#include <fcntl.h> // open
-#include <unistd.h> // close, stat
-#include <stdio.h> // fdopen
-#include <string.h> // strerror
-#include <errno.h> // errno
-#include <assert.h>
-#include <strstream.h>
+/*
+ source-file.cc -- implement Source_file
-#include "string.hh"
-#include "proto.hh"
-#include "plist.hh"
+ source file of the GNU LilyPond music typesetter
-//#include "lexer.hh"
+ (c) 1997--1999 Jan Nieuwenhuizen <janneke@gnu.org>
+ & Han-Wen Nienhuys <hanwen@cs.uu.nl>
+*/
-#include "debug.hh"
-#include "windhoos-suck-suck-suck-thank-you-cygnus.hh"
-// #include "parseconstruct.hh" // defined_ch_c_l
-extern char const* defined_ch_c_l;
-// ugh
-// #include "main.hh" // find_file
-String find_file(String);
+#include <assert.h>
+#include <strstream.h>
+#include "string.hh"
+#include "proto.hh"
+#include "warn.hh"
+#include "thank-you-cygnus.hh"
#include "source-file.hh"
+#include "simple-file-storage.hh"
+#include "string-storage.hh"
-Source_file::Source_file( String &filename_str )
+Source_file::Source_file (String filename_str)
{
- data_caddr_ = 0;
- fildes_i_ = 0;
- size_off_ = 0;
- name_str_ = filename_str;
- istream_p_ = 0;
-
- open();
- map();
- // ugh!?, should call name_str() !
- filename_str = name_str_;
+ name_str_ = filename_str;
+ istream_p_ = 0;
+ storage_p_ = new Simple_file_storage (filename_str);
+ pos_ch_C_ = ch_C ();
}
-Source_file::~Source_file()
+Source_file::Source_file (String name_str, String data_str)
{
- delete istream_p_;
- istream_p_ = 0;
- unmap();
- close();
+ name_str_ = name_str;
+ istream_p_ = 0;
+ storage_p_ = new String_storage (data_str);
+ pos_ch_C_ = ch_C ();
}
-char const*
-Source_file::ch_c_l()
+istream*
+Source_file::istream_l ()
{
- assert( this );
- return (char const*)data_caddr_;
+ /*
+ if (!name_str_.length_i ())
+ return &cin;
+ */
+
+ if (!istream_p_)
+ {
+ if (length_i ()) // can-t this be done without such a hack?
+ istream_p_ = new istrstream (ch_C (), length_i ());
+ else
+ {
+ istream_p_ = new istrstream ("", 0);
+ istream_p_->set (ios::eofbit);
+ }
+ }
+ return istream_p_;
}
-void
-Source_file::close()
+String
+Source_file::file_line_column_str (char const *context_ch_C) const
{
- if ( fildes_i_ ) {
- ::close( fildes_i_ );
- fildes_i_ = 0;
- }
+ if (!ch_C ())
+ return "(" + _ ("position unknown") + ")";
+ else
+ return name_str () + ":" + to_str (line_i (context_ch_C))
+ + ":" + to_str (char_i (context_ch_C));
}
String
-Source_file::error_str( char const* pos_ch_c_l )
-{
- assert( this );
- if ( !in_b( pos_ch_c_l ) )
- return "";
-
- char const* begin_ch_c_l = pos_ch_c_l;
- char const* data_ch_c_l = ch_c_l();
- while ( begin_ch_c_l > data_ch_c_l )
- if ( *--begin_ch_c_l == '\n' ) {
- begin_ch_c_l++;
- break;
- }
-
- char const* end_ch_c_l = pos_ch_c_l;
- while ( end_ch_c_l < data_ch_c_l + size_off_ )
- if ( *end_ch_c_l++ == '\n' ) {
- break;
- }
- end_ch_c_l--;
-
-#if 1
-// String( char const* p, int length ) is missing!?
- String line_str( (Byte const*)begin_ch_c_l, end_ch_c_l - begin_ch_c_l );
-#else
- int length_i = end_ch_c_l - begin_ch_c_l;
- char* ch_p = new char[ length_i + 1 ];
- strncpy( ch_p, begin_ch_c_l, length_i );
- ch_p[ length_i ] = 0;
- String line_str( ch_p );
- delete ch_p;
-#endif
-
- int error_col_i = 0;
- char const* scan_ch_c_l = begin_ch_c_l;
- while ( scan_ch_c_l < pos_ch_c_l )
- if ( *scan_ch_c_l++ == '\t' )
- error_col_i = ( error_col_i / 8 + 1 ) * 8;
- else
- error_col_i++;
-
- String str = line_str.left_str( pos_ch_c_l - begin_ch_c_l )
- + String( '\n' )
- + String( ' ', error_col_i )
- + line_str.mid_str( pos_ch_c_l - begin_ch_c_l, INT_MAX ); // String::mid should take 0 arg..
- return str;
+Source_file::name_str () const
+{
+ return name_str_;
}
-bool
-Source_file::in_b( char const* pos_ch_c_l )
+Source_file::~Source_file ()
{
- return ( pos_ch_c_l && ( pos_ch_c_l >= ch_c_l() ) && ( pos_ch_c_l < ch_c_l() + size_off_ ) );
+ delete istream_p_;
+ istream_p_ = 0;
+ delete storage_p_;
}
-istream*
-Source_file::istream_l()
-{
- assert( fildes_i_ );
- if ( !istream_p_ ) {
- if ( size_off_ ) // can-t this be done without such a hack?
- istream_p_ = new istrstream( ch_c_l(), size_off_ );
- else {
- istream_p_ = new istrstream( "", 0 );
- istream_p_->set(ios::eofbit);
- }
- }
- return istream_p_;
+Slice
+Source_file::line_slice (char const* pos_ch_C) const
+{
+ if (!in_b (pos_ch_C))
+ return Slice (0,0);
+
+ char const* data_ch_C = ch_C ();
+ char const * eof_C_ = data_ch_C + length_i ();
+
+ if (pos_ch_C == eof_C_)
+ pos_ch_C --;
+ char const* begin_ch_C = pos_ch_C;
+ while (begin_ch_C > data_ch_C)
+ if (*--begin_ch_C == '\n')
+ {
+ begin_ch_C++;
+ break;
+ }
+
+ char const* end_ch_C = pos_ch_C;
+ while (end_ch_C < eof_C_)
+ if (*end_ch_C++ == '\n')
+ {
+ end_ch_C--;
+ break;
+ }
+
+ return Slice (begin_ch_C - data_ch_C, end_ch_C - data_ch_C);
}
-off_t
-Source_file::length_off()
+String
+Source_file::line_str (char const* pos_ch_C) const
{
- return size_off_;
+ if (!in_b (pos_ch_C))
+ return "";
+
+ Slice line = line_slice (pos_ch_C);
+ char const* data_ch_C = ch_C ();
+ return String ((Byte const*)data_ch_C + line[LEFT], line.length ());
}
int
-Source_file::line_i( char const* pos_ch_c_l )
+Source_file::char_i (char const* pos_ch_C) const
{
- if ( !in_b( pos_ch_c_l ) )
- return 0;
+ if (!in_b (pos_ch_C))
+ return 0;
- int i = 1;
- char const* scan_ch_c_l = ch_c_l();
- while ( scan_ch_c_l < pos_ch_c_l )
- if ( *scan_ch_c_l++ == '\n' )
- i++;
- return i;
+ char const* data_ch_C = ch_C ();
+ return pos_ch_C - (line_slice (pos_ch_C)[SMALLER] + data_ch_C);
}
-void
-Source_file::map()
+int
+Source_file::column_i (char const* pos_ch_C) const
{
- if ( fildes_i_ == -1 )
- return;
+ if (!in_b (pos_ch_C))
+ return 0;
- data_caddr_ = (caddr_t)mmap( (void*)0, size_off_, PROT_READ, MAP_SHARED, fildes_i_, 0 );
+ int ch_i = char_i (pos_ch_C);
+ String line = line_str (pos_ch_C);
- if ( (int)data_caddr_ == -1 )
- // ugh: defined_ch_c_l...
- warning( String( "can't map: " ) + name_str_ + String( ": " ) + strerror( errno ), defined_ch_c_l ); //lexer->here_ch_c_l() );
+ int col_i = 0;
+ for (int i = 0; i < ch_i; i++)
+ if (line[i] == '\t')
+ col_i = (col_i / 8 + 1) * 8;
+ else
+ col_i++;
+
+ return col_i;
}
String
-Source_file::name_str()
+Source_file::error_str (char const* pos_ch_C) const
{
- return name_str_;
+ if (!in_b (pos_ch_C))
+ return "(" + _ ("position unknown") + ")";
+
+ int ch_i = char_i (pos_ch_C);
+ String line = line_str (pos_ch_C);
+ String context = line.left_str (ch_i)
+ + to_str ('\n')
+ + to_str (' ', column_i (pos_ch_C))
+ + line.cut_str (ch_i, INT_MAX);
+
+ return context;
}
-void
-Source_file::open()
+bool
+Source_file::in_b (char const* pos_ch_C) const
{
- String name_str = find_file( name_str_ );
- if ( name_str != "" )
- name_str_ = name_str;
+ return (pos_ch_C && (pos_ch_C >= ch_C ()) && (pos_ch_C <= ch_C () + length_i ()));
+}
- fildes_i_ = ::open( name_str_, O_RDONLY );
-
- if ( fildes_i_ == -1 ) {
- warning( String( "can't open: " ) + name_str_ + String( ": " ) + strerror( errno ), defined_ch_c_l ); // lexer->here_ch_c_l() );
- return;
- }
+int
+Source_file::line_i (char const* pos_ch_C) const
+{
+ if (!in_b (pos_ch_C))
+ return 0;
+
+ int i = 1;
+ char const* scan_ch_C = ch_C ();
+ if (!scan_ch_C)
+ return 0;
+
+ while (scan_ch_C < pos_ch_C)
+ if (*scan_ch_C++ == '\n')
+ i++;
+ return i;
+}
- struct stat file_stat;
- fstat( fildes_i_, &file_stat );
- size_off_ = file_stat.st_size;
+int
+Source_file::length_i () const
+{
+ return storage_p_->length_i ();
+}
+
+char const *
+Source_file::ch_C () const
+{
+ return storage_p_->ch_C ();
}
void
-Source_file::unmap()
+Source_file::set_pos (char const * pos_ch_C)
{
- if ( data_caddr_ ) {
- munmap( data_caddr_, size_off_ );
- data_caddr_ = 0;
- size_off_ = 0;
- }
+ if (in_b (pos_ch_C))
+ pos_ch_C_ = pos_ch_C;
+ else
+ error (error_str (pos_ch_C) + "invalid pos");
}
+
+char const*
+Source_file::seek_ch_C (int n)
+{
+ char const* new_ch_C = ch_C () + n;
+ if (n < 0)
+ new_ch_C += length_i ();
+ if (in_b (new_ch_C))
+ pos_ch_C_ = new_ch_C;
+ else
+ error (error_str (new_ch_C) + "seek past eof");
+
+ return pos_ch_C_;
+}
+
+char const*
+Source_file::forward_ch_C (int n)
+{
+ char const* old_pos_C = pos_ch_C_;
+ char const* new_ch_C = pos_ch_C_ + n;
+ if (in_b (new_ch_C))
+ pos_ch_C_ = new_ch_C;
+ else
+ error (error_str (new_ch_C) + "forward past eof");
+
+ return old_pos_C;
+}
+
String
-Source_file::file_line_no_str(char const *ch_c_l )
+Source_file::get_str (int n)
{
- return name_str() + ": "
- + String( line_i( ch_c_l ) );
+ String str ((Byte const*)forward_ch_C (n), n);
+ return str;
}