1 // Code to output symbols to a legacy filesystem
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
5 // This software is provided 'as-is', without any express or implied warranty.
6 // In no event will the authors or contributors be held liable for any damages
7 // arising from the use of this software.
9 // Permission is hereby granted to everyone, free of charge, to use, copy,
10 // modify, prepare derivative works of, publish, distribute, perform,
11 // sublicense, and/or sell copies of the Software, provided that the above
12 // copyright notice and disclaimer of warranty be included in all copies or
13 // substantial portions of this software.
21 #include <sys/types.h>
28 static string *map_sym(const char *root, Symbol *sym)
30 typedef std::vector<StringRef> StringVec;
33 while (sym && sym != output_ns && sym->name) {
34 const String *name = NameSpace::mangle(sym->name);
39 return stringvec_to_path(path, root);
42 string *stringvec_to_path(StringVec &stringvec, const char *prepend)
44 string *s = new string();
47 *s += string(prepend);
49 for (StringVec::reverse_iterator i = stringvec.rbegin();
50 i != stringvec.rend(); ++i)
59 void NameSpace::output(const char *root)
61 std::auto_ptr<string> path(map_sym(root, this));
63 if (mkdir(path->c_str(), 0777) && errno != EEXIST) {
64 fprintf(stderr, "Cannot create directory \"%s\": %s.\n",
65 path->c_str(), strerror(errno));
70 for (tbl_type::iterator i = tbl.begin(); i != tbl.end(); ++i) {
71 Symbol *sym = (*i).second;
78 void Def::output_self(const char *root, Symbol *sym, bool dir)
80 std::auto_ptr<string> path(map_sym(root, sym));
85 int fd = open(path->c_str(), O_CREAT | O_EXCL | O_WRONLY, 0666);
87 fprintf(stderr, "Cannot create file \"%s\": %s.\n",
88 path->c_str(), strerror(errno));
93 // open() is used so that O_EXCL can be specified, but
94 // fwrite is used for buffering.
95 File f = fdopen(fd, "wb");
97 fprintf(stderr, "Cannot fdopen \"%s\": %s.\n",
98 path->c_str(), strerror(errno));
103 if (fwrite(&hdr, sizeof(hdr), 1, f) != 1)
105 if (fwrite(self, self_len, 1, f) != 1)
107 if (!output_extra(f))
113 fprintf(stderr, "Cannot write to file \"%s\": %s.\n",
114 path->c_str(), strerror(ferror(f)));
119 template<typename T, bool namespace_qual>
120 bool output_list(list<T> &entries, int count, FILE *f)
124 for (typename list<T>::iterator i = entries.begin();
125 i != entries.end(); ++i)
133 s = (*i)->get_fq_name()->flatten();
137 int32_t len = s->length();
139 if (fwrite(&len, sizeof(len), 1, f) != 1)
142 if (fwrite(s->c_str(), len + 1, 1, f) != 1)
145 // Make sure the next string's byte count is aligned on a
146 // 4-byte boundary. Len now includes the null.
150 int pad = ((len + 3) & ~3) - len;
153 if (pad && fwrite(&zero, pad, 1, f) != 1)
165 void Enum::output(const char *root)
167 NameSpace::output(root);
168 output_self(root, this, true);
171 bool Enum::output_extra(FILE *f)
173 return output_list<DatumRef, false>(entries, def.num_entries, f);
176 void Interface::output(const char *root)
178 NameSpace::output(root);
179 output_self(root, this, true);
182 bool Interface::output_extra(FILE *f)
184 return output_list<MethodRef, false>(methods, def.num_methods, f) &&
185 output_list<InterfaceRef, true>(supers, def.num_supers, f);
188 void Method::output(const char *root)
190 NameSpace::output(root);
191 output_self(root, this, true);
194 bool Method::output_extra(FILE *f)
196 return output_list<ParamRef, false>(entries, def.num_entries, f);
199 void Param::output(const char *root)
201 output_self(root, this, false);
204 bool Param::output_extra(FILE *f)
207 return fwrite(type_fq_name->c_str(), def.type.length + 1, 1, f) == 1;
212 void Struct::output(const char *root)
214 NameSpace::output(root);
215 output_self(root, this, true);
218 bool Struct::output_extra(FILE *f)
220 if (!output_list<DatumRef, false>(entries, def.num_entries, f))
224 list<Struct *> superlist;
225 superlist.push_back(super);
226 return output_list<Struct *, true>(superlist, 1, f);
232 void BitField::output(const char *root)
234 NameSpace::output(root);
235 output_self(root, this, true);
238 bool BitField::output_extra(FILE *f)
240 return output_list<DatumRef, false>(entries, def.num_entries, f);
243 void Datum::output(const char *root)
245 if (def.flags.field.Const && !const_init) {
246 resolve_constant_chain();
252 output_self(root, this, false);
255 bool Datum::output_extra(FILE *f)
258 return fwrite(type_fq_name->c_str(), def.type.length + 1, 1, f) == 1;
263 void BasicType::output(const char *root)
268 output_self(root, this, false);
271 void Alias::output(const char *root)
273 output_self(root, this, false);
276 bool Alias::output_extra(FILE *f)
278 return fwrite(sym_fq_name->c_str(), def.length + 1, 1, f) == 1;
281 void UserNameSpace::output(const char *root)
283 NameSpace::output(root);
284 output_self(root, this, true);
287 bool UserNameSpace::output_extra(FILE *f)
289 return fwrite(mountpoint_name->c_str(), def.length + 1, 1, f) == 1;