1 /* input.cc -- Code to load symbols from a legacy filesystem
3 * Written by Scott Wood <scott@buserror.net>
17 // To deal with namespaces on a case-insensitive filesystem, names
18 // are annotated with a hexadecimal prefix indicating the case of each
19 // letter. Each bit in the number represents a letter, with 0 being
20 // lowercase (or a non-letter) and 1 being uppercase. The
21 // least-significant bit is the first letter. This is done on both
22 // case sensitive and case insensitive filesystems so that the output
23 // can be freely copied between them (it also simplifies the code).
24 // As such, hex digits should be in upper case so that case-sensitive
25 // lookups can be used. This prefix is separated from the actual name
28 // When the time comes along that UTF-8 is supported, this applies to
29 // UTF-8 characters, not ASCII characters.
31 // This mangling can also be used (with a leading underscore or
32 // whatever) in case-insensitive languages, though ideally there
33 // should be aliases with the unannotated name if there is no
36 // I don't want to go the CORBA route of disallowing case conflicts,
37 // as I find using capitals for types and lowercase for instances to
38 // be a useful convention (and less ugly than appending _t, except
39 // when case sensitivity is missing), and would rather not be limited
40 // at such a fundamental level by broken languages.
42 static char tohex(int digit)
47 return digit + 'A' - 10;
50 const String *NameSpace::mangle(const String *name)
52 String *mangled_string = new String;
54 // The conversion is done manually so that I don't have to deal
55 // with bignum arithmetic.
57 std::vector<bool> hex;
58 std::vector<bool>::size_type name_len = name->length();
60 // Pad out the first digit with leading zeroes, so that
61 // we don't have to deal with that later.
64 for (int i = name_len & 3; i < 4; ++i)
67 for (string::const_iterator i = name->begin(); i != name->end(); ++i)
68 hex.push_back(isupper(*i));
70 assert((hex.size() & 3) == 0);
72 for (std::vector<bool>::size_type i = 0; i < hex.size(); i += 4) {
73 int digit = hex[i] * 8 +
78 *mangled_string += tohex(digit);
81 *mangled_string += '_';
82 *mangled_string += *name;
83 return mangled_string;
93 msg = strerror(ferror(f));
99 struct ImportContext {
101 const char *filename;
107 CompiledDefHeader hdr;
110 static void import_and_validate_array(ImportContext &ctx,
114 out.bounds[0] = swap64(in.bounds[0], ctx.swap);
115 out.bounds[1] = swap64(in.bounds[1], ctx.swap);
117 if (out.bounds[0] < 0) {
118 fprintf(stderr, "\"%s\" is not a valid object "
119 "(bad array lower bound %" PRId64 ").\n",
120 ctx.filename, out.bounds[0]);
124 if (out.bounds[1] < -1) {
125 fprintf(stderr, "\"%s\" is not a valid object "
126 "(bad array upper bound %" PRId64 ").\n",
127 ctx.filename, out.bounds[0]);
131 if (out.bounds[1] > 0 &&
132 out.bounds[1] < out.bounds[0]) {
133 fprintf(stderr, "\"%s\" is not a valid object "
134 "(array upper bound %" PRId64 " less than lower bound %" PRId64 ").\n",
135 ctx.filename, out.bounds[1], out.bounds[0]);
140 static void import_and_validate_basictype(ImportContext &ctx,
141 CompiledBasicType &out,
142 CompiledBasicType &in)
144 out.bits = swap32(in.bits, ctx.swap);
145 out.flags.raw = swap32(in.flags.raw, ctx.swap);
148 if (out.flags.field.Unsigned)
150 if (out.flags.field.Float)
152 if (out.flags.field.Bool)
155 fprintf(stderr, "\"%s\" is not a valid object "
156 "(bad flags 0x%08x).\n",
157 ctx.filename, out.flags.raw);
161 if (out.flags.field.Bool) {
163 fprintf(stderr, "\"%s\" is not a valid object "
164 "(bad bits %d for bool type).\n",
165 ctx.filename, out.bits);
168 } else if (out.flags.field.Float) {
169 if (out.bits != 32 && out.bits != 64) {
170 fprintf(stderr, "\"%s\" is not a valid object "
171 "(bad bits %d for floating point type).\n",
172 ctx.filename, out.bits);
175 } else if (!dynamic_cast<BitField *>(ctx.parent) &&
176 !dynamic_cast<Enum *>(ctx.parent)) {
177 if (out.bits != 8 && out.bits != 16 &&
178 out.bits != 32 && out.bits != 64) {
179 fprintf(stderr, "\"%s\" is not a valid object "
180 "(bad bits %d for integer type).\n",
181 ctx.filename, out.bits);
185 if (out.bits == 8 && !out.flags.field.Unsigned) {
186 fprintf(stderr, "\"%s\" is not a valid object "
187 "(octet type must be unsigned).\n",
193 // Bitfield entries can take anywhere from 1 to 64 bits, but
194 // will be verified by the parent after all entries have loaded,
195 // so it can verify that the sum does not exceed the size of
198 import_and_validate_array(ctx, out.array, in.array);
201 BasicType *BasicType::import(ImportContext &ctx)
204 fprintf(stderr, "\"%s\" is not a valid object "
205 "(a BasicType must be a file).\n",
210 CompiledBasicType def;
211 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
212 throw IOError(ctx.f);
214 BasicType *bt = new BasicType(ctx.name);
215 ctx.parent->add_import(bt, ctx.filename);
217 import_and_validate_basictype(ctx, bt->def, def);
223 static String *read_string_raw(ImportContext &ctx, int32_t length)
225 if (length < 0 || length > 4096) {
226 fprintf(stderr, "\"%s\" is not a valid object "
227 "(unreasonable string length %d).\n",
228 ctx.filename, length);
232 // Is there a way to reserve space in a C++ string, and pass
233 // the buffer into fread?
235 char *buf = new char[length + 1];
237 if (fread(buf, length + 1, 1, ctx.f) != 1)
238 throw IOError(ctx.f);
240 String *s = new String(buf);
245 static const String *read_string(ImportContext &ctx)
247 off_t pos = ftello(ctx.f);
248 int pad = ((pos + 3) & ~3) - pos;
250 if (pad != 0 && fseeko(ctx.f, pad, SEEK_CUR) != 0)
251 throw IOError(ctx.f);
254 if (fread(&length, sizeof(length), 1, ctx.f) != 1)
255 throw IOError(ctx.f);
257 return read_string_raw(ctx, swap32(length, ctx.swap));
260 StrList::StrList(const String *input, char delimeter)
262 const char *cur = input->c_str();
265 char *next = strchr(cur, delimeter);
266 String *s = new String();
267 s->token = TOK_IDENT;
269 if (next == cur || *cur == 0)
270 throw InvalidArgument();
273 s->append(cur, next - cur);
284 // FIXME: Handle illegal recursion.
285 static Symbol *lookup_sym_noyyerror(ImportContext &ctx, const String *name)
290 sl = new StrList(name);
293 catch (InvalidArgument) {
294 fprintf(stderr, "\"%s\" is not a valid object "
295 "(\"%s\" is not a valid identifier).\n",
296 ctx.filename, name->c_str());
301 return lookup_sym(toplevel, sl, toplevel);
305 fprintf(stderr, "\"%s\" is not a valid object "
306 "(\"%s\" could not be loaded).\n",
307 ctx.filename, name->c_str());
313 // FIXME: Handle illegal recursion.
314 static Symbol *lookup_sym_in_ns_noyyerror(ImportContext &ctx,
318 Symbol *sym = ns->lookup_noex(name);
320 fprintf(stderr, "\"%s\" is not a valid object "
321 "(\"%s\" is not found).\n",
322 ctx.filename, name->c_str());
330 Datum *Datum::import(ImportContext &ctx)
333 fprintf(stderr, "\"%s\" is not a valid object "
334 "(a Datum must be a file).\n",
340 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
341 throw IOError(ctx.f);
343 Datum *d = new Datum(ctx.name);
344 d->def.flags.raw = swap32(def.flags.raw, ctx.swap);
346 if (d->def.flags.field.Invalid) {
347 fprintf(stderr, "\"%s\" is not a valid object "
348 "(bad flags 0x%08x).\n",
349 ctx.filename, d->def.flags.raw);
353 ctx.parent->add_import(d, ctx.filename);
355 d->def.type.length = swap32(def.type.length, ctx.swap);
357 if (d->def.type.length != 0) {
358 d->type_fq_name = read_string_raw(ctx, d->def.type.length);
359 Symbol *sym = lookup_sym_noyyerror(ctx, d->type_fq_name);
360 d->type = dynamic_cast<Type *>(sym);
363 fprintf(stderr, "\"%s\" is not a valid object "
364 "(\"%s\" is not a type).\n",
365 ctx.filename, d->type_fq_name->c_str());
369 import_and_validate_array(ctx, d->def.basictype.array,
370 def.basictype.array);
372 BasicType *bt = dynamic_cast<BasicType *>(*d->type);
379 import_and_validate_basictype(ctx, d->def.basictype,
381 d->cbt = &d->def.basictype;
384 d->def.ucon = swap64(def.ucon, ctx.swap);
386 if (d->def.flags.field.Const) {
388 fprintf(stderr, "\"%s\" is not a valid object "
389 "(constant, but non-basic type).\n",
394 if (d->cbt->flags.field.Float)
395 d->con_type = TOK_FCON;
396 else if (!d->cbt->flags.field.Unsigned)
397 d->con_type = TOK_ICON;
399 d->con_type = TOK_UCON;
401 if (!d->verify_const()) {
402 fprintf(stderr, "\"%s\" is not a valid object "
408 d->con_type = TOK_NONE;
414 // OPT: Importing methods and supers isn't necessary for idlc to
415 // work; it could be made optional to speed up large compilations.
417 Interface *Interface::import(ImportContext &ctx)
420 fprintf(stderr, "\"%s\" is not a valid object "
421 "(an Interface must be a directory).\n",
426 CompiledInterface def;
427 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
428 throw IOError(ctx.f);
430 Interface *iface = new Interface(ctx.name);
431 iface->path = new String(ctx.filename);
432 ctx.parent->add_import(iface, ctx.filename);
434 iface->def.guid[0] = def.guid[0];
435 iface->def.guid[1] = def.guid[1];
437 int32_t num_methods = swap32(def.num_methods, ctx.swap);
438 int32_t num_supers = swap32(def.num_supers, ctx.swap);
440 if (num_methods < 0 || num_methods > 4096) {
441 fprintf(stderr, "\"%s\" is not a valid object "
442 "(unreasonable num_methods %d).\n",
443 ctx.filename, num_methods);
447 if (num_supers < 0 || num_supers > 4096) {
448 fprintf(stderr, "\"%s\" is not a valid object "
449 "(unreasonable num_supers %d).\n",
450 ctx.filename, num_supers);
454 for (int32_t i = 0; i < num_methods; i++) {
455 const String *str = read_string(ctx);
456 Symbol *sym = lookup_sym_in_ns_noyyerror(ctx, iface, str);
457 Method *m = dynamic_cast<Method *>(sym);
460 fprintf(stderr, "\"%s\" is not a valid object "
461 "(\"%s\" is not a method).\n",
462 ctx.filename, str->c_str());
469 // FIXME: Check for bad recursion again
471 for (int32_t i = 0; i < num_supers; i++) {
472 const String *str = read_string(ctx);
473 Symbol *sym = lookup_sym_noyyerror(ctx, str);
474 Interface *super = dynamic_cast<Interface *>(sym);
477 fprintf(stderr, "\"%s\" is not a valid object "
478 "(\"%s\" is not an interface).\n",
479 ctx.filename, str->c_str());
483 iface->add_super(super);
486 assert(num_methods == iface->def.num_methods);
487 assert(num_supers == iface->def.num_supers);
489 iface->sort_chains();
493 Method *Method::import(ImportContext &ctx)
496 fprintf(stderr, "\"%s\" is not a valid object "
497 "(a Method must be a directory).\n",
503 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
504 throw IOError(ctx.f);
506 Method *m = new Method(ctx.name);
507 m->path = new String(ctx.filename);
508 ctx.parent->add_import(m, ctx.filename);
510 int32_t num_entries = swap32(def.num_entries, ctx.swap);
512 m->def.flags.raw = swap32(def.flags.raw, ctx.swap);
514 if (num_entries < 0 || num_entries > 4096) {
515 fprintf(stderr, "\"%s\" is not a valid object "
516 "(unreasonable num_entries %d).\n",
517 ctx.filename, num_entries);
521 for (int32_t i = 0; i < num_entries; i++) {
522 const String *str = read_string(ctx);
523 Symbol *sym = lookup_sym_in_ns_noyyerror(ctx, m, str);
524 Param *p = dynamic_cast<Param *>(sym);
527 fprintf(stderr, "\"%s\" is not a valid object "
528 "(\"%s\" is not a parameter).\n",
529 ctx.filename, str->c_str());
536 assert(num_entries == m->def.num_entries);
540 Param *Param::import(ImportContext &ctx)
543 fprintf(stderr, "\"%s\" is not a valid object "
544 "(a Parameter must be a file).\n",
550 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
551 throw IOError(ctx.f);
553 Param *p = new Param(ctx.name);
554 ctx.parent->add_import(p, ctx.filename);
556 p->def.type.length = swap32(def.type.length, ctx.swap);
558 if (p->def.type.length != 0) {
559 p->type_fq_name = read_string_raw(ctx, p->def.type.length);
560 Symbol *sym = lookup_sym_noyyerror(ctx, p->type_fq_name);
561 p->type = dynamic_cast<Type *>(sym);
564 fprintf(stderr, "\"%s\" is not a valid object "
565 "(\"%s\" is not a type).\n",
566 ctx.filename, p->type_fq_name->c_str());
570 import_and_validate_array(ctx, p->def.basictype.array,
571 def.basictype.array);
573 import_and_validate_basictype(ctx, p->def.basictype,
577 p->def.flags.raw = swap32(def.flags.raw, ctx.swap);
581 // OPT: Importing data and super isn't necessary for idlc to
582 // work; it could be made optional to speed up large compilations.
584 Struct *Struct::import(ImportContext &ctx)
587 fprintf(stderr, "\"%s\" is not a valid object "
588 "(a Struct must be a directory).\n",
594 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
595 throw IOError(ctx.f);
597 Struct *s = new Struct(ctx.name);
598 s->path = new String(ctx.filename);
599 ctx.parent->add_import(s, ctx.filename);
601 s->def.guid[0] = def.guid[0];
602 s->def.guid[1] = def.guid[1];
604 int32_t num_entries = swap32(def.num_entries, ctx.swap);
606 s->def.flags.raw = swap32(def.flags.raw, ctx.swap);
608 if (num_entries < 0 || num_entries > 4096) {
609 fprintf(stderr, "\"%s\" is not a valid object "
610 "(unreasonable num_entries %d).\n",
611 ctx.filename, num_entries);
615 for (int32_t i = 0; i < num_entries; i++) {
616 const String *str = read_string(ctx);
618 Symbol *sym = lookup_sym_in_ns_noyyerror(ctx, s, str);
619 Datum *d = dynamic_cast<Datum *>(sym);
622 fprintf(stderr, "\"%s\" is not a valid object "
623 "(\"%s\" is not a datum).\n",
624 ctx.filename, str->c_str());
631 if (s->def.flags.field.Super) {
632 const String *str = read_string(ctx);
633 Symbol *sym = lookup_sym_noyyerror(ctx, str);
634 Struct *super = dynamic_cast<Struct *>(sym);
637 fprintf(stderr, "\"%s\" is not a valid object "
638 "(\"%s\" is not a struct).\n",
639 ctx.filename, str->c_str());
645 if (super->is_virtual() && !s->is_virtual()) {
646 fprintf(stderr, "\"%s\" is not a valid object "
647 "(not virtual but parent is).\n",
653 assert(num_entries == s->def.num_entries);
657 // OPT: Importing elements isn't necessary for idlc to work (at
658 // least, not unless inheritance is implemented); it could be made
659 // optional to speed up large compilations.
661 BitField *BitField::import(ImportContext &ctx)
664 fprintf(stderr, "\"%s\" is not a valid object "
665 "(a BitField must be a directory).\n",
670 CompiledBitField def;
671 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
672 throw IOError(ctx.f);
674 BitField *bf = new BitField(ctx.name);
675 bf->path = new String(ctx.filename);
676 ctx.parent->add_import(bf, ctx.filename);
678 int32_t num_entries = swap32(def.num_entries, ctx.swap);
679 bf->def.bits = swap32(def.bits, ctx.swap);
681 if (num_entries < 0 || num_entries > 4096) {
682 fprintf(stderr, "\"%s\" is not a valid object "
683 "(unreasonable num_entries %d).\n",
684 ctx.filename, num_entries);
688 // FIXME: bits can only be 16, 32, or 64 when not in another bitfield.
690 if (bf->def.bits < 1 || bf->def.bits > 64) {
691 fprintf(stderr, "\"%s\" is not a valid object "
692 "(unreasonable bits %d).\n",
693 ctx.filename, num_entries);
697 for (int32_t i = 0; i < num_entries; i++) {
698 const String *str = read_string(ctx);
699 Symbol *sym = lookup_sym_in_ns_noyyerror(ctx, bf, str);
700 Datum *d = dynamic_cast<Datum *>(sym);
703 fprintf(stderr, "\"%s\" is not a valid object "
704 "(\"%s\" is not a datum).\n",
705 ctx.filename, str->c_str());
712 assert(num_entries == bf->def.num_entries);
716 // OPT: Importing elements isn't necessary for idlc to work (at
717 // least, not unless inheritance is implemented); it could be made
718 // optional to speed up large compilations.
720 Enum *Enum::import(ImportContext &ctx)
723 fprintf(stderr, "\"%s\" is not a valid object "
724 "(a Enum must be a directory).\n",
730 if (fread(&def, sizeof(def), 1, ctx.f) != 1)
731 throw IOError(ctx.f);
733 Enum *e = new Enum(ctx.name);
734 e->path = new String(ctx.filename);
735 ctx.parent->add_import(e, ctx.filename);
737 int32_t num_entries = swap32(def.num_entries, ctx.swap);
738 e->def.bits = swap32(def.bits, ctx.swap);
740 if (num_entries < 0 || num_entries > 4096) {
741 fprintf(stderr, "\"%s\" is not a valid object "
742 "(unreasonable num_entries %d).\n",
743 ctx.filename, num_entries);
747 // FIXME: bits can only be 16, 32, or 64 when not in another bitfield.
749 if (e->def.bits < 1 || e->def.bits > 64) {
750 fprintf(stderr, "\"%s\" is not a valid object "
751 "(unreasonable bits %d).\n",
752 ctx.filename, num_entries);
756 for (int32_t i = 0; i < num_entries; i++) {
757 const String *str = read_string(ctx);
758 Symbol *sym = lookup_sym_in_ns_noyyerror(ctx, e, str);
759 Datum *d = dynamic_cast<Datum *>(sym);
762 fprintf(stderr, "\"%s\" is not a valid object "
763 "(\"%s\" is not a datum).\n",
764 ctx.filename, str->c_str());
771 assert(num_entries == e->def.num_entries);
775 Alias *Alias::import(ImportContext &ctx)
778 fprintf(stderr, "\"%s\" is not a valid object "
779 "(an Alias must be a file).\n",
784 Alias *a = new Alias(ctx.name);
785 ctx.parent->add_import(a, ctx.filename);
787 const String *str = read_string(ctx);
788 Symbol *sym = lookup_sym_noyyerror(ctx, str);
790 Alias *aptr = dynamic_cast<Alias *>(sym);
792 fprintf(stderr, "\"%s\" is not a valid object "
793 "(points to \"%s\", which is an alias).\n",
794 ctx.filename, str->c_str());
799 a->sym_fq_name = str;
800 a->def.length = str->length();
805 TypeDef *TypeDef::import(ImportContext &ctx)
808 fprintf(stderr, "\"%s\" is not a valid object "
809 "(a TypeDef must be a file).\n",
814 TypeDef *td = new TypeDef(ctx.name);
815 ctx.parent->add_import(td, ctx.filename);
817 const String *str = read_string(ctx);
818 Symbol *sym = lookup_sym_noyyerror(ctx, str);
820 Alias *aptr = dynamic_cast<Alias *>(sym);
822 fprintf(stderr, "\"%s\" is not a valid object "
823 "(points to \"%s\", which is an alias).\n",
824 ctx.filename, str->c_str());
829 td->sym_fq_name = str;
830 td->def.length = str->length();
835 UserNameSpace *UserNameSpace::import(ImportContext &ctx)
838 fprintf(stderr, "\"%s\" is not a valid object "
839 "(a NameSpace must be a directory).\n",
844 UserNameSpace *uns = new UserNameSpace();
845 uns->path = new String(ctx.filename);
847 // FIXME: sanity check the mount point
849 uns->name = ctx.name;
850 ctx.parent->add_import(uns, ctx.filename);
854 Symbol *do_load(ImportContext &ctx)
856 int type = swap32(ctx.hdr.type, ctx.swap);
859 case CompiledDefHeader::NameSpace:
860 return UserNameSpace::import(ctx);
863 case CompiledDefHeader::BasicType:
864 return BasicType::import(ctx);
867 case CompiledDefHeader::Datum:
868 return Datum::import(ctx);
871 case CompiledDefHeader::Interface:
872 return Interface::import(ctx);
875 case CompiledDefHeader::Method:
876 return Method::import(ctx);
879 case CompiledDefHeader::Param:
880 return Param::import(ctx);
883 case CompiledDefHeader::Struct:
884 return Struct::import(ctx);
887 case CompiledDefHeader::Enum:
888 return Enum::import(ctx);
891 case CompiledDefHeader::BitField:
892 return BitField::import(ctx);
895 case CompiledDefHeader::Alias:
896 ctx.is_typedef = false;
897 return Alias::import(ctx);
900 case CompiledDefHeader::TypeDef:
901 ctx.is_typedef = true;
902 return TypeDef::import(ctx);
906 fprintf(stderr, "\"%s\" is not a valid object "
907 "(bad type %08x).\n",
914 Symbol *NameSpace::load(const String *symname)
917 const String *mangled = mangle(symname);
919 ctx.name = new String(*symname);
923 string filename_no_self(path);
924 filename_no_self += '/';
925 filename_no_self += *mangled;
926 ctx.filename = filename_no_self.c_str();
928 string filename(filename_no_self);
929 filename.append("/.self");
931 ctx.f = fopen(filename.c_str(), "rb");
934 ctx.f = fopen(ctx.filename, "rb");
939 filename = filename_no_self;
944 if (fread(&ctx.hdr, sizeof(ctx.hdr), 1, ctx.f) != 1)
945 throw IOError(ctx.f);
947 if (ctx.hdr.magic == CompiledDefHeader::magic_normal)
949 else if (ctx.hdr.magic == CompiledDefHeader::magic_reversed)
952 fprintf(stderr, "\"%s\" is not a valid object "
953 "(bad magic 0x%08x).\n",
954 ctx.filename, ctx.hdr.magic);
963 fprintf(stderr, "Cannot read from file \"%s\": %s.\n",
964 ctx.filename, e.msg);
972 NameSpace *check_for_imports(NameSpace *ns)
984 void UserNameSpace::declare_import(const char *path)
987 UserNameSpace *ns = new UserNameSpace();
988 string filename(path);
989 filename.append("/.self");
994 ctx.f = fopen(filename.c_str(), "rb");
996 fprintf(stderr, "Cannot import \"%s\": %s.\n",
997 path, strerror(errno));
1002 const String *mount;
1004 if (fread(&ctx.hdr, sizeof(ctx.hdr), 1, ctx.f) != 1)
1005 throw IOError(ctx.f);
1007 if (ctx.hdr.magic == CompiledDefHeader::magic_normal)
1009 else if (ctx.hdr.magic == CompiledDefHeader::magic_reversed)
1012 fprintf(stderr, "\"%s\" is not a valid object "
1013 "(bad magic 0x%08x).\n",
1014 ctx.filename, ctx.hdr.magic);
1019 mount = read_string(ctx);
1022 catch (IOError &e) {
1023 fprintf(stderr, "Cannot read from file \"%s\": %s.\n",
1024 ctx.filename, e.msg);
1029 StrList *strl = new StrList(mount);
1031 fprintf(stderr, "\"%s\" is not a valid object "
1032 "(mount point \"%s\" is not valid).\n",
1033 ctx.filename, mount->c_str());
1038 ns->name = strl->back();
1041 if (strl->size() != 0) {
1042 ctx.parent = add_nspace(strl, false);
1047 NameSpace *conflict = check_for_imports(ctx.parent);
1049 fprintf(stderr, "Import \"%s\" conflicts"
1050 " with \"%s\" at \"%s\".\n",
1051 path, conflict->get_fq_name()->flatten()->c_str(),
1052 conflict->get_path()->c_str());
1057 ctx.parent = toplevel;
1060 ns->path = new String(path);
1061 ctx.parent->add_import(ns, ctx.filename);
1064 void NameSpace::import_all()
1069 DIR *dir = opendir(path->c_str());
1071 fprintf(stderr, "Cannot open directory \"%s\".\n", path->c_str());
1075 struct dirent ent, *entp;
1077 // readdir_r is buggy on osx 10.2, and will fail if errno is
1081 if (readdir_r(dir, &ent, &entp)) {
1082 fprintf(stderr, "1 Cannot readdir on \"%s\": %s.\n",
1083 path->c_str(), strerror(errno));
1092 // Ignore ".", "..", and ".self".
1093 if (ent.d_name[0] == '.')
1097 char *under = strchr(ent.d_name, '_');
1099 fprintf(stderr, "\"%s\" is not a valid namespace "
1100 "(bad member \"%s\").\n",
1101 path->c_str(), ent.d_name);
1106 String *s = new String(under + 1);
1110 catch (SymbolNotFound) {
1111 fprintf(stderr, "\"%s\" is not a valid namespace "
1112 "(member \"%s\" disappeared).\n",
1113 path->c_str(), ent.d_name);
1123 void NameSpace::import_all_recursive()
1127 for (const_iterator i = begin(); i != end(); ++i) {
1128 Symbol *sym = (*i).second;
1129 NameSpace *ns = dynamic_cast<NameSpace *>(sym);
1131 ns->import_all_recursive();