lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Frescobaldi 2.0.11


From: David Kastrup
Subject: Re: Frescobaldi 2.0.11
Date: Thu, 17 Oct 2013 17:21:50 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux)

"Phil Burfitt" <address@hidden> writes:

> The directory "trial" is lowercase.
>
> However I've tried with...
>
> c:\trial
> c:/trial
> C:\trial
> C:/trial
> C:\TRIAL
> C:/TRIAL
>
> all treated the same and same output. Under Windows/DOS you can use
> "\" or "/" for paths and changing directories etc.

Ok ok, this is pretty thorough.  It was just a case of "Once you ruled
out all the probable cases, it must be one of the improbable ones."

Something like the file name containing a BOM mark (non-printing
character).  But that's not terribly likely.

We have
Source_file *
Sources::get_file (string file_string, string const &current_dir)
{
  if (file_string != "-")
    {
      // First, check for a path relative to the directory of the
      // file currently being parsed.
      if (current_dir.length ()
          && file_string.length ()
          && !File_name (file_string).is_absolute ()
          && is_file (current_dir + DIRSEP + file_string))
        file_string = current_dir + DIRSEP + file_string;

      // Otherwise, check the rest of the path.
      else if (path_)
        {
          string file_string_o = path_->find (file_string);
          if ((file_string_o == "") && (file_string != ""))
            return 0;

          file_string = file_string_o;
        }
    }

  Source_file *f = new Source_file (file_string);
  add (f);
  return f;
}

Which is called in lily/includable-lexer.cc with
/** Set the new input file to NAME, remember old file.  */
void
Includable_lexer::new_input (const string &name, Sources *sources)
{
  string current_dir = dir_name (main_input_name_);
  if (relative_includes)
    current_dir = include_stack_.size () ? dir_name (include_stack_.back 
()->name_string ()) : "";

  Source_file *file = sources->get_file (name, current_dir);
  if (!file)
    {
      string msg = _f ("cannot find file: `%s'", name);
      msg += "\n";
      msg += _f ("(search path: `%s')",
                 (current_dir.length () ? (current_dir + PATHSEP) : "") + 
sources->path_->to_string ().c_str ());
      LexerError (msg.c_str ());
      return;
    }

Now relative_includes is _off_ by default, so current_dir should be
dir_name (main_input_name_).  And that appears to be just the normal
file name., so as far as I can tell from
string
dir_name (const string &file_name)
{
  string s = file_name;
  s = slashify (s);
  ssize n = s.length ();
  if (n && s[n - 1] == '/')
    s[n - 1] = 0;
  if (s.rfind ('/') != NPOS)
    s = s.substr (0, s.rfind ('/'));
  else
    s = "";

  return s;
}
We should get an empty string.  The s[n - 1] = 0; line is obviously
utterly broken, but it should not get executed in your case.

Which should let us fall through "check the rest of the path".

path_->find leads us to

File_path::find (const string &name) const
{
  if (!name.length () || (name == "-"))
    return name;

#ifdef __MINGW32__
  if (name.find ('\\') != NPOS)
    programming_error ("file name not normalized: " + name);
#endif /* __MINGW32__ */

  /* Handle absolute file name.  */
  File_name file_name (name);
  if (file_name.dir_[0] == DIRSEP && is_file (file_name.to_string ()))
    return file_name.to_string ();

  for (vsize i = 0; i < dirs_.size (); i++)
    {
      File_name file_name (name);
      File_name dir = (string) dirs_[i];
      file_name.root_ = dir.root_;
      dir.root_ = "";
      if (file_name.dir_.empty ())
        file_name.dir_ = dir.to_string ();
      else if (!dir.to_string ().empty ())
        file_name.dir_ = dir.to_string ()
                         + ::to_string (DIRSEP) + file_name.dir_;
      if (is_file (file_name.to_string ()))
        return file_name.to_string ();
    }
  return "";
}

Now the criterion for "absolute file names" is obviously wrong for
Windows, but I don't see this causing a problem.

One worthwhile observation is that when the path is printed, this gets
done using

string
File_path::to_string () const
{
  string s;
  for (vsize i = 0; i < dirs_.size (); i++)
    {
      s = s + dirs_[i];
      if (i < dirs_.size () - 1)
        s += ::to_string (PATHSEP);
    }
  return s;
}

rather than just printing a string.  So if one entry looks like
C:/something;C:/somethingelse
rather than being two separate entries in the File_path array, we don't
get to see the difference.

Do we have any other Windows users who could try reproducing this rather
strange behavior?

-- 
David Kastrup



reply via email to

[Prev in Thread] Current Thread [Next in Thread]