]> git.donarmstrong.com Git - lilypond.git/blob - flower/file-path.cc
175357d88962d232328d70f796732ee22ce0b7de
[lilypond.git] / flower / file-path.cc
1 /*
2   file-path.cc - implement File_path
3
4   source file of the Flower Library
5
6   (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7   Jan Nieuwenhuizen <janneke@gnu.org>
8 */
9
10 #include "file-path.hh"
11
12 #include <cstdio>
13 #include <cerrno>
14
15 #include "config.hh"
16 #if HAVE_SYS_STAT_H
17 #include <sys/stat.h>
18 #endif
19
20 #ifdef __CYGWIN__
21 #include <sys/cygwin.h>
22 #endif
23
24 #include "file-name.hh"
25 #include "warn.hh"
26
27 #ifndef PATHSEP
28 #define PATHSEP ':'
29 #endif
30
31 vector<string>
32 File_path::directories () const
33 {
34   return dirs_;
35 }
36
37 #include <algorithm>
38 void
39 File_path::parse_path (string p)
40 {
41   concat (dirs_, string_split (p, PATHSEP));
42 }
43
44 bool
45 is_file (string file_name)
46 {
47 #if !STAT_MACROS_BROKEN
48   struct stat sbuf;
49   if (stat (file_name.c_str (), &sbuf) != 0)
50     return false;
51
52   return !S_ISDIR (sbuf.st_mode);
53 #endif
54
55   if (FILE *f = fopen (file_name.c_str (), "r"))
56     {
57       fclose (f);
58       return true;
59     }
60
61   return false;
62 }
63
64 bool
65 is_dir (string file_name)
66 {
67   /*
68     canonicalize; in particular, trailing slashes should disappear.
69    */
70   file_name = File_name (file_name).to_string ();
71   
72 #if !STAT_MACROS_BROKEN
73   struct stat sbuf;
74   if (stat (file_name.c_str (), &sbuf) != 0)
75     return false;
76
77   return S_ISDIR (sbuf.st_mode);
78 #endif
79
80   if (FILE *f = fopen (file_name.c_str (), "r"))
81     {
82       fclose (f);
83       return true;
84     }
85   return false;
86 }
87
88 /** Find a file.
89
90 Check absolute file name, search in the current dir (DUH! FIXME!),
91 in the construction-arg (what's that?), and in any other appended
92 directory, in this order.
93
94 @return
95 The file name if found, or empty string if not found. */
96
97 string
98 File_path::find (string name) const
99 {
100   if (!name.length () || (name == "-"))
101     return name;
102
103 #ifdef __MINGW32__
104   if (name.find ('\\') != NPOS)
105     programming_error ("file name not normalized: " + name);
106 #endif /* __MINGW32__ */
107
108   /* Handle absolute file name.  */
109   File_name file_name (name);
110   if (file_name.dir_[0] == DIRSEP && is_file (file_name.to_string ()))
111     return file_name.to_string ();
112
113   for (vsize i = 0; i < dirs_.size (); i++)
114     {
115       File_name file_name (name);
116       File_name dir = (string) dirs_[i];
117       file_name.root_ = dir.root_;
118       dir.root_ = "";
119       if (file_name.dir_.empty ())
120         file_name.dir_ = dir.to_string ();
121       else if (!dir.to_string ().empty ())
122         file_name.dir_ = dir.to_string ()
123           + ::to_string (DIRSEP) + file_name.dir_;
124       if (is_file (file_name.to_string ()))
125         return file_name.to_string ();
126     }
127   return "";
128 }
129
130 /*
131   Try to find
132
133   file.EXT,
134
135   where EXT is from EXTENSIONS.
136 */
137 string
138 File_path::find (string name, char const *extensions[])
139 {
140   if (name.empty () || name == "-")
141     return name;
142   
143   File_name file_name (name);
144   string orig_ext = file_name.ext_;
145   for (int i = 0; extensions[i]; i++)
146     {
147       file_name.ext_ = orig_ext;
148       if (*extensions[i] && !file_name.ext_.empty ())
149         file_name.ext_ += ".";
150       file_name.ext_ += extensions[i];
151       string found = find (file_name.to_string ());
152       if (!found.empty ())
153         return found;
154     }
155   
156   return "";
157 }
158
159 /** Append a directory, return false if failed.  */
160 bool
161 File_path::try_append (string s)
162 {
163   if (s == "")
164     s = ".";
165   if (is_dir (s))
166     {
167       append (s);
168       return true;
169     }
170   return false;
171 }
172
173 string
174 File_path::to_string () const
175 {
176   string s;
177   for (vsize i = 0; i < dirs_.size (); i++)
178     {
179       s = s + dirs_[i];
180       if (i < dirs_.size () - 1)
181         s += ::to_string (PATHSEP);
182     }
183   return s;
184 }
185
186 void
187 File_path::append (string str)
188 {
189   dirs_.push_back (str);
190 }
191
192 void
193 File_path::prepend (string str)
194 {
195   dirs_.insert (dirs_.begin (), str);
196 }