RISC-V: Implement instruction patterns for ZBS extension.
[official-gcc.git] / libcody / server.cc
blobe2fa069bb9335042156810d95573caeeabe76ccc
1 // CODYlib -*- mode:c++ -*-
2 // Copyright (C) 2020 Nathan Sidwell, nathan@acm.org
3 // License: Apache v2.0
5 // Cody
6 #include "internal.hh"
7 // C++
8 #include <tuple>
9 // C
10 #include <cerrno>
11 #include <cstdlib>
12 #include <cstring>
14 // Server code
16 namespace Cody {
18 // These do not need to be members
19 static Resolver *ConnectRequest (Server *, Resolver *,
20 std::vector<std::string> &words);
21 static int ModuleRepoRequest (Server *, Resolver *,
22 std::vector<std::string> &words);
23 static int ModuleExportRequest (Server *, Resolver *,
24 std::vector<std::string> &words);
25 static int ModuleImportRequest (Server *, Resolver *,
26 std::vector<std::string> &words);
27 static int ModuleCompiledRequest (Server *, Resolver *,
28 std::vector<std::string> &words);
29 static int IncludeTranslateRequest (Server *, Resolver *,
30 std::vector<std::string> &words);
32 namespace {
33 using RequestFn = int (Server *, Resolver *, std::vector<std::string> &);
34 using RequestPair = std::tuple<char const *, RequestFn *>;
35 static RequestPair
36 const requestTable[Detail::RC_HWM] =
38 // Same order as enum RequestCode
39 RequestPair {u8"HELLO", nullptr},
40 RequestPair {u8"MODULE-REPO", ModuleRepoRequest},
41 RequestPair {u8"MODULE-EXPORT", ModuleExportRequest},
42 RequestPair {u8"MODULE-IMPORT", ModuleImportRequest},
43 RequestPair {u8"MODULE-COMPILED", ModuleCompiledRequest},
44 RequestPair {u8"INCLUDE-TRANSLATE", IncludeTranslateRequest},
48 Server::Server (Resolver *r)
49 : resolver (r), direction (READING)
51 PrepareToRead ();
54 Server::Server (Server &&src)
55 : write (std::move (src.write)),
56 read (std::move (src.read)),
57 resolver (src.resolver),
58 is_connected (src.is_connected),
59 direction (src.direction)
61 fd.from = src.fd.from;
62 fd.to = src.fd.to;
65 Server::~Server ()
69 Server &Server::operator= (Server &&src)
71 write = std::move (src.write);
72 read = std::move (src.read);
73 resolver = src.resolver;
74 is_connected = src.is_connected;
75 direction = src.direction;
76 fd.from = src.fd.from;
77 fd.to = src.fd.to;
79 return *this;
82 void Server::DirectProcess (Detail::MessageBuffer &from,
83 Detail::MessageBuffer &to)
85 read.PrepareToRead ();
86 std::swap (read, from);
87 ProcessRequests ();
88 resolver->WaitUntilReady (this);
89 write.PrepareToWrite ();
90 std::swap (to, write);
93 void Server::ProcessRequests (void)
95 std::vector<std::string> words;
97 direction = PROCESSING;
98 while (!read.IsAtEnd ())
100 int err = 0;
101 unsigned ix = Detail::RC_HWM;
102 if (!read.Lex (words))
104 Assert (!words.empty ());
105 while (ix--)
107 if (words[0] != std::get<0> (requestTable[ix]))
108 continue; // not this one
110 if (ix == Detail::RC_CONNECT)
112 // CONNECT
113 if (IsConnected ())
114 err = -1;
115 else if (auto *r = ConnectRequest (this, resolver, words))
116 resolver = r;
117 else
118 err = -1;
120 else
122 if (!IsConnected ())
123 err = -1;
124 else if (int res = (std::get<1> (requestTable[ix])
125 (this, resolver, words)))
126 err = res;
128 break;
132 if (err || ix >= Detail::RC_HWM)
134 // Some kind of error
135 std::string msg;
137 if (err > 0)
138 msg = u8"error processing '";
139 else if (ix >= Detail::RC_HWM)
140 msg = u8"unrecognized '";
141 else if (IsConnected () && ix == Detail::RC_CONNECT)
142 msg = u8"already connected '";
143 else if (!IsConnected () && ix != Detail::RC_CONNECT)
144 msg = u8"not connected '";
145 else
146 msg = u8"malformed '";
148 read.LexedLine (msg);
149 msg.append (u8"'");
150 if (err > 0)
152 msg.append (u8" ");
153 msg.append (strerror (err));
155 resolver->ErrorResponse (this, std::move (msg));
160 // Return numeric value of STR as an unsigned. Returns ~0u on error
161 // (so that value is not representable).
162 static unsigned ParseUnsigned (std::string &str)
164 char *eptr;
165 unsigned long val = strtoul (str.c_str (), &eptr, 10);
166 if (*eptr || unsigned (val) != val)
167 return ~0u;
169 return unsigned (val);
172 Resolver *ConnectRequest (Server *s, Resolver *r,
173 std::vector<std::string> &words)
175 if (words.size () < 3 || words.size () > 4)
176 return nullptr;
178 if (words.size () == 3)
179 words.emplace_back (u8"");
180 unsigned version = ParseUnsigned (words[1]);
181 if (version == ~0u)
182 return nullptr;
184 return r->ConnectRequest (s, version, words[2], words[3]);
187 int ModuleRepoRequest (Server *s, Resolver *r,std::vector<std::string> &words)
189 if (words.size () != 1)
190 return -1;
192 return r->ModuleRepoRequest (s);
195 int ModuleExportRequest (Server *s, Resolver *r, std::vector<std::string> &words)
197 if (words.size () < 2 || words.size () > 3 || words[1].empty ())
198 return -1;
200 Flags flags = Flags::None;
201 if (words.size () == 3)
203 unsigned val = ParseUnsigned (words[2]);
204 if (val == ~0u)
205 return -1;
206 flags = Flags (val);
209 return r->ModuleExportRequest (s, flags, words[1]);
212 int ModuleImportRequest (Server *s, Resolver *r, std::vector<std::string> &words)
214 if (words.size () < 2 || words.size () > 3 || words[1].empty ())
215 return -1;
217 Flags flags = Flags::None;
218 if (words.size () == 3)
220 unsigned val = ParseUnsigned (words[2]);
221 if (val == ~0u)
222 return -1;
223 flags = Flags (val);
226 return r->ModuleImportRequest (s, flags, words[1]);
229 int ModuleCompiledRequest (Server *s, Resolver *r,
230 std::vector<std::string> &words)
232 if (words.size () < 2 || words.size () > 3 || words[1].empty ())
233 return -1;
235 Flags flags = Flags::None;
236 if (words.size () == 3)
238 unsigned val = ParseUnsigned (words[2]);
239 if (val == ~0u)
240 return -1;
241 flags = Flags (val);
244 return r->ModuleCompiledRequest (s, flags, words[1]);
247 int IncludeTranslateRequest (Server *s, Resolver *r,
248 std::vector<std::string> &words)
250 if (words.size () < 2 || words.size () > 3 || words[1].empty ())
251 return -1;
253 Flags flags = Flags::None;
254 if (words.size () == 3)
256 unsigned val = ParseUnsigned (words[2]);
257 if (val == ~0u)
258 return -1;
259 flags = Flags (val);
262 return r->IncludeTranslateRequest (s, flags, words[1]);
265 void Server::ErrorResponse (char const *error, size_t elen)
267 write.BeginLine ();
268 write.AppendWord (u8"ERROR");
269 write.AppendWord (error, true, elen);
270 write.EndLine ();
273 void Server::OKResponse ()
275 write.BeginLine ();
276 write.AppendWord (u8"OK");
277 write.EndLine ();
280 void Server::ConnectResponse (char const *agent, size_t alen)
282 is_connected = true;
284 write.BeginLine ();
285 write.AppendWord (u8"HELLO");
286 write.AppendInteger (Version);
287 write.AppendWord (agent, true, alen);
288 write.EndLine ();
291 void Server::PathnameResponse (char const *cmi, size_t clen)
293 write.BeginLine ();
294 write.AppendWord (u8"PATHNAME");
295 write.AppendWord (cmi, true, clen);
296 write.EndLine ();
299 void Server::BoolResponse (bool truthiness)
301 write.BeginLine ();
302 write.AppendWord (u8"BOOL");
303 write.AppendWord (truthiness ? u8"TRUE" : u8"FALSE");
304 write.EndLine ();