]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libcody/resolver.cc
1 // CODYlib -*- mode:c++ -*-
2 // Copyright (C) 2020 Nathan Sidwell, nathan@acm.org
3 // License: Apache v2.0
11 #include <sys/types.h>
13 #if (defined (__unix__) \
14 || (defined (__Apple__) \
15 && defined (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) \
16 && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000))
18 #define HAVE_FSTATAT 1
20 #define HAVE_FSTATAT 0
26 inline bool IsDirSep (char c
)
28 return c
== '/' || c
== '\\';
30 inline bool IsAbsPath (char const *str
)
32 // IIRC windows has the concept of per-drive current directories,
33 // which make drive-using paths confusing. Let's not get into that.
35 || (((str
[0] >= 'A' && str
[1] <= 'Z')
36 || (str
[0] >= 'a' && str
[1] <= 'z'))&& str
[1] == ':');
39 inline bool IsDirSep (char c
)
43 inline bool IsAbsPath (char const *str
)
45 return IsDirSep (str
[0]);
49 constexpr char DIR_SEPARATOR
= '/';
51 constexpr char DOT_REPLACE
= ','; // Replace . directories
52 constexpr char COLON_REPLACE
= '-'; // Replace : (partition char)
53 constexpr char const REPO_DIR
[] = "cmi.cache";
57 Resolver::~Resolver ()
61 char const *Resolver::GetCMISuffix ()
66 std::string
Resolver::GetCMIName (std::string
const &module
)
70 result
.reserve (module
.size () + 8);
71 bool is_header
= false;
74 if (IsAbsPath (module
.c_str ()))
75 is_header
= is_abs
= true;
76 else if (module
.front () == '.' && IsDirSep (module
.c_str ()[1]))
81 result
.push_back ('.');
82 result
.append (module
);
85 result
= std::move (module
);
90 result
[0] = DOT_REPLACE
;
92 /* Map .. to DOT_REPLACE, DOT_REPLACE. */
93 for (size_t ix
= 1; ; ix
++)
95 ix
= result
.find ('.', ix
);
96 if (ix
== result
.npos
)
98 if (ix
+ 2 > result
.size ())
100 if (result
[ix
+ 1] != '.')
102 if (!IsDirSep (result
[ix
- 1]))
104 if (!IsDirSep (result
[ix
+ 2]))
106 result
[ix
] = DOT_REPLACE
;
107 result
[ix
+ 1] = DOT_REPLACE
;
110 else if (COLON_REPLACE
!= ':')
112 // There can only be one colon in a module name
113 auto colon
= result
.find (':');
114 if (colon
!= result
.npos
)
115 result
[colon
] = COLON_REPLACE
;
118 if (char const *suffix
= GetCMISuffix ())
120 result
.push_back ('.');
121 result
.append (suffix
);
127 void Resolver::WaitUntilReady (Server
*)
131 Resolver
*Resolver::ConnectRequest (Server
*s
, unsigned version
,
132 std::string
&, std::string
&)
134 if (version
> Version
)
135 s
->ErrorResponse ("version mismatch");
137 s
->ConnectResponse ("default");
142 int Resolver::ModuleRepoRequest (Server
*s
)
144 s
->PathnameResponse (REPO_DIR
);
148 // Deprecated resolver functions
149 int Resolver::ModuleExportRequest (Server
*s
, Flags
, std::string
&module
)
151 auto cmi
= GetCMIName (module
);
152 s
->PathnameResponse (cmi
);
156 int Resolver::ModuleImportRequest (Server
*s
, Flags
, std::string
&module
)
158 auto cmi
= GetCMIName (module
);
159 s
->PathnameResponse (cmi
);
163 int Resolver::ModuleCompiledRequest (Server
*s
, Flags
, std::string
&)
169 int Resolver::IncludeTranslateRequest (Server
*s
, Flags
, std::string
&include
)
173 // This is not the most efficient
174 auto cmi
= GetCMIName (include
);
178 int fd_dir
= open (REPO_DIR
, O_RDONLY
| O_CLOEXEC
| O_DIRECTORY
);
180 && fstatat (fd_dir
, cmi
.c_str (), &statbuf
, 0) == 0
181 && S_ISREG (statbuf
.st_mode
))
182 // Sadly can't easily check if this process has read access,
183 // except by trying to open it.
188 std::string append
= REPO_DIR
;
189 append
.push_back (DIR_SEPARATOR
);
191 if (stat (append
.c_str (), &statbuf
) == 0
192 || S_ISREG (statbuf
.st_mode
))
197 s
->PathnameResponse (cmi
);
199 s
->BoolResponse (false);
204 void Resolver::ErrorResponse (Server
*server
, std::string
&&msg
)
206 server
->ErrorResponse (msg
);