1 // Code to load symbols from 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.
26 // To deal with namespaces on a case-insensitive filesystem, names
27 // are annotated with a hexadecimal prefix indicating the case of each
28 // letter. Each bit in the number represents a letter, with 0 being
29 // lowercase (or a non-letter) and 1 being uppercase. The
30 // least-significant bit is the first letter. This is done on both
31 // case sensitive and case insensitive filesystems so that the output
32 // can be freely copied between them (it also simplifies the code).
33 // As such, hex digits should be in upper case so that case-sensitive
34 // lookups can be used. This prefix is separated from the actual name
37 // When the time comes along that UTF-8 is supported, this applies to
38 // UTF-8 characters, not ASCII characters.
40 // This mangling can also be used (with a leading underscore or
41 // whatever) in case-insensitive languages, though ideally there
42 // should be aliases with the unannotated name if there is no
45 // I don't want to go the CORBA route of disallowing case conflicts,
46 // as I find using capitals for types and lowercase for instances to
47 // be a useful convention (and less ugly than appending _t, except
48 // when case sensitivity is missing), and would rather not be limited
49 // at such a fundamental level by broken languages.
51 static char tohex(int digit)
56 return digit + 'A' - 10;
59 const String *NameSpace::mangle(const String *name)
61 String *mangled_string = new String;
63 // The conversion is done manually so that I don't have to deal
64 // with bignum arithmetic.
66 std::vector<bool> hex;
67 std::vector<bool>::size_type name_len = name->length();
69 // Pad out the first digit with leading zeroes, so that
70 // we don't have to deal with that later.
73 for (int i = name_len & 3; i < 4; ++i)
76 for (string::const_iterator i = name->begin(); i != name->end(); ++i)
77 hex.push_back(isupper(*i));
79 assert((hex.size() & 3) == 0);
81 for (std::vector<bool>::size_type i = 0; i < hex.size(); i += 4) {
82 int digit = hex[i] * 8 +
87 *mangled_string += tohex(digit);
90 *mangled_string += '_';
91 *mangled_string += *name;
92 return mangled_string;
102 msg = strerror(ferror(f));
108 struct ImportContext {
110 const char *filename;
116 CompiledDefHeader hdr;
119 static void import_and_validate_array(ImportContext &ctx,
123 out.bounds[0] = swap64(in.bounds[0], ctx.swap);
124 out.bounds[1] = swap64(in.bounds[1], ctx.swap);
126 if (out.bounds[0] < 0) {
127 fprintf(stderr, "\"%s\" is not a valid object "
128 "(bad array lower bound %" PRId64 ").\n",
129 ctx.filename, out.bounds[0]);
133 if (out.bounds[1] < -1) {
134 fprintf(stderr, "\"%s\" is not a valid object "
135 "(bad array upper bound %" PRId64 ").\n",
136 ctx.filename, out.bounds[0]);
140 if (out.bounds[1] > 0 &&
141 out.bounds[1] < out.bounds[0]) {
142 fprintf(stderr, "\"%s\" is not a valid object "
143 "(array upper bound %" PRId64 " less than lower bound %" PRId64 ").\n",
144 ctx.filename, out.bounds[1], out.bounds[0]);
149 static void import_and_validate_basictype(ImportContext &ctx,
150 CompiledBasicType &out,
151 CompiledBasicType &in)
153 out.bits = swap32(in.bits, ctx.swap);
154 out.flags.raw = swap32(in.flags.raw, ctx.swap);
157 if (out.flags.field.Unsigned)
159 if (out.flags.field.Float)
161 if (out.flags.field.Bool)
164 fprintf(stderr, "\"%s\" is not a valid object "
165 "(bad flags 0x%08x).\n",
166 ctx.filename, out.flags.raw);
170 if (out.flags.field.Bool) {
172 fprintf(stderr, "\"%s\" is not a valid object "
173 "(bad bits %d for bool type).\n",
174 ctx.filename, out.bits);
177 } else if (out.flags.field.Float) {
178 if (out.bits != 32 && out.bits != 64) {
179 fprintf(stderr, "\"%s\" is not a valid object "
180 "(bad bits %d for floating point type).\n",
181 ctx.filename, out.bits);
184 } else if (!dynamic_cast<BitField *>(ctx.parent) &&
185 !dynamic_cast<Enum *>(ctx.parent)) {
186 if (out.bits != 8 && out.bits != 16 &&
187 out.bits != 32 && out.bits != 64) {
188 fprintf(stderr, "\"%s\" is not a valid object "
189 "(bad bits %d for integer type).\n",
190 ctx.filename, out.bits);
194 if (out.bits == 8 && !out.flags.field.Unsigned) {
195 fprintf(stderr, "\"%s\" is not a valid object "
196 "(octet type must be unsigned).\n",
202 // Bitfield entries can take anywhere from 1 to 64 bits, but
203 // will be verified by the parent after all entries have loaded,
204 // so it can verify that the sum does not exceed the size of
207 import_and_validate_array(ctx, out.array, in.array);
210 BasicType *BasicType::import(ImportContext &ctx)
213 fprintf(stderr, "\"%s\" is not a valid object "
214 "(a BasicType must be a file).\n",
219 CompiledBasicType def;
220 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
221 throw IOError(ctx.f);
223 BasicType *bt = new BasicType(ctx.name);
224 ctx.parent->add_import(bt, ctx.filename);
226 import_and_validate_basictype(ctx, bt->def, def);
232 static String *read_string_raw(ImportContext &ctx, int32_t length)
234 if (length < 0 || length > 4096) {
235 fprintf(stderr, "\"%s\" is not a valid object "
236 "(unreasonable string length %d).\n",
237 ctx.filename, length);
241 // Is there a way to reserve space in a C++ string, and pass
242 // the buffer into fread?
244 char *buf = new char[length + 1];
246 if (fread(buf, length + 1, 1, ctx.f) != 1)
247 throw IOError(ctx.f);
249 String *s = new String(buf);
254 static const String *read_string(ImportContext &ctx)
256 off_t pos = ftello(ctx.f);
257 int pad = ((pos + 3) & ~3) - pos;
259 if (pad != 0 && fseeko(ctx.f, pad, SEEK_CUR) != 0)
260 throw IOError(ctx.f);
263 if (fread(&length, sizeof(length), 1, ctx.f) != 1)
264 throw IOError(ctx.f);
266 return read_string_raw(ctx, swap32(length, ctx.swap));
269 StrList::StrList(const String *input, char delimeter)
271 const char *cur = input->c_str();
274 char *next = strchr(cur, delimeter);
275 String *s = new String();
276 s->token = TOK_IDENT;
278 if (next == cur || *cur == 0)
279 throw InvalidArgument();
282 s->append(cur, next - cur);
293 // FIXME: Handle illegal recursion.
294 static Symbol *lookup_sym_noyyerror(ImportContext &ctx, const String *name)
299 sl = new StrList(name);
302 catch (InvalidArgument) {
303 fprintf(stderr, "\"%s\" is not a valid object "
304 "(\"%s\" is not a valid identifier).\n",
305 ctx.filename, name->c_str());
310 return lookup_sym(toplevel, sl, toplevel);
314 fprintf(stderr, "\"%s\" is not a valid object "
315 "(\"%s\" could not be loaded).\n",
316 ctx.filename, name->c_str());
322 // FIXME: Handle illegal recursion.
323 static Symbol *lookup_sym_in_ns_noyyerror(ImportContext &ctx,
327 Symbol *sym = ns->lookup_noex(name);
329 fprintf(stderr, "\"%s\" is not a valid object "
330 "(\"%s\" is not found).\n",
331 ctx.filename, name->c_str());
339 Datum *Datum::import(ImportContext &ctx)
342 fprintf(stderr, "\"%s\" is not a valid object "
343 "(a Datum must be a file).\n",
349 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
350 throw IOError(ctx.f);
352 Datum *d = new Datum(ctx.name);
353 d->def.flags.raw = swap32(def.flags.raw, ctx.swap);
355 if (d->def.flags.field.Invalid) {
356 fprintf(stderr, "\"%s\" is not a valid object "
357 "(bad flags 0x%08x).\n",
358 ctx.filename, d->def.flags.raw);
362 ctx.parent->add_import(d, ctx.filename);
364 d->def.type.length = swap32(def.type.length, ctx.swap);
366 if (d->def.type.length != 0) {
367 d->type_fq_name = read_string_raw(ctx, d->def.type.length);
368 Symbol *sym = lookup_sym_noyyerror(ctx, d->type_fq_name);
369 d->type = dynamic_cast<Type *>(sym);
372 fprintf(stderr, "\"%s\" is not a valid object "
373 "(\"%s\" is not a type).\n",
374 ctx.filename, d->type_fq_name->c_str());
378 import_and_validate_array(ctx, d->def.basictype.array,
379 def.basictype.array);
381 BasicType *bt = dynamic_cast<BasicType *>(*d->type);
388 import_and_validate_basictype(ctx, d->def.basictype,
390 d->cbt = &d->def.basictype;
393 d->def.ucon = swap64(def.ucon, ctx.swap);
395 if (d->def.flags.field.Const) {
397 fprintf(stderr, "\"%s\" is not a valid object "
398 "(constant, but non-basic type).\n",
403 if (d->cbt->flags.field.Float)
404 d->con_type = TOK_FCON;
405 else if (!d->cbt->flags.field.Unsigned)
406 d->con_type = TOK_ICON;
408 d->con_type = TOK_UCON;
410 if (!d->verify_const()) {
411 fprintf(stderr, "\"%s\" is not a valid object "
417 d->con_type = TOK_NONE;
423 // OPT: Importing methods and supers isn't necessary for idlc to
424 // work; it could be made optional to speed up large compilations.
426 Interface *Interface::import(ImportContext &ctx)
429 fprintf(stderr, "\"%s\" is not a valid object "
430 "(an Interface must be a directory).\n",
435 CompiledInterface def;
436 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
437 throw IOError(ctx.f);
439 Interface *iface = new Interface(ctx.name);
440 iface->path = new String(ctx.filename);
441 ctx.parent->add_import(iface, ctx.filename);
443 iface->def.guid[0] = def.guid[0];
444 iface->def.guid[1] = def.guid[1];
446 int32_t num_methods = swap32(def.num_methods, ctx.swap);
447 int32_t num_supers = swap32(def.num_supers, ctx.swap);
449 if (num_methods < 0 || num_methods > 4096) {
450 fprintf(stderr, "\"%s\" is not a valid object "
451 "(unreasonable num_methods %d).\n",
452 ctx.filename, num_methods);
456 if (num_supers < 0 || num_supers > 4096) {
457 fprintf(stderr, "\"%s\" is not a valid object "
458 "(unreasonable num_supers %d).\n",
459 ctx.filename, num_supers);
463 for (int32_t i = 0; i < num_methods; i++) {
464 const String *str = read_string(ctx);
465 Symbol *sym = lookup_sym_in_ns_noyyerror(ctx, iface, str);
466 Method *m = dynamic_cast<Method *>(sym);
469 fprintf(stderr, "\"%s\" is not a valid object "
470 "(\"%s\" is not a method).\n",
471 ctx.filename, str->c_str());
478 // FIXME: Check for bad recursion again
480 for (int32_t i = 0; i < num_supers; i++) {
481 const String *str = read_string(ctx);
482 Symbol *sym = lookup_sym_noyyerror(ctx, str);
483 Interface *super = dynamic_cast<Interface *>(sym);
486 fprintf(stderr, "\"%s\" is not a valid object "
487 "(\"%s\" is not an interface).\n",
488 ctx.filename, str->c_str());
492 iface->add_super(super);
495 assert(num_methods == iface->def.num_methods);
496 assert(num_supers == iface->def.num_supers);
498 iface->sort_chains();
502 Method *Method::import(ImportContext &ctx)
505 fprintf(stderr, "\"%s\" is not a valid object "
506 "(a Method must be a directory).\n",
512 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
513 throw IOError(ctx.f);
515 Method *m = new Method(ctx.name);
516 m->path = new String(ctx.filename);
517 ctx.parent->add_import(m, ctx.filename);
519 int32_t num_entries = swap32(def.num_entries, ctx.swap);
521 m->def.flags.raw = swap32(def.flags.raw, ctx.swap);
523 if (num_entries < 0 || num_entries > 4096) {
524 fprintf(stderr, "\"%s\" is not a valid object "
525 "(unreasonable num_entries %d).\n",
526 ctx.filename, num_entries);
530 for (int32_t i = 0; i < num_entries; i++) {
531 const String *str = read_string(ctx);
532 Symbol *sym = lookup_sym_in_ns_noyyerror(ctx, m, str);
533 Param *p = dynamic_cast<Param *>(sym);
536 fprintf(stderr, "\"%s\" is not a valid object "
537 "(\"%s\" is not a parameter).\n",
538 ctx.filename, str->c_str());
545 assert(num_entries == m->def.num_entries);
549 Param *Param::import(ImportContext &ctx)
552 fprintf(stderr, "\"%s\" is not a valid object "
553 "(a Parameter must be a file).\n",
559 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
560 throw IOError(ctx.f);
562 Param *p = new Param(ctx.name);
563 ctx.parent->add_import(p, ctx.filename);
565 p->def.type.length = swap32(def.type.length, ctx.swap);
567 if (p->def.type.length != 0) {
568 p->type_fq_name = read_string_raw(ctx, p->def.type.length);
569 Symbol *sym = lookup_sym_noyyerror(ctx, p->type_fq_name);
570 p->type = dynamic_cast<Type *>(sym);
573 fprintf(stderr, "\"%s\" is not a valid object "
574 "(\"%s\" is not a type).\n",
575 ctx.filename, p->type_fq_name->c_str());
579 import_and_validate_array(ctx, p->def.basictype.array,
580 def.basictype.array);
582 import_and_validate_basictype(ctx, p->def.basictype,
586 p->def.flags.raw = swap32(def.flags.raw, ctx.swap);
590 // OPT: Importing data and super isn't necessary for idlc to
591 // work; it could be made optional to speed up large compilations.
593 Struct *Struct::import(ImportContext &ctx)
596 fprintf(stderr, "\"%s\" is not a valid object "
597 "(a Struct must be a directory).\n",
603 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
604 throw IOError(ctx.f);
606 Struct *s = new Struct(ctx.name);
607 s->path = new String(ctx.filename);
608 ctx.parent->add_import(s, ctx.filename);
610 s->def.guid[0] = def.guid[0];
611 s->def.guid[1] = def.guid[1];
613 int32_t num_entries = swap32(def.num_entries, ctx.swap);
615 s->def.flags.raw = swap32(def.flags.raw, ctx.swap);
617 if (num_entries < 0 || num_entries > 4096) {
618 fprintf(stderr, "\"%s\" is not a valid object "
619 "(unreasonable num_entries %d).\n",
620 ctx.filename, num_entries);
624 for (int32_t i = 0; i < num_entries; i++) {
625 const String *str = read_string(ctx);
627 Symbol *sym = lookup_sym_in_ns_noyyerror(ctx, s, str);
628 Datum *d = dynamic_cast<Datum *>(sym);
631 fprintf(stderr, "\"%s\" is not a valid object "
632 "(\"%s\" is not a datum).\n",
633 ctx.filename, str->c_str());
640 if (s->def.flags.field.Super) {
641 const String *str = read_string(ctx);
642 Symbol *sym = lookup_sym_noyyerror(ctx, str);
643 Struct *super = dynamic_cast<Struct *>(sym);
646 fprintf(stderr, "\"%s\" is not a valid object "
647 "(\"%s\" is not a struct).\n",
648 ctx.filename, str->c_str());
654 if (super->is_virtual() && !s->is_virtual()) {
655 fprintf(stderr, "\"%s\" is not a valid object "
656 "(not virtual but parent is).\n",
662 assert(num_entries == s->def.num_entries);
666 // OPT: Importing elements isn't necessary for idlc to work (at
667 // least, not unless inheritance is implemented); it could be made
668 // optional to speed up large compilations.
670 BitField *BitField::import(ImportContext &ctx)
673 fprintf(stderr, "\"%s\" is not a valid object "
674 "(a BitField must be a directory).\n",
679 CompiledBitField def;
680 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
681 throw IOError(ctx.f);
683 BitField *bf = new BitField(ctx.name);
684 bf->path = new String(ctx.filename);
685 ctx.parent->add_import(bf, ctx.filename);
687 int32_t num_entries = swap32(def.num_entries, ctx.swap);
688 bf->def.bits = swap32(def.bits, ctx.swap);
690 if (num_entries < 0 || num_entries > 4096) {
691 fprintf(stderr, "\"%s\" is not a valid object "
692 "(unreasonable num_entries %d).\n",
693 ctx.filename, num_entries);
697 // FIXME: bits can only be 16, 32, or 64 when not in another bitfield.
699 if (bf->def.bits < 1 || bf->def.bits > 64) {
700 fprintf(stderr, "\"%s\" is not a valid object "
701 "(unreasonable bits %d).\n",
702 ctx.filename, num_entries);
706 for (int32_t i = 0; i < num_entries; i++) {
707 const String *str = read_string(ctx);
708 Symbol *sym = lookup_sym_in_ns_noyyerror(ctx, bf, str);
709 Datum *d = dynamic_cast<Datum *>(sym);
712 fprintf(stderr, "\"%s\" is not a valid object "
713 "(\"%s\" is not a datum).\n",
714 ctx.filename, str->c_str());
721 assert(num_entries == bf->def.num_entries);
725 // OPT: Importing elements isn't necessary for idlc to work (at
726 // least, not unless inheritance is implemented); it could be made
727 // optional to speed up large compilations.
729 Enum *Enum::import(ImportContext &ctx)
732 fprintf(stderr, "\"%s\" is not a valid object "
733 "(a Enum must be a directory).\n",
739 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
740 throw IOError(ctx.f);
742 Enum *e = new Enum(ctx.name);
743 e->path = new String(ctx.filename);
744 ctx.parent->add_import(e, ctx.filename);
746 int32_t num_entries = swap32(def.num_entries, ctx.swap);
747 e->def.bits = swap32(def.bits, ctx.swap);
749 if (num_entries < 0 || num_entries > 4096) {
750 fprintf(stderr, "\"%s\" is not a valid object "
751 "(unreasonable num_entries %d).\n",
752 ctx.filename, num_entries);
756 // FIXME: bits can only be 16, 32, or 64 when not in another bitfield.
758 if (e->def.bits < 1 || e->def.bits > 64) {
759 fprintf(stderr, "\"%s\" is not a valid object "
760 "(unreasonable bits %d).\n",
761 ctx.filename, num_entries);
765 for (int32_t i = 0; i < num_entries; i++) {
766 const String *str = read_string(ctx);
767 Symbol *sym = lookup_sym_in_ns_noyyerror(ctx, e, str);
768 Datum *d = dynamic_cast<Datum *>(sym);
771 fprintf(stderr, "\"%s\" is not a valid object "
772 "(\"%s\" is not a datum).\n",
773 ctx.filename, str->c_str());
780 assert(num_entries == e->def.num_entries);
784 Alias *Alias::import(ImportContext &ctx)
787 fprintf(stderr, "\"%s\" is not a valid object "
788 "(an Alias must be a file).\n",
793 Alias *a = new Alias(ctx.name);
794 ctx.parent->add_import(a, ctx.filename);
796 const String *str = read_string(ctx);
797 Symbol *sym = lookup_sym_noyyerror(ctx, str);
799 Alias *aptr = dynamic_cast<Alias *>(sym);
801 fprintf(stderr, "\"%s\" is not a valid object "
802 "(points to \"%s\", which is an alias).\n",
803 ctx.filename, str->c_str());
808 a->sym_fq_name = str;
809 a->def.length = str->length();
814 TypeDef *TypeDef::import(ImportContext &ctx)
817 fprintf(stderr, "\"%s\" is not a valid object "
818 "(a TypeDef must be a file).\n",
823 TypeDef *td = new TypeDef(ctx.name);
824 ctx.parent->add_import(td, ctx.filename);
826 const String *str = read_string(ctx);
827 Symbol *sym = lookup_sym_noyyerror(ctx, str);
829 Alias *aptr = dynamic_cast<Alias *>(sym);
831 fprintf(stderr, "\"%s\" is not a valid object "
832 "(points to \"%s\", which is an alias).\n",
833 ctx.filename, str->c_str());
838 td->sym_fq_name = str;
839 td->def.length = str->length();
844 UserNameSpace *UserNameSpace::import(ImportContext &ctx)
847 fprintf(stderr, "\"%s\" is not a valid object "
848 "(a NameSpace must be a directory).\n",
853 UserNameSpace *uns = new UserNameSpace();
854 uns->path = new String(ctx.filename);
856 // FIXME: sanity check the mount point
858 uns->name = ctx.name;
859 ctx.parent->add_import(uns, ctx.filename);
863 Symbol *do_load(ImportContext &ctx)
865 int type = swap32(ctx.hdr.type, ctx.swap);
868 case CompiledDefHeader::NameSpace:
869 return UserNameSpace::import(ctx);
872 case CompiledDefHeader::BasicType:
873 return BasicType::import(ctx);
876 case CompiledDefHeader::Datum:
877 return Datum::import(ctx);
880 case CompiledDefHeader::Interface:
881 return Interface::import(ctx);
884 case CompiledDefHeader::Method:
885 return Method::import(ctx);
888 case CompiledDefHeader::Param:
889 return Param::import(ctx);
892 case CompiledDefHeader::Struct:
893 return Struct::import(ctx);
896 case CompiledDefHeader::Enum:
897 return Enum::import(ctx);
900 case CompiledDefHeader::BitField:
901 return BitField::import(ctx);
904 case CompiledDefHeader::Alias:
905 ctx.is_typedef = false;
906 return Alias::import(ctx);
909 case CompiledDefHeader::TypeDef:
910 ctx.is_typedef = true;
911 return TypeDef::import(ctx);
915 fprintf(stderr, "\"%s\" is not a valid object "
916 "(bad type %08x).\n",
923 Symbol *NameSpace::load(const String *symname)
926 const String *mangled = mangle(symname);
928 ctx.name = new String(*symname);
932 string filename_no_self(path);
933 filename_no_self += '/';
934 filename_no_self += *mangled;
935 ctx.filename = filename_no_self.c_str();
937 string filename(filename_no_self);
938 filename.append("/.self");
940 ctx.f = fopen(filename.c_str(), "rb");
943 ctx.f = fopen(ctx.filename, "rb");
948 filename = filename_no_self;
953 if (fread(&ctx.hdr, sizeof(ctx.hdr), 1, ctx.f) != 1)
954 throw IOError(ctx.f);
956 if (ctx.hdr.magic == CompiledDefHeader::magic_normal)
958 else if (ctx.hdr.magic == CompiledDefHeader::magic_reversed)
961 fprintf(stderr, "\"%s\" is not a valid object "
962 "(bad magic 0x%08x).\n",
963 ctx.filename, ctx.hdr.magic);
972 fprintf(stderr, "Cannot read from file \"%s\": %s.\n",
973 ctx.filename, e.msg);
981 NameSpace *check_for_imports(NameSpace *ns)
993 void UserNameSpace::declare_import(const char *path)
996 UserNameSpace *ns = new UserNameSpace();
997 string filename(path);
998 filename.append("/.self");
1001 ctx.filename = path;
1003 ctx.f = fopen(filename.c_str(), "rb");
1005 fprintf(stderr, "Cannot import \"%s\": %s.\n",
1006 path, strerror(errno));
1011 const String *mount;
1013 if (fread(&ctx.hdr, sizeof(ctx.hdr), 1, ctx.f) != 1)
1014 throw IOError(ctx.f);
1016 if (ctx.hdr.magic == CompiledDefHeader::magic_normal)
1018 else if (ctx.hdr.magic == CompiledDefHeader::magic_reversed)
1021 fprintf(stderr, "\"%s\" is not a valid object "
1022 "(bad magic 0x%08x).\n",
1023 ctx.filename, ctx.hdr.magic);
1028 mount = read_string(ctx);
1031 catch (IOError &e) {
1032 fprintf(stderr, "Cannot read from file \"%s\": %s.\n",
1033 ctx.filename, e.msg);
1038 StrList *strl = new StrList(mount);
1040 fprintf(stderr, "\"%s\" is not a valid object "
1041 "(mount point \"%s\" is not valid).\n",
1042 ctx.filename, mount->c_str());
1047 ns->name = strl->back();
1050 if (strl->size() != 0) {
1051 ctx.parent = add_nspace(strl, false);
1056 NameSpace *conflict = check_for_imports(ctx.parent);
1058 fprintf(stderr, "Import \"%s\" conflicts"
1059 " with \"%s\" at \"%s\".\n",
1060 path, conflict->get_fq_name()->flatten()->c_str(),
1061 conflict->get_path()->c_str());
1066 ctx.parent = toplevel;
1069 ns->path = new String(path);
1070 ctx.parent->add_import(ns, ctx.filename);
1073 void NameSpace::import_all()
1078 DIR *dir = opendir(path->c_str());
1080 fprintf(stderr, "Cannot open directory \"%s\".\n", path->c_str());
1084 struct dirent ent, *entp;
1086 // readdir_r is buggy on osx 10.2, and will fail if errno is
1090 if (readdir_r(dir, &ent, &entp)) {
1091 fprintf(stderr, "1 Cannot readdir on \"%s\": %s.\n",
1092 path->c_str(), strerror(errno));
1101 // Ignore ".", "..", and ".self".
1102 if (ent.d_name[0] == '.')
1106 char *under = strchr(ent.d_name, '_');
1108 fprintf(stderr, "\"%s\" is not a valid namespace "
1109 "(bad member \"%s\").\n",
1110 path->c_str(), ent.d_name);
1115 String *s = new String(under + 1);
1119 catch (SymbolNotFound) {
1120 fprintf(stderr, "\"%s\" is not a valid namespace "
1121 "(member \"%s\" disappeared).\n",
1122 path->c_str(), ent.d_name);
1132 void NameSpace::import_all_recursive()
1136 for (const_iterator i = begin(); i != end(); ++i) {
1137 Symbol *sym = (*i).second;
1138 NameSpace *ns = dynamic_cast<NameSpace *>(sym);
1140 ns->import_all_recursive();