1 // Code to output symbols to a legacy filesystem
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of
6 // this software and associated documentation files (the "Software"), to deal with
7 // the Software without restriction, including without limitation the rights to
8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 // of the Software, and to permit persons to whom the Software is furnished to do
10 // so, subject to the following condition:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
29 #include <sys/types.h>
36 static string *map_sym(const char *root, Symbol *sym)
38 typedef std::vector<StringRef> StringVec;
41 while (sym && sym != output_ns && sym->name) {
42 const String *name = NameSpace::mangle(sym->name);
47 return stringvec_to_path(path, root);
50 string *stringvec_to_path(StringVec &stringvec, const char *prepend)
52 string *s = new string();
55 *s += string(prepend);
57 for (StringVec::reverse_iterator i = stringvec.rbegin();
58 i != stringvec.rend(); ++i)
67 void NameSpace::output(const char *root)
69 std::auto_ptr<string> path(map_sym(root, this));
71 if (mkdir(path->c_str(), 0777) && errno != EEXIST) {
72 fprintf(stderr, "Cannot create directory \"%s\": %s.\n",
73 path->c_str(), strerror(errno));
78 for (tbl_type::iterator i = tbl.begin(); i != tbl.end(); ++i) {
79 Symbol *sym = (*i).second;
86 void Def::output_self(const char *root, Symbol *sym, bool dir)
88 std::auto_ptr<string> path(map_sym(root, sym));
93 int fd = open(path->c_str(), O_CREAT | O_EXCL | O_WRONLY, 0666);
95 fprintf(stderr, "Cannot create file \"%s\": %s.\n",
96 path->c_str(), strerror(errno));
101 // open() is used so that O_EXCL can be specified, but
102 // fwrite is used for buffering.
103 File f = fdopen(fd, "wb");
105 fprintf(stderr, "Cannot fdopen \"%s\": %s.\n",
106 path->c_str(), strerror(errno));
111 if (fwrite(&hdr, sizeof(hdr), 1, f) != 1)
113 if (fwrite(self, self_len, 1, f) != 1)
115 if (!output_extra(f))
121 fprintf(stderr, "Cannot write to file \"%s\": %s.\n",
122 path->c_str(), strerror(ferror(f)));
127 template<typename T, bool namespace_qual>
128 bool output_list(list<T> &entries, int count, FILE *f)
132 for (typename list<T>::iterator i = entries.begin();
133 i != entries.end(); ++i)
141 s = (*i)->get_fq_name()->flatten();
145 int32_t len = s->length();
147 if (fwrite(&len, sizeof(len), 1, f) != 1)
150 if (fwrite(s->c_str(), len + 1, 1, f) != 1)
153 // Make sure the next string's byte count is aligned on a
154 // 4-byte boundary. Len now includes the null.
158 int pad = ((len + 3) & ~3) - len;
161 if (pad && fwrite(&zero, pad, 1, f) != 1)
173 void Enum::output(const char *root)
175 NameSpace::output(root);
176 output_self(root, this, true);
179 bool Enum::output_extra(FILE *f)
181 return output_list<DatumRef, false>(entries, def.num_entries, f);
184 void Interface::output(const char *root)
186 NameSpace::output(root);
187 output_self(root, this, true);
190 bool Interface::output_extra(FILE *f)
192 return output_list<MethodRef, false>(methods, def.num_methods, f) &&
193 output_list<InterfaceRef, true>(supers, def.num_supers, f);
196 void Method::output(const char *root)
198 NameSpace::output(root);
199 output_self(root, this, true);
202 bool Method::output_extra(FILE *f)
204 return output_list<ParamRef, false>(entries, def.num_entries, f);
207 void Param::output(const char *root)
209 output_self(root, this, false);
212 bool Param::output_extra(FILE *f)
215 return fwrite(type_fq_name->c_str(), def.type.length + 1, 1, f) == 1;
220 void Struct::output(const char *root)
222 NameSpace::output(root);
223 output_self(root, this, true);
226 bool Struct::output_extra(FILE *f)
228 if (!output_list<DatumRef, false>(entries, def.num_entries, f))
232 list<Struct *> superlist;
233 superlist.push_back(super);
234 return output_list<Struct *, true>(superlist, 1, f);
240 void BitField::output(const char *root)
242 NameSpace::output(root);
243 output_self(root, this, true);
246 bool BitField::output_extra(FILE *f)
248 return output_list<DatumRef, false>(entries, def.num_entries, f);
251 void Datum::output(const char *root)
253 if (def.flags.field.Const && !const_init) {
254 resolve_constant_chain();
260 output_self(root, this, false);
263 bool Datum::output_extra(FILE *f)
266 return fwrite(type_fq_name->c_str(), def.type.length + 1, 1, f) == 1;
271 void BasicType::output(const char *root)
276 output_self(root, this, false);
279 void Alias::output(const char *root)
281 output_self(root, this, false);
284 bool Alias::output_extra(FILE *f)
286 return fwrite(sym_fq_name->c_str(), def.length + 1, 1, f) == 1;
289 void UserNameSpace::output(const char *root)
291 NameSpace::output(root);
292 output_self(root, this, true);
295 bool UserNameSpace::output_extra(FILE *f)
297 return fwrite(mountpoint_name->c_str(), def.length + 1, 1, f) == 1;