]> git.donarmstrong.com Git - lilypond.git/blobdiff - lib/source-file.cc
release: 1.2.0
[lilypond.git] / lib / source-file.cc
index a39a57cbfa276973f23840a513f26301c38e7bde..e6ea86aeb854a35c38bb2079d4e8b618b9c405b2 100644 (file)
-//
-// 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;
 }