1 // idlc.h -- Definitions used throughout idlc.
2 // A lot of this should probably be factored out into more specific headers.
4 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
6 // This software is provided 'as-is', without any express or implied warranty.
7 // In no event will the authors or contributors be held liable for any damages
8 // arising from the use of this software.
10 // Permission is hereby granted to everyone, free of charge, to use, copy,
11 // modify, prepare derivative works of, publish, distribute, perform,
12 // sublicense, and/or sell copies of the Software, provided that the above
13 // copyright notice and disclaimer of warranty be included in all copies or
14 // substantial portions of this software.
19 // inttypes.h on OSX assumes it can use restrict, but C++ doesn't have it.
20 // Hopefully C++ will catch up to C soon...
34 #include "compileddef.h"
45 #define cdl_lex idl_lex
46 void idl_error(char *s);
48 #define cdl_error idl_error
50 void setup_idlparse();
51 void setup_cdlparse();
54 void yyerrorf(const char *s, ...) __attribute__((format(printf, 1, 2)));
55 void yyerrorfl(const char *file, int line, const char *s, ...)
56 __attribute__((format(printf, 3, 4)));
58 void yyerrorf(const char *s, ...);
59 void yyerrorfl(const char *file, int line, const char *s, ...);
66 extern int idl_debug, cdl_debug, curline, impl, num_err;
67 extern int current_pass;
69 extern unsigned int enum_pos;
70 extern const char *cur_input_file;
71 extern int compiling_idl, compiling_cdl;
76 // Location in the IDLC source of the BUG()
80 InternalError(const char *file, int line) :
81 file(file), line(line)
87 throw InternalError(__FILE__, __LINE__); \
92 #define assert(x) do { \
100 virtual ~Releasable()
104 Releasable(int COUNT) : count(COUNT)
111 fprintf(stderr, "Reference count is %d in release\n", count);
120 class AutoReleasePool {
121 list<const Releasable *> pool;
124 void add(const Releasable *obj)
131 for (list<const Releasable *>::iterator i = pool.begin();
132 i != pool.end(); ++i)
134 const Releasable *obj = *i;
142 extern AutoReleasePool autorelease_pool;
144 template <typename T>
145 class RefCountable : public Releasable {
147 // RefCountable objects should never be assigned to,
148 // as there could be references to the object remaining.
149 // The private assignment operator prevents this, unless
150 // a subclass defines its own assigment operator (don't
152 void operator =(const RefCountable &rc)
157 RefCountable(const RefCountable &rc) : Releasable(1)
163 RefCountable() : Releasable(1)
165 // Normally, this wouldn't be automatic, but this is what most
166 // things in IDLC are going to want, and it elimanates problems
167 // with needing to cast the return type of autorelease().
169 // The automatic autorelease() means that all refcountable objects
170 // must be allocated with "new", not on the stack, as global
171 // data, or as a class member.
176 virtual ~RefCountable()
180 const T *retain() const
183 fprintf(stderr, "Reference count is %d in retain\n", count);
188 return static_cast<const T *>(this);
194 fprintf(stderr, "Reference count is %d in retain\n", count);
199 return static_cast<T *>(this);
202 const T *autorelease() const
204 autorelease_pool.add(static_cast<Releasable *>(this));
205 return static_cast<T *>(this);
210 autorelease_pool.add(static_cast<Releasable *>(this));
211 return static_cast<T *>(this);
214 // This is only here because C++ obnoxiously requires it to
215 // be just because it's "called" from code excluded with an
216 // if (0) in a template. No code is ever generated that calls
217 // it, but it still must exist.
219 bool operator < (const RefCountable &rc)
225 // T must be RefCountable
226 template<typename T, bool compare_ptrs = true>
228 // STL containers like to use const on the items they
229 // contain; the mutable allows such containers to hold
230 // pointers to non-const data. For truly const Refs,
231 // make T const, as in StringRef. Unfortunately,
232 // it cannot be done in a more fine-grained manner,
244 Ref(T *data) : data(data)
250 Ref(Ref &le) : data(le.data)
256 Ref &operator =(const Ref &le)
258 // The retain must come first, in case both Refs are the same
269 Ref &operator =(T *new_data)
271 // The retain must come first, in case both Refs are the same
298 T *operator *() const
303 T *operator ->() const
308 bool operator == (const Ref &le) const
311 return data == le.data;
313 return *data == *le.data;
316 bool operator != (const Ref &le) const
319 return data != le.data;
321 return *data != *le.data;
324 bool operator < (const Ref &le) const
327 return reinterpret_cast<intptr_t>(data) <
328 reinterpret_cast<intptr_t>(le.data);
330 return *data < *le.data;
334 class String : public string, public RefCountable<String> {
336 // Origin of the string, if from the IDL file.
337 // Otherwise, fill both values with zero.
343 String(const char *s = "") : string(s)
350 String(const String &s) : string(s)
357 String(const char *s, const char *file, int line, int token) :
358 string(s), file(file), line(line), token(token)
362 extern String **yylval_string;
363 typedef Ref<const String, false> StringRef;
365 /* If a StrList is used for a namespace-qualified identifier, and
366 said identifier begins with ".." (i.e. starts from the root
367 namespace), the leading ".." is represented by a zero-length
370 Note that list doesn't have a virtual destructor, so all deletions
371 should happen through either RefCountable or the wrapper List
374 class StrList : public list<StringRef>, public RefCountable<StrList> {
380 // Parse a flat String into a StrList, using the specified delimeter.
381 StrList(const String *input, char delimiter = '.');
383 // Turn a StrList into a flat String, using the specified delimiter.
384 String *flatten(const char *delimiter = ".");
387 typedef Ref<StrList> StrListRef;
389 // ConList is like StrList, but with constant initializers
399 // FIXME: handle platforms with weird floating point endianness
405 // TOK_ICON, TOK_UCON, TOK_FCON, TOK_BOOL, TOK_DCON,
406 // TOK_INVALID, or TOK_NONE
407 // Constants are stored as signed (ICON) unless too
408 // large to fit in a signed 64-bit integer. Additional size and
409 // signedness checks are mode when down casting to a smaller size
410 // to fit into a particular datum; such constants will have a
413 // TOK_NONE is valid for maybeconst and size. TOK_INVALID
414 // indicates a previously detected error; don't emit any further
415 // errors due to this constant.
417 // TOK_DCON is used for symbolic constants, whose value may
423 extern Con *yylval_con;
429 ConInit(const String *str, Con &con) : str(str), con(con)
433 ConInit(const ConInit &coninit)
439 class ConList : public list<ConInit>, public RefCountable<ConList> {};
440 typedef Ref<ConList> ConListRef;
442 // Like StrList, but is a list of possibly namespace-qualified identifiers.
443 class IDList : public list<StrListRef>, public RefCountable<IDList> {};
444 typedef Ref<IDList> IDListRef;
450 // This is incremented when a chain of symbols is traversed to reset
451 // detection of already-visited symbols. It is assumed that this
452 // will not have to happen billions of times.
454 extern int traversal;
456 class Symbol : public RefCountable<Symbol> {
462 // Symbol was loaded externally
465 // If set, the symbol is private, and will not be available
466 // for lookups except those made directly in the context of
467 // the containing namespace. Private symbols do not get
468 // outputted. They are used to implement imports of specific
469 // symbols (as aliases), rather than entire namespaces.
473 // This is set to ::traversal when this symbol is visited along a chain.
474 // If a target needs more than 8 simultaneous chains, increase the size
475 // of the array. These traversals are reserved for language binding use.
485 memset(traversed, 0, sizeof(traversed));
488 Symbol(const String *_name) : name(_name)
497 memset(traversed, 0, sizeof(traversed));
502 NameSpace *get_ns() const
507 const String *get_name() const
512 // If append is non-NULL, it is appended to non-user namespaces,
513 // to facilitate a language binding that cannot place nested types
514 // in the same language construct as the actual interface. The
515 // recommended suffix is "_ns", which is a reserved ending in the
516 // IDL. No suffix is placed on the final component of the name,
517 // even if it is a non-user namespace. The not_last field is used
518 // to detect whether it is the final component; it is only used
519 // internally, and should always be false when called externally.
521 // This function does *NOT* add a null first element to indicate
522 // that the name is fully qualified. If you need that, you have
523 // to add it yourself (call 'push_front(new String(""))' on the
526 StrList *get_fq_name(const char *append = NULL,
527 bool not_last = false) const;
529 virtual void lookup_imports()
533 virtual void lookup_chain()
537 virtual void lookup_misc()
541 virtual void final_analysis()
545 // These two methods must be implemented by all IDL symbols, but are
546 // not needed in CDL symbols (and therefore are not pure virtual).
548 virtual void output(const char *root)
552 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL)
556 // Find and return the topmost symbol other than a user namespace
557 // containing this symbol. If this symbol's parent is a user
558 // namespace, it returns itself. May not be called on the
559 // toplevel namespace.
561 Symbol *find_toplevel_type();
563 // Get the true type of the symbol, regardless of whether it is an
566 virtual Symbol *get_concrete_sym(bool follow_typedefs = true)
571 friend class NameSpace;
574 typedef Ref<Symbol> SymbolRef;
576 class SymList : public list<SymbolRef>, public RefCountable<SymList> {};
577 typedef Ref<SymList> SymListRef;
579 struct SymbolNotFound {
582 struct DuplicateSymbol {
585 struct InvalidArgument {
591 typedef Ref<NameSpace> NameSpaceRef;
593 class NameSpace : public virtual Symbol {
595 // Filesystem path to the external symbol storage, or NULL
596 // if not an import namespace.
598 // Import namespaces are read-only namespaces which are created
599 // for the importation of externally-declared symbols. One is
600 // initially created for each "mount point" specified by the user;
601 // whenever such a namespace is searched, it checks the external
602 // storage, and if the lookup succeeds, the symbol is loaded and
603 // added to the namespace. Failed lookups could be cached with a
604 // special BadSymbol or some such, as the imported namespace is
605 // assumed to be constant, but I don't think such an optimization
606 // is worthwhile, at least at this point.
610 // Load a symbol from external storage, constructing the relevant type
611 // of object, and adding it to this namespace. Only called for
612 // import namespaces.
614 Symbol *load(const String *symname);
616 typedef map<StringRef, SymbolRef> tbl_type;
619 list<StrListRef> import_strs;
620 list<NameSpaceRef> imports;
623 // This is set in the destructor, so the contents of the namespace
624 // don't try to remove themselves from the namespace when destructed
625 // due to the destruction of map.
628 // This is a counter for generating unique names for anonymous
629 // members of the namespace.
632 NameSpace() : dying(0), anon(0)
641 // Return a description of the type of namespace, for
643 virtual const char *description()
648 virtual void output(const char *root);
650 typedef tbl_type::const_iterator const_iterator;
651 typedef tbl_type::value_type value_type;
653 // Derived classes can throw InvalidArgument if you give them
654 // a type of Symbol that they don't accept; see their comments
655 // for more details. Unfortunately, this cannot be done
656 // with static type-checking, as there are places that know
657 // they've been given a namespace that can accept a particular
658 // type of symbol, but they don't know exactly what kind of
659 // namespace it is. C++'s type system is not sufficient to
660 // express this (at least not while retaining any semblance
663 // DuplicateSymbol is thrown if sym already exists in this namespace.
664 virtual void add(Symbol *sym, bool from_import)
666 if (path && !from_import)
667 throw InvalidArgument();
670 sym->external = true;
675 pair<const_iterator, bool> ret = tbl.insert(value_type(sym->name, sym));
680 throw DuplicateSymbol();
684 // Add the symbol to this namespace, handling duplicate symbols by
685 // printing an error and throwing a UserError(). This should not be
686 // done in the symbol's constructor, as the parent may not accept
687 // the symbol until it is fully constructed (the RTTI information
688 // changes, and in general partially constructed objects shouldn't
689 // be exposed to the rest of the system).
691 void add_user(Symbol *sym);
693 // Like add_user, but used by the import code. Duplicate
694 // symbols result in internal errors, and the add is done with
695 // from_import set to true. InvalidArgument results in an error
696 // message and a reraise as UserError.
698 // All conditions checked by the parent namespace's add() method
699 // (such as constness of data) must be satisfied prior to calling
700 // add_import(). On the other hand, add_import() must be called
701 // before any recursive importation is done which could
702 // conceivably try to import the current symbol (thus causing
703 // infinite recursion).
705 void add_import(Symbol *sym, const char *filename);
707 // SymbolNotFound is thrown if sym is not in this namespace.
708 virtual void del(Symbol *sym)
710 fprintf(stderr, "Removing symbol %s\n",
711 sym->get_fq_name()->flatten()->c_str());
713 if (tbl.erase(sym->name) == 0)
714 throw SymbolNotFound();
720 Symbol *lookup_noex_noimport(const String *symname)
722 const_iterator ret = tbl.find(symname);
724 if (ret != tbl.end())
725 return (*ret).second;
731 Symbol *lookup_noex(const String *symname, bool priv_ok = false)
733 Symbol *ret = NameSpace::lookup_noex_noimport(symname);
738 if (ret && !priv_ok && ret->priv)
744 Symbol *lookup(const String *symname, bool priv_ok = false)
746 Symbol *ret = lookup_noex(symname, priv_ok);
749 throw SymbolNotFound();
754 // Like lookup_noex, but also checks imported namespaces,
755 // and returns the namespace containing the match rather
756 // than the match itself.
758 NameSpace *search(const String *name, Symbol *exclude);
760 void add_search(StrList *ns)
762 import_strs.push_back(ns);
765 // Return a string containing case information manglement.
766 // See input.cc for more information.
768 static const String *mangle(const String *name);
770 const String *get_path()
775 // Import all members of this namespace. A no-op if not an import
779 // As import_all, but also recursively applies to any sub-namespaces.
780 void import_all_recursive();
782 const_iterator begin()
792 virtual void lookup_imports();
794 virtual void lookup_chain()
796 for (const_iterator i = begin(); i != end(); ++i) {
797 Symbol *sym = (*i).second;
802 virtual void lookup_misc()
804 for (const_iterator i = begin(); i != end(); ++i) {
805 Symbol *sym = (*i).second;
810 virtual void final_analysis()
812 for (const_iterator i = begin(); i != end(); ++i) {
813 Symbol *sym = (*i).second;
814 sym->final_analysis();
820 extern NameSpaceRef cur_nspace;
821 extern list<NameSpaceRef> nspace_stack;
823 typedef std::vector<StringRef> StringVec;
825 string *stringvec_to_path(StringVec &stringvec, const char *prepend);
827 // lookup_sym and lookup_type throw UserError on user error
828 // The context namespace is required for the proper
829 // set of namespaces to be searched.
831 Symbol *lookup_sym(NameSpace *topns, StrList *name, NameSpace *ctx,
832 Symbol *exclude = NULL);
835 const char *self; // Pointer to the type-specific struct
836 int self_len; // Length of the type-specific struct
839 CompiledDefHeader hdr;
841 // sym is the symbol from which to get the path/name, and
842 // dir is true if it should be "name/.self" rather than
844 void output_self(const char *dir, Symbol *sym, bool dir);
847 Def(const char *self, int self_len, CompiledDefHeader::Type type) :
848 self(self), self_len(self_len)
850 hdr.magic = CompiledDefHeader::magic_normal;
858 // Specific types may override this to output extra data
859 // to the .self file without having to reopen the file.
861 // Returns false on error.
863 virtual bool output_extra(FILE *f)
869 // Internal context struct used by input.cc to avoid passing
870 // lots of parameters around
871 struct ImportContext;
873 // This represents an actual IDL namespace {}, rather than
874 // a derived namespace such as a Struct or Interface.
876 class UserNameSpace : public NameSpace, public Def {
878 CompiledNameSpace def;
879 StringRef mountpoint_name;
881 UserNameSpace(const String *name = NULL) :
883 Def((const char *)&def, sizeof(def), CompiledDefHeader::NameSpace)
885 mountpoint_name = get_fq_name()->flatten();
886 def.length = mountpoint_name->length();
889 virtual void output(const char *root);
890 bool output_extra(FILE *f);
892 static void declare_import(const char *path);
894 static UserNameSpace *import(ImportContext &ctx);
895 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
898 typedef Ref<UserNameSpace> UserNameSpaceRef;
899 extern UserNameSpaceRef toplevel, cdl_toplevel;
900 extern UserNameSpace *output_ns;
902 class Type : public virtual Symbol {
912 virtual int get_default_bf_size()
914 // Only allow types in bitfields that explicitly
921 typedef Ref<Type> TypeRef;
923 // ctx can be NULL if basic_types_only is true
924 Type *lookup_type(StrList *sl, NameSpace *ctx, bool basic_types_only = false);
926 class BasicType : public Type, public Def {
928 CompiledBasicType def;
931 BasicType(const String *name) :
933 Def((const char *)&def, sizeof(def), CompiledDefHeader::BasicType)
936 memset(&def, 0, sizeof(def));
939 void init(CompiledBasicType &DEF)
947 static BasicType *declare(const String *name, NameSpace *parent,
948 CompiledBasicType &DEF)
950 BasicType *bt = new BasicType(name);
954 parent->add_user(bt);
959 virtual void output(const char *root);
961 static BasicType *import(ImportContext &ctx);
962 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
965 static inline bool is_array(CompiledBasicType &bt)
967 return bt.array.bounds[0] || bt.array.bounds[1];
970 static inline bool is_array(CompiledBasicType *bt)
972 return is_array(*bt);
975 typedef Ref<Datum> DatumRef;
977 class Array : public RefCountable<Array>
979 NameSpace *lookup_ctx;
982 // lower is [0], upper is [1]
986 // Strings for error reporting on each constant. If the constant
987 // is symbolic, then this is the fully qualified symbol name.
988 // Otherwise, it is the numerical value converted to a string. In
989 // each case, the file/line shall correspond to where the array
990 // bound was specified.
995 // ca is not valid until after final_analysis() is called.
998 Array(NameSpace *LOOKUP_CTX);
999 void set_bound(Con &con, int bound);
1000 void final_analysis();
1002 void set_unbounded();
1005 typedef Ref<Array> ArrayRef;
1007 class Datum : public Symbol, public Def {
1008 StrListRef type_name;
1010 StringRef type_fq_name;
1012 StrListRef const_val_name;
1013 SymbolRef const_val_sym;
1016 bool basic; // Datum is of a BasicType
1018 bool const_init; // Datum's constant has been initialized; this is
1019 // true after a successful verify_const().
1020 CompiledBasicType *cbt;
1024 int chain_traversed;
1026 // Recursively retrieve the actual value of a const datum
1027 // initialized with another named const datum. Returns
1028 // the "end" of an infinite loop, if one is found. Once
1029 // the full infinite loop has been printed, UserError is
1032 Datum *resolve_constant_chain();
1034 void init_const_early(Con *con);
1036 void use_anon_type(const CompiledBasicType &CBT)
1038 def.basictype = CBT;
1039 cbt = &def.basictype;
1042 def.type.length = 0;
1045 void process_type();
1047 void set_array(Array *ARRAY)
1057 int con_type; // Used to store the TOK_[IUF]CON of the Con struct
1058 // for type checking once the type is known.
1060 Datum(const String *name) :
1062 Def((const char *)&def, sizeof(def), CompiledDefHeader::Datum)
1066 chain_traversed = 0;
1067 memset(&def, 0, sizeof(def));
1070 void init(StrList *type, Array *ARRAY, Con *con = NULL);
1071 void init(CompiledBasicType &cbt, Array *ARRAY, Con *con = NULL);
1073 static Datum *declare(const String *name, NameSpace *parent,
1074 StrList *type, Array *ARRAY,
1079 Datum *d = new Datum(name);
1080 d->init(type, ARRAY, con);
1082 parent->add_user(d);
1086 static Datum *declare(const String *name, NameSpace *parent,
1087 CompiledBasicType &type,
1088 Array *ARRAY, Con *con = NULL)
1092 Datum *d = new Datum(name);
1093 d->init(type, ARRAY, con);
1095 parent->add_user(d);
1101 def.flags.field.Inline = 1;
1106 return def.flags.field.Inline;
1109 void set_immutable()
1111 def.flags.field.Immutable = 1;
1116 return def.flags.field.Immutable;
1119 // Returns true if the constant was acceptable, false otherwise (an
1120 // error is also output to the user in this case).
1122 bool verify_const();
1124 virtual void lookup_chain()
1129 const_val_sym = lookup_sym(toplevel, const_val_name, get_ns());
1133 type_sym = lookup_type(type_name, get_ns(), true);
1135 type_sym = lookup_sym(toplevel, type_name, get_ns());
1141 virtual void lookup_misc()
1143 if (def.flags.field.Const) {
1145 assert(def.flags.field.Const);
1148 Datum *d = resolve_constant_chain();
1158 virtual void final_analysis();
1160 virtual void output(const char *root);
1161 bool output_extra(FILE *f);
1163 static Datum *import(ImportContext &ctx);
1164 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1166 uint64_t get_ucon(const String *err_str)
1168 if (!def.flags.field.Const) {
1169 yyerrorfl(err_str->file, err_str->line,
1170 "\"%s\" is not a const Datum.\n",
1171 get_fq_name()->flatten()->c_str());
1181 return ::is_array(def.basictype);
1185 template<typename T>
1186 bool output_list(T *sym, FILE *f);
1188 class BitField : public NameSpace, public Type, public Def {
1189 list<DatumRef> entries;
1191 void add_elem(Datum *d);
1194 CompiledBitField def;
1197 BitField(const String *name) :
1199 Def((const char *)&def, sizeof(def), CompiledDefHeader::BitField)
1201 memset(&def, 0, sizeof(def));
1204 void init(int bits, NameSpace *parent)
1206 if (bits < 0 || bits > 64) {
1207 yyerrorf("\"%s\" has invalid bitfield size %d",
1208 name->c_str(), bits);
1210 bits = bits < 0 ? 0 : 64;
1216 static BitField *declare(const String *name, NameSpace *parent,
1221 BitField *bf = new BitField(name);
1222 bf->init(bits, parent);
1224 parent->add_user(bf);
1228 // Only integral Datums, Enums, and BitFields can be added.
1230 void add(Symbol *sym, bool from_import);
1232 virtual const char *description()
1237 virtual void lookup_misc()
1239 NameSpace::lookup_misc();
1242 virtual void final_analysis()
1244 // FIXME: check total size of elements
1246 NameSpace::final_analysis();
1249 int get_default_bf_size()
1254 virtual void output(const char *root);
1255 bool output_extra(FILE *f);
1257 static BitField *import(ImportContext &ctx);
1258 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1260 typedef list<DatumRef>::const_iterator entries_iterator;
1261 typedef list<DatumRef>::const_reverse_iterator entries_reverse_iterator;
1263 entries_iterator entries_begin()
1265 return entries.begin();
1268 entries_iterator entries_end()
1270 return entries.end();
1273 entries_reverse_iterator entries_rbegin()
1275 return entries.rbegin();
1278 entries_reverse_iterator entries_rend()
1280 return entries.rend();
1285 typedef Ref<Struct> StructRef;
1286 extern Struct *System_VStruct;
1288 // FIXME: typedefed superstructs
1289 class Struct : public NameSpace, public Type, public Def {
1290 list<DatumRef> entries;
1293 StrListRef supername;
1294 bool attrs_resolved;
1296 void add_elem(Datum *d);
1298 void resolve_attrs()
1303 if (super && !super->attrs_resolved)
1304 super->resolve_attrs();
1306 if (super && super->def.flags.field.Virtual)
1307 def.flags.field.Virtual = 1;
1309 attrs_resolved = true;
1315 // This is not maintained by the generic code, but can be
1316 // used by language bindings to cache the result of the
1321 Struct(const String *name) :
1323 Def((const char *)&def, sizeof(def), CompiledDefHeader::Struct)
1325 memset(&def, 0, sizeof(def));
1329 void init(StrList *SUPERNAME)
1331 supername = SUPERNAME;
1334 static Struct *declare(const String *name, NameSpace *parent,
1339 Struct *st = new Struct(name);
1340 st->init(SUPERNAME);
1342 parent->add_user(st);
1348 def.flags.field.Virtual = 1;
1353 def.flags.field.Inline = 1;
1358 return def.flags.field.Virtual;
1363 return def.flags.field.Inline;
1366 // Only Datums and Types can be added.
1368 void add(Symbol *sym, bool from_import);
1370 virtual const char *description()
1377 assert(current_pass >= 4);
1381 virtual void lookup_chain()
1384 supersym = lookup_sym(toplevel, supername, get_ns());
1388 NameSpace::lookup_chain();
1394 if (supersym && !super) {
1395 super = dynamic_cast<Struct *>(supersym->get_concrete_sym());
1398 const String *str = supername->back();
1399 yyerrorfl(str->file, str->line,
1400 "\"%s\" is not a struct.",
1401 supersym->get_fq_name()->flatten()->c_str());
1404 def.flags.field.Super = 1;
1405 super->lookup_super();
1407 if (super->is_virtual())
1411 if (is_virtual() && !supersym && !super) {
1412 assert(System_VStruct);
1413 if (this != System_VStruct) {
1414 def.flags.field.Super = 1;
1415 super = System_VStruct;
1421 virtual void lookup_misc()
1425 if (is_virtual() && def.guid[0] == 0 && def.guid[1] == 0)
1426 yyerrorfl(name->file, name->line,
1427 "Virtual struct \"%s\" is missing a GUID.",
1428 get_fq_name()->flatten()->c_str());
1430 NameSpace::lookup_misc();
1433 virtual void final_analysis()
1435 // FIXME: check for infinite loops in struct inheritance
1438 NameSpace::final_analysis();
1441 virtual void output(const char *root);
1442 bool output_extra(FILE *f);
1444 static Struct *import(ImportContext &ctx);
1445 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1447 typedef list<DatumRef>::const_iterator entries_iterator;
1449 entries_iterator entries_begin()
1451 return entries.begin();
1454 entries_iterator entries_end()
1456 return entries.end();
1459 void set_guid(uint64_t guid[2])
1461 if (def.guid[0] || def.guid[1])
1462 yyerrorf("\"%s\" already has a GUID.",
1463 get_fq_name()->flatten()->c_str());
1465 def.guid[0] = guid[0];
1466 def.guid[1] = guid[1];
1470 class Param : public Symbol, public Def {
1471 StrListRef type_name;
1472 StringRef type_fq_name;
1474 bool basic; // Datum is of a BasicType
1479 void use_named_type(BasicType *bt)
1481 assert(!bt || bt->def.flags.field.TypeDef);
1485 type_fq_name = type->get_fq_name()->flatten();
1486 def.type.length = type_fq_name->length();
1489 void use_anon_type(const CompiledBasicType &cbt)
1491 def.basictype = cbt;
1496 void set_array(Array *ARRAY)
1506 Param(const String *name) :
1508 Def((const char *)&def, sizeof(def), CompiledDefHeader::Param)
1510 memset(&def, 0, sizeof(def));
1513 void init(StrList *TYPE, CompiledParam::Flags flags, Array *ARRAY)
1520 static Param *declare(const String *name, NameSpace *parent,
1521 StrList *TYPE, CompiledParam::Flags flags,
1524 virtual void lookup_misc()
1526 type = lookup_type(type_name, get_ns());
1529 virtual void final_analysis()
1531 BasicType *bt = dynamic_cast<BasicType *>(type->get_concrete_sym());
1533 if (bt && !bt->def.flags.field.TypeDef) {
1534 use_anon_type(bt->def);
1538 Struct *str = dynamic_cast<Struct *>(*type);
1539 if (str && str->is_inline())
1542 if (!str && is_inline()) {
1543 yyerrorfl(name->file, name->line,
1544 "\"%s\" is static but not a struct.",
1545 get_fq_name()->flatten()->c_str());
1550 array->final_analysis();
1551 def.basictype.array = array->ca;
1553 def.basictype.array.bounds[0] = 0;
1554 def.basictype.array.bounds[1] = 0;
1560 def.flags.field.Inline = 1;
1565 return def.flags.field.Inline;
1570 return def.flags.field.In;
1575 return def.flags.field.Out;
1578 virtual void output(const char *root);
1579 bool output_extra(FILE *f);
1581 static Param *import(ImportContext &ctx);
1582 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1586 return ::is_array(def.basictype);
1590 typedef Ref<Param> ParamRef;
1592 class Method : public NameSpace, public Def {
1593 list<ParamRef> entries;
1595 void add_elem(Param *p);
1600 Method(const String *name) :
1602 Def((const char *)&def, sizeof(def), CompiledDefHeader::Method)
1604 memset(&def, 0, sizeof(def));
1609 def.flags.field.Async = 1;
1614 return def.flags.field.Async;
1617 static Method *declare(const String *name, NameSpace *parent);
1619 void add(Symbol *sym, bool from_import);
1621 virtual const char *description()
1626 virtual void output(const char *root);
1627 bool output_extra(FILE *f);
1629 static Method *import(ImportContext &ctx);
1630 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1632 typedef list<ParamRef>::const_iterator entries_iterator;
1634 entries_iterator entries_begin()
1636 return entries.begin();
1639 entries_iterator entries_end()
1641 return entries.end();
1645 typedef Ref<Method> MethodRef;
1648 typedef Ref<Interface> InterfaceRef;
1650 extern Interface *System_Object;
1652 // FIXME: typedefed superinterfaces
1653 class Interface : public NameSpace, public Type, public Def {
1654 list<MethodRef> methods;
1655 list<InterfaceRef> supers;
1656 IDListRef supernames;
1658 void add_elem(Method *m);
1660 // This is like Symbol::traversed[], but used internally by the
1661 // for_each_super function to ensure that common ancestors are only
1664 int traversed_all_supers;
1665 static int all_supers_traversal;
1668 typedef void (*callback)(Interface *i, void *arg);
1671 template<callback cb>
1672 void for_each_super_internal(void *arg)
1674 for (supers_iterator i = supers_begin(); i != supers_end(); ++i) {
1675 Interface *iface = *i;
1677 if (iface->traversed_all_supers < all_supers_traversal) {
1678 iface->traversed_all_supers = all_supers_traversal;
1680 iface->for_each_super_internal<cb>(arg);
1685 // All interfaces in the map and vector are supers of this
1686 // interface, and thus retained that way, so plain pointers
1687 // can be used here.
1689 typedef map<Interface *, int> chain_map_type;
1690 typedef chain_map_type::value_type chain_valtype;
1691 typedef chain_map_type::const_iterator chain_iter;
1693 chain_map_type super_to_chain_map;
1697 vector<Interface *> chain_heads;
1700 int super_to_chain(Interface *iface, bool must_find_it = true)
1702 chain_iter ret = super_to_chain_map.find(iface);
1704 if (ret == super_to_chain_map.end()) {
1705 assert(!must_find_it);
1709 return (*ret).second;
1712 Interface *get_chain_head(int chain)
1714 return chain_heads[chain];
1717 int get_num_chains()
1723 void set_chain(Interface *iface, int chain)
1725 pair<chain_iter, bool> ret =
1726 super_to_chain_map.insert(chain_valtype(iface, chain));
1730 // This is the inner depth-first search, which terminates
1731 // at each level upon finding that the node it had previously
1732 // recursed into found an unchained node.
1734 void pick_chain(Interface *iface, int chain)
1736 assert(super_to_chain(iface, false) == -1);
1737 chain_heads.push_back(iface);
1740 set_chain(iface, chain);
1742 if (iface->supers.empty())
1745 iface = iface->supers.front();
1746 } while (super_to_chain(iface, false) == -1);
1749 // This is the outer breadth-first-search, making sure every
1750 // super is assigned to a chain.
1754 list<Interface *> bfs;
1757 bfs.push_back(this);
1759 while (!bfs.empty()) {
1760 Interface *iface = bfs.front();
1763 for (supers_iterator i = iface->supers_begin();
1764 i != iface->supers_end(); ++i)
1767 if (super_to_chain(iface, false) == -1)
1768 pick_chain(iface, num_chains++);
1773 // Do not call after lookup_misc
1774 void add_super(Interface *i)
1776 assert(current_pass != 1);
1778 supers.push_back(i);
1782 CompiledInterface def;
1784 Interface(const String *name) :
1786 Def((const char *)&def, sizeof(def), CompiledDefHeader::Interface)
1788 memset(&def, 0, sizeof(def));
1789 traversed_all_supers = 0;
1792 void init(IDList *SUPERNAMES)
1794 supernames = SUPERNAMES;
1797 static Interface *declare(const String *name, NameSpace *parent,
1802 Interface *i = new Interface(name);
1803 i->init(SUPERNAMES);
1805 parent->add_user(i);
1809 // Only Methods, Types, and const BasicType Datums can be added.
1811 void add(Symbol *sym, bool from_import);
1813 virtual const char *description()
1819 void add_object_super()
1821 assert(System_Object);
1822 if (this != System_Object && supers.empty())
1823 add_super(System_Object);
1827 virtual void lookup_misc()
1829 if (def.guid[0] == 0 && def.guid[1] == 0)
1830 yyerrorfl(name->file, name->line,
1831 "Interface \"%s\" is missing a GUID.",
1832 get_fq_name()->flatten()->c_str());
1835 for (IDList::iterator i = supernames->begin();
1836 i != supernames->end(); ++i)
1838 Symbol *sym = lookup_sym(toplevel, *i, get_ns());
1840 dynamic_cast<Interface *>(sym->get_concrete_sym());
1843 const String *str = (*i)->back();
1844 yyerrorfl(str->file, str->line,
1845 "\"%s\" is not an interface.\n",
1846 sym->get_fq_name()->flatten()->c_str());
1856 NameSpace::lookup_misc();
1859 virtual void final_analysis()
1861 // FIXME: check for infinite loops in inheritance
1864 NameSpace::final_analysis();
1867 virtual void output(const char *root);
1868 bool output_extra(FILE *f);
1870 static Interface *import(ImportContext &ctx);
1871 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1873 typedef list<MethodRef>::const_iterator methods_iterator;
1874 typedef list<InterfaceRef>::const_iterator supers_iterator;
1876 supers_iterator supers_begin()
1878 assert(current_pass != 1);
1879 return supers.begin();
1882 supers_iterator supers_end()
1884 return supers.end();
1889 assert(current_pass != 1);
1890 return supers.empty();
1893 methods_iterator methods_begin()
1895 return methods.begin();
1898 methods_iterator methods_end()
1900 return methods.end();
1903 template<callback cb>
1904 void for_each_super(void *arg)
1906 assert(current_pass >= 4);
1908 all_supers_traversal++;
1909 for_each_super_internal<cb>(arg);
1912 void finalize_class_iface()
1918 void set_guid(uint64_t guid[2])
1920 if (def.guid[0] || def.guid[1])
1921 yyerrorf("\"%s\" already has a GUID.",
1922 get_fq_name()->flatten()->c_str());
1924 def.guid[0] = guid[0];
1925 def.guid[1] = guid[1];
1929 class IFaceList : public list<InterfaceRef>,
1930 public RefCountable<IFaceList> {};
1932 class Enum : public NameSpace, public Type, public Def {
1933 list<DatumRef> entries;
1935 void add_elem(Datum *d);
1938 unsigned int next_val;
1941 Enum(const String *name) :
1943 Def((const char *)&def, sizeof(def), CompiledDefHeader::Enum),
1946 memset(&def, 0, sizeof(def));
1951 if (bits < 0 || bits > 64) {
1952 yyerrorf("\"%s\" has invalid enum size %d",
1953 name->c_str(), bits);
1955 bits = bits < 0 ? 0 : 64;
1961 static Enum *declare(const String *name, NameSpace *parent,
1966 Enum *e = new Enum(name);
1969 parent->add_user(e);
1973 // Only const unsigned integer BasicType Datums are allowed.
1975 void add(Symbol *sym, bool from_import);
1977 virtual const char *description()
1979 return "enumeration";
1982 int get_default_bf_size()
1987 virtual void output(const char *root);
1988 bool output_extra(FILE *f);
1990 static Enum *import(ImportContext &ctx);
1991 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1993 typedef list<DatumRef>::const_iterator entries_iterator;
1995 entries_iterator entries_begin()
1997 return entries.begin();
2000 entries_iterator entries_end()
2002 return entries.end();
2006 class Alias : public Symbol, public Def {
2012 Cycle(Alias *END) : end(END)
2021 StringRef sym_fq_name;
2022 StrListRef sym_name;
2024 Alias(const String *name) :
2026 Def((const char *)&def, sizeof(def), CompiledDefHeader::Alias)
2028 memset(&def, 0, sizeof(def));
2029 lookup_begun = false;
2032 void init(StrList *symname, bool is_private)
2038 static Alias *declare(const String *name, NameSpace *parent,
2039 StrList *symname, bool is_private = false)
2042 Alias *a = new Alias(name);
2043 a->init(symname, is_private);
2045 parent->add_user(a);
2049 void resolve_chain()
2053 yyerrorfl(name->file, name->line,
2054 "Alias loop defining \"%s\"",
2055 get_fq_name()->flatten()->c_str());
2060 lookup_begun = true;
2063 real_sym = lookup_sym(toplevel, sym_name, get_ns(), this);
2067 yyerrorfl(name->file, name->line, " ...referenced by \"%s\"",
2068 get_fq_name()->flatten()->c_str());
2078 virtual Symbol *get_concrete_sym(bool follow_typedefs = true)
2081 return real_sym->get_concrete_sym(follow_typedefs);
2084 virtual void lookup_chain()
2086 get_concrete_sym(true);
2089 virtual void lookup_misc()
2091 real_sym = real_sym->get_concrete_sym(false);
2092 sym_fq_name = real_sym->get_fq_name()->flatten();
2094 def.length = sym_fq_name->length();
2097 virtual void output(const char *root);
2098 bool output_extra(FILE *f);
2100 static Alias *import(ImportContext &ctx);
2101 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
2104 class TypeDef : public Alias {
2106 TypeDef(const String *name) : Alias(name)
2108 memset(&def, 0, sizeof(def));
2109 hdr.type = CompiledDefHeader::TypeDef;
2112 static TypeDef *declare(const String *name, NameSpace *parent,
2116 TypeDef *td = new TypeDef(name);
2117 td->init(symname, false);
2119 parent->add_user(td);
2123 virtual Symbol *get_concrete_sym(bool follow_typedefs = true)
2125 if (follow_typedefs) {
2127 return real_sym->get_concrete_sym(follow_typedefs);
2133 static TypeDef *import(ImportContext &ctx);
2134 virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
2137 NameSpace *add_nspace(StrList *name, bool push);
2140 // Declare an instance of "type" in "ns" for each element of "ids".
2141 // This function will report any errors, but not throw UserError.
2143 void declare_data(NameSpace *ns, StrList *ids, StrList *type,
2144 Array *array, StrList *attr);
2145 void declare_aliases(NameSpace *ns, StrList *ids, StrList *type,
2147 void declare_basictypes(NameSpace *ns, StrList *ids,
2148 BasicType *type, bool is_typedef);
2150 // You'd think they'd have standard functions to do this these days.
2151 // All I could find that come close are the network-byte-order
2152 // functions, and they're no-ops on big-endian machines.
2154 static inline uint32_t swap32(uint32_t in, bool swap)
2157 return ((in & 0x000000ff) << 24) |
2158 ((in & 0x0000ff00) << 8) |
2159 ((in & 0x00ff0000) >> 8) |
2160 ((in & 0xff000000) >> 24);
2165 static inline uint64_t swap64(uint64_t in, bool swap)
2168 return (((uint64_t)swap32((uint32_t)in, true)) << 32) |
2169 swap32((uint32_t)(in >> 32), true);
2187 File *operator =(FILE *F)
2205 // Verify that a prospective new import (or output namespace)
2206 // does not overlap an existing import. Returns the conflicting
2207 // import, or NULL if none found.
2209 NameSpace *check_for_imports(NameSpace *ns);