1 /* output.cc -- Code to output symbols to a legacy filesystem
3 * Written by Scott Wood <scott@buserror.net>
12 #include <sys/types.h>
19 static string *map_sym(const char *root, Symbol *sym)
21 typedef std::vector<StringRef> StringVec;
24 while (sym && sym != output_ns && sym->name) {
25 const String *name = NameSpace::mangle(sym->name);
30 return stringvec_to_path(path, root);
33 string *stringvec_to_path(StringVec &stringvec, const char *prepend)
35 string *s = new string();
38 *s += string(prepend);
40 for (StringVec::reverse_iterator i = stringvec.rbegin();
41 i != stringvec.rend(); ++i)
50 void NameSpace::output(const char *root)
52 std::auto_ptr<string> path(map_sym(root, this));
54 if (mkdir(path->c_str(), 0777) && errno != EEXIST) {
55 fprintf(stderr, "Cannot create directory \"%s\": %s.\n",
56 path->c_str(), strerror(errno));
61 for (tbl_type::iterator i = tbl.begin(); i != tbl.end(); ++i) {
62 Symbol *sym = (*i).second;
69 void Def::output_self(const char *root, Symbol *sym, bool dir)
71 std::auto_ptr<string> path(map_sym(root, sym));
76 int fd = open(path->c_str(), O_CREAT | O_EXCL | O_WRONLY, 0666);
78 fprintf(stderr, "Cannot create file \"%s\": %s.\n",
79 path->c_str(), strerror(errno));
84 // open() is used so that O_EXCL can be specified, but
85 // fwrite is used for buffering.
86 File f = fdopen(fd, "wb");
88 fprintf(stderr, "Cannot fdopen \"%s\": %s.\n",
89 path->c_str(), strerror(errno));
94 if (fwrite(&hdr, sizeof(hdr), 1, f) != 1)
96 if (fwrite(self, self_len, 1, f) != 1)
104 fprintf(stderr, "Cannot write to file \"%s\": %s.\n",
105 path->c_str(), strerror(ferror(f)));
110 template<typename T, bool namespace_qual>
111 bool output_list(list<T> &entries, int count, FILE *f)
115 for (typename list<T>::iterator i = entries.begin();
116 i != entries.end(); ++i)
124 s = (*i)->get_fq_name()->flatten();
128 int32_t len = s->length();
130 if (fwrite(&len, sizeof(len), 1, f) != 1)
133 if (fwrite(s->c_str(), len + 1, 1, f) != 1)
136 // Make sure the next string's byte count is aligned on a
137 // 4-byte boundary. Len now includes the null.
141 int pad = ((len + 3) & ~3) - len;
144 if (pad && fwrite(&zero, pad, 1, f) != 1)
156 void Enum::output(const char *root)
158 NameSpace::output(root);
159 output_self(root, this, true);
162 bool Enum::output_extra(FILE *f)
164 return output_list<DatumRef, false>(entries, def.num_entries, f);
167 void Interface::output(const char *root)
169 NameSpace::output(root);
170 output_self(root, this, true);
173 bool Interface::output_extra(FILE *f)
175 return output_list<MethodRef, false>(methods, def.num_methods, f) &&
176 output_list<InterfaceRef, true>(supers, def.num_supers, f);
179 void Method::output(const char *root)
181 NameSpace::output(root);
182 output_self(root, this, true);
185 bool Method::output_extra(FILE *f)
187 return output_list<ParamRef, false>(entries, def.num_entries, f);
190 void Param::output(const char *root)
192 output_self(root, this, false);
195 bool Param::output_extra(FILE *f)
198 return fwrite(type_fq_name->c_str(), def.type.length + 1, 1, f) == 1;
203 void Struct::output(const char *root)
205 NameSpace::output(root);
206 output_self(root, this, true);
209 bool Struct::output_extra(FILE *f)
211 if (!output_list<DatumRef, false>(entries, def.num_entries, f))
215 list<Struct *> superlist;
216 superlist.push_back(super);
217 return output_list<Struct *, true>(superlist, 1, f);
223 void BitField::output(const char *root)
225 NameSpace::output(root);
226 output_self(root, this, true);
229 bool BitField::output_extra(FILE *f)
231 return output_list<DatumRef, false>(entries, def.num_entries, f);
234 void Datum::output(const char *root)
236 if (def.flags.field.Const && !const_init) {
237 resolve_constant_chain();
243 output_self(root, this, false);
246 bool Datum::output_extra(FILE *f)
249 return fwrite(type_fq_name->c_str(), def.type.length + 1, 1, f) == 1;
254 void BasicType::output(const char *root)
259 output_self(root, this, false);
262 void Alias::output(const char *root)
264 output_self(root, this, false);
267 bool Alias::output_extra(FILE *f)
269 return fwrite(sym_fq_name->c_str(), def.length + 1, 1, f) == 1;
272 void UserNameSpace::output(const char *root)
274 NameSpace::output(root);
275 output_self(root, this, true);
278 bool UserNameSpace::output_extra(FILE *f)
280 return fwrite(mountpoint_name->c_str(), def.length + 1, 1, f) == 1;