]> git.buserror.net Git - polintos/scott/priv.git/blob - idlcomp/idlc.h
Switch to a simple X11-style license.
[polintos/scott/priv.git] / idlcomp / idlc.h
1 // idlc.h -- Definitions used throughout idlc. 
2 // A lot of this should probably be factored out into more specific headers.
3 //
4 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
5 // 
6 // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 // this software and associated documentation files (the "Software"), to deal with
8 // the Software without restriction, including without limitation the rights to
9 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10 // of the Software, and to permit persons to whom the Software is furnished to do
11 // so, subject to the following condition:
12 // 
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 // 
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
22 // SOFTWARE.
23
24 #ifndef IDLC_H
25 #define IDLC_H
26
27 // inttypes.h on OSX assumes it can use restrict, but C++ doesn't have it.
28 // Hopefully C++ will catch up to C soon...
29
30 #define restrict
31
32 #include <stdint.h>
33 #include <inttypes.h>
34 #include <stdio.h>
35 #include <ctype.h>
36 #include <string>
37 #include <stack>
38 #include <list>
39 #include <map>
40 #include <vector>
41
42 #include "compileddef.h"
43
44 using std::list;
45 using std::stack;
46 using std::string;
47 using std::pair;
48 using std::map;
49 using std::vector;
50
51 int yylex();
52 int idl_lex();
53 #define cdl_lex idl_lex
54 void idl_error(char *s);
55
56 #define cdl_error idl_error
57
58 void setup_idlparse();
59 void setup_cdlparse();
60
61 #ifdef __GNUC__
62 void yyerrorf(const char *s, ...) __attribute__((format(printf, 1, 2)));
63 void yyerrorfl(const char *file, int line, const char *s, ...)
64 __attribute__((format(printf, 3, 4)));
65 #else
66 void yyerrorf(const char *s, ...);
67 void yyerrorfl(const char *file, int line, const char *s, ...);
68 #endif
69
70 int idl_parse();
71 int cdl_parse();
72 int finish_lex();
73
74 extern int idl_debug, cdl_debug, curline, impl, num_err;
75 extern int current_pass;
76 extern FILE *yyin;
77 extern unsigned int enum_pos;
78 extern const char *cur_input_file;
79 extern int compiling_idl, compiling_cdl;
80 extern bool makedep;
81
82 struct InternalError
83 {
84         // Location in the IDLC source of the BUG()
85         const char *file;
86         int line;
87         
88         InternalError(const char *file, int line) :
89         file(file), line(line)
90         {
91         }
92 };
93
94 #define BUG() do { \
95         throw InternalError(__FILE__, __LINE__); \
96 } while (0)
97
98 #undef assert
99
100 #define assert(x) do { \
101         if (!(x)) BUG(); \
102 } while (0)
103
104 class Releasable {
105 public:
106         mutable int count;
107         
108         virtual ~Releasable()
109         {
110         }
111         
112         Releasable(int COUNT) : count(COUNT)
113         {
114         }
115
116         void release() const
117         {
118                 if (count <= 0) {
119                         fprintf(stderr, "Reference count is %d in release\n", count);
120                         BUG();
121                 }   
122                 
123                 if (!--count)
124                         delete this;
125         }
126 };
127
128 class AutoReleasePool {
129         list<const Releasable *> pool;
130
131 public:
132         void add(const Releasable *obj)
133         {
134                 pool.push_back(obj);
135         }
136         
137         void clean()
138         {
139                 for (list<const Releasable *>::iterator i = pool.begin();
140                      i != pool.end(); ++i)
141                 {
142                         const Releasable *obj = *i;
143                         obj->release();
144                 }
145                 
146                 pool.clear();
147         }
148 };
149
150 extern AutoReleasePool autorelease_pool;
151
152 template <typename T>
153 class RefCountable : public Releasable {
154 private:
155         // RefCountable objects should never be assigned to,
156         // as there could be references to the object remaining.
157         // The private assignment operator prevents this, unless
158         // a subclass defines its own assigment operator (don't
159         // do that).
160         void operator =(const RefCountable &rc)
161         {
162                 BUG();
163         }
164
165         RefCountable(const RefCountable &rc) : Releasable(1)
166         {
167                 BUG();
168         }
169         
170 public:
171         RefCountable() : Releasable(1)
172         {
173                 // Normally, this wouldn't be automatic, but this is what most
174                 // things in IDLC are going to want, and it elimanates problems
175                 // with needing to cast the return type of autorelease().
176                 //
177                 // The automatic autorelease() means that all refcountable objects
178                 // must be allocated with "new", not on the stack, as global
179                 // data, or as a class member.
180                 
181                 autorelease();
182         }
183         
184         virtual ~RefCountable()
185         {
186         }
187
188         const T *retain() const
189         {
190                 if (count <= 0) {
191                         fprintf(stderr, "Reference count is %d in retain\n", count);
192                         BUG();
193                 }   
194                 
195                 count++;
196                 return static_cast<const T *>(this);
197         }
198
199         T *retain()
200         {
201                 if (count <= 0) {
202                         fprintf(stderr, "Reference count is %d in retain\n", count);
203                         BUG();
204                 }   
205                 
206                 count++;
207                 return static_cast<T *>(this);
208         }
209         
210         const T *autorelease() const
211         {
212                 autorelease_pool.add(static_cast<Releasable *>(this));
213                 return static_cast<T *>(this);
214         }
215
216         T *autorelease()
217         {
218                 autorelease_pool.add(static_cast<Releasable *>(this));
219                 return static_cast<T *>(this);
220         }
221         
222         // This is only here because C++ obnoxiously requires it to
223         // be just because it's "called" from code excluded with an
224         // if (0) in a template.  No code is ever generated that calls
225         // it, but it still must exist.
226         
227         bool operator < (const RefCountable &rc)
228         {
229                 BUG();
230         }
231 };
232
233 // T must be RefCountable
234 template<typename T, bool compare_ptrs = true>
235 class Ref {
236         // STL containers like to use const on the items they
237         // contain; the mutable allows such containers to hold
238         // pointers to non-const data.  For truly const Refs,
239         // make T const, as in StringRef.  Unfortunately,
240         // it cannot be done in a more fine-grained manner,
241         // AFAICT.
242
243 public: 
244         mutable T *data;
245         
246 public:
247         Ref()
248         {
249                 data = NULL;
250         }
251
252         Ref(T *data) : data(data)
253         {
254                 if (data)
255                         data->retain();
256         }
257         
258         Ref(Ref &le) : data(le.data)
259         {
260                 if (data)
261                         data->retain();
262         }
263
264         Ref &operator =(const Ref &le)
265         {
266                 // The retain must come first, in case both Refs are the same
267                 if (le.data)
268                         le.data->retain();
269                 if (data)
270                         data->release();
271
272                 data = le.data;
273                 
274                 return *this;
275         }
276
277         Ref &operator =(T *new_data)
278         {
279                 // The retain must come first, in case both Refs are the same
280                 if (new_data)
281                         new_data->retain();
282                 if (data)
283                         data->release();
284
285                 data = new_data;
286                 
287                 return *this;
288         }
289         
290         ~Ref()
291         {
292                 if (data)
293                         data->release();
294         }
295         
296         operator T *() const
297         {
298                 return data;
299         }
300         
301         operator T &() const
302         {
303                 return *data;
304         }
305         
306         T *operator *() const
307         {
308                 return data;
309         }
310
311         T *operator ->() const
312         {
313                 return data;
314         }
315         
316         bool operator == (const Ref &le) const
317         {
318                 if (compare_ptrs)
319                         return data == le.data;
320                 else
321                         return *data == *le.data;
322         }
323
324         bool operator != (const Ref &le) const
325         {
326                 if (compare_ptrs)
327                         return data != le.data;
328                 else
329                         return *data != *le.data;
330         }
331
332         bool operator < (const Ref &le) const
333         {
334                 if (compare_ptrs)
335                         return reinterpret_cast<intptr_t>(data) < 
336                                reinterpret_cast<intptr_t>(le.data);
337                 else
338                         return *data < *le.data;
339         }
340 };
341
342 class String : public string, public RefCountable<String> {
343 public:
344         // Origin of the string, if from the IDL file.
345         // Otherwise, fill both values with zero.
346
347         const char *file;
348         int line;
349         int token;
350
351         String(const char *s = "") : string(s)
352         {
353                 file = "";
354                 line = 0;
355                 token = 0;
356         }
357
358         String(const String &s) : string(s)
359         {
360                 file = s.file;
361                 line = s.line;
362                 token = s.token;
363         }
364
365         String(const char *s, const char *file, int line, int token) :
366                string(s), file(file), line(line), token(token)
367         {}
368 };
369
370 extern String **yylval_string;
371 typedef Ref<const String, false> StringRef;
372
373 /* If a StrList is used for a namespace-qualified identifier, and
374    said identifier begins with ".." (i.e. starts from the root
375    namespace), the leading ".." is represented by a zero-length
376    String. 
377    
378    Note that list doesn't have a virtual destructor, so all deletions
379    should happen through either RefCountable or the wrapper List
380    class. */
381
382 class StrList : public list<StringRef>, public RefCountable<StrList> {
383 public:
384         StrList()
385         {
386         }
387         
388         // Parse a flat String into a StrList, using the specified delimeter.
389         StrList(const String *input, char delimiter = '.');
390
391         // Turn a StrList into a flat String, using the specified delimiter.
392         String *flatten(const char *delimiter = ".");
393 };
394
395 typedef Ref<StrList> StrListRef;
396
397 // ConList is like StrList, but with constant initializers
398
399 class Datum;
400
401 struct Con {
402         union {
403                 int64_t icon;
404                 uint64_t ucon;
405                 StrList *dcon;
406                 
407                 // FIXME: handle platforms with weird floating point endianness
408                 double fcon;
409                 
410                 char data[8];
411         } con;
412         
413         // TOK_ICON, TOK_UCON, TOK_FCON, TOK_BOOL, TOK_DCON, 
414         // TOK_INVALID, or TOK_NONE
415         // Constants are stored as signed (ICON) unless too
416         // large to fit in a signed 64-bit integer.  Additional size and
417         // signedness checks are mode when down casting to a smaller size
418         // to fit into a particular datum; such constants will have a
419         // value of zero.
420         //
421         // TOK_NONE is valid for maybeconst and size.  TOK_INVALID
422         // indicates a previously detected error; don't emit any further
423         // errors due to this constant.
424         //
425         // TOK_DCON is used for symbolic constants, whose value may
426         // not yet be known.
427         
428         int type;
429 };
430
431 extern Con *yylval_con;
432
433 struct ConInit {
434         StringRef str;
435         Con con;
436
437         ConInit(const String *str, Con &con) : str(str), con(con)
438         {
439         }
440
441         ConInit(const ConInit &coninit)
442         {
443                 *this = coninit;
444         }
445 };
446
447 class ConList : public list<ConInit>, public RefCountable<ConList> {};
448 typedef Ref<ConList> ConListRef;
449
450 // Like StrList, but is a list of possibly namespace-qualified identifiers.
451 class IDList : public list<StrListRef>, public RefCountable<IDList> {};
452 typedef Ref<IDList> IDListRef;
453
454
455 class NameSpace;
456 class LangCallback;
457
458 // This is incremented when a chain of symbols is traversed to reset
459 // detection of already-visited symbols.  It is assumed that this
460 // will not have to happen billions of times.
461
462 extern int traversal;
463
464 class Symbol : public RefCountable<Symbol> {
465         NameSpace *ns;
466         
467 public:
468         StringRef name;
469
470         // Symbol was loaded externally
471         bool external;
472         
473         // If set, the symbol is private, and will not be available
474         // for lookups except those made directly in the context of
475         // the containing namespace.  Private symbols do not get
476         // outputted.  They are used to implement imports of specific
477         // symbols (as aliases), rather than entire namespaces.
478         
479         bool priv;
480         
481         // This is set to ::traversal when this symbol is visited along a chain.
482         // If a target needs more than 8 simultaneous chains, increase the size
483         // of the array.  These traversals are reserved for language binding use.
484         
485         int traversed[8];
486
487         Symbol()
488         {
489                 ns = NULL;
490                 external = false;
491                 priv = false;
492                 
493                 memset(traversed, 0, sizeof(traversed));
494         }
495         
496         Symbol(const String *_name) : name(_name)
497         {
498                 if (_name)
499                         name->retain();
500
501                 ns = NULL;
502                 external = false;
503                 priv = false;
504
505                 memset(traversed, 0, sizeof(traversed));
506         }
507
508         virtual ~Symbol();
509
510         NameSpace *get_ns() const
511         {
512                 return ns;
513         }
514
515         const String *get_name() const
516         {
517                 return name;
518         }
519         
520         // If append is non-NULL, it is appended to non-user namespaces,
521         // to facilitate a language binding that cannot place nested types
522         // in the same language construct as the actual interface.  The
523         // recommended suffix is "_ns", which is a reserved ending in the
524         // IDL.  No suffix is placed on the final component of the name,
525         // even if it is a non-user namespace.  The not_last field is used
526         // to detect whether it is the final component; it is only used
527         // internally, and should always be false when called externally.
528         //
529         // This function does *NOT* add a null first element to indicate
530         // that the name is fully qualified.  If you need that, you have
531         // to add it yourself (call 'push_front(new String(""))' on the
532         // result).
533         
534         StrList *get_fq_name(const char *append = NULL,
535                              bool not_last = false) const;
536         
537         virtual void lookup_imports()
538         {
539         }
540         
541         virtual void lookup_chain()
542         {
543         }
544
545         virtual void lookup_misc()
546         {
547         }
548         
549         virtual void final_analysis()
550         {
551         }
552
553         // These two methods must be implemented by all IDL symbols, but are
554         // not needed in CDL symbols (and therefore are not pure virtual).
555
556         virtual void output(const char *root)
557         {
558         }
559
560         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL)
561         {
562         }
563         
564         // Find and return the topmost symbol other than a user namespace
565         // containing this symbol.  If this symbol's parent is a user
566         // namespace, it returns itself.  May not be called on the
567         // toplevel namespace.
568         
569         Symbol *find_toplevel_type();
570
571         // Get the true type of the symbol, regardless of whether it is an
572         // alias.
573         
574         virtual Symbol *get_concrete_sym(bool follow_typedefs = true)
575         {
576                 return this;
577         }
578         
579         friend class NameSpace;
580 };
581
582 typedef Ref<Symbol> SymbolRef;
583
584 class SymList : public list<SymbolRef>, public RefCountable<SymList> {};
585 typedef Ref<SymList> SymListRef;
586
587 struct SymbolNotFound {
588 };
589
590 struct DuplicateSymbol {
591 };
592
593 struct InvalidArgument {
594 };
595
596 struct UserError {
597 };
598
599 typedef Ref<NameSpace> NameSpaceRef;
600
601 class NameSpace : public virtual Symbol {
602 protected:
603         // Filesystem path to the external symbol storage, or NULL
604         // if not an import namespace.
605         //
606         // Import namespaces are read-only namespaces which are created
607         // for the importation of externally-declared symbols.  One is
608         // initially created for each "mount point" specified by the user;
609         // whenever such a namespace is searched, it checks the external
610         // storage, and if the lookup succeeds, the symbol is loaded and
611         // added to the namespace.  Failed lookups could be cached with a
612         // special BadSymbol or some such, as the imported namespace is
613         // assumed to be constant, but I don't think such an optimization
614         // is worthwhile, at least at this point.
615         
616         StringRef path;
617
618         // Load a symbol from external storage, constructing the relevant type
619         // of object, and adding it to this namespace.  Only called for
620         // import namespaces.
621
622         Symbol *load(const String *symname);
623
624         typedef map<StringRef, SymbolRef> tbl_type;
625         tbl_type tbl;
626         
627         list<StrListRef> import_strs;
628         list<NameSpaceRef> imports;
629
630 public:
631         // This is set in the destructor, so the contents of the namespace
632         // don't try to remove themselves from the namespace when destructed
633         // due to the destruction of map.
634         int dying;
635         
636         // This is a counter for generating unique names for anonymous
637         // members of the namespace.
638         int anon;
639         
640         NameSpace() : dying(0), anon(0)
641         {
642         }
643         
644         virtual ~NameSpace()
645         {
646                 dying = 1;
647         }
648         
649         // Return a description of the type of namespace, for
650         // error messages.
651         virtual const char *description()
652         {
653                 return "namespace";
654         }
655
656         virtual void output(const char *root);
657
658         typedef tbl_type::const_iterator const_iterator;
659         typedef tbl_type::value_type value_type;
660
661         // Derived classes can throw InvalidArgument if you give them
662         // a type of Symbol that they don't accept; see their comments
663         // for more details.  Unfortunately, this cannot be done
664         // with static type-checking, as there are places that know
665         // they've been given a namespace that can accept a particular
666         // type of symbol, but they don't know exactly what kind of
667         // namespace it is.  C++'s type system is not sufficient to
668         // express this (at least not while retaining any semblance
669         // of sanity).
670
671         // DuplicateSymbol is thrown if sym already exists in this namespace.
672         virtual void add(Symbol *sym, bool from_import)
673         {
674                 if (path && !from_import)
675                         throw InvalidArgument();
676                 
677                 if (path)
678                         sym->external = true;
679                 
680                 if (!sym->name.data)
681                         BUG();
682
683                 pair<const_iterator, bool> ret = tbl.insert(value_type(sym->name, sym));
684                 
685                 if (ret.second)
686                         sym->ns = this;
687                 else {
688                         throw DuplicateSymbol();
689                 }
690         }
691
692         // Add the symbol to this namespace, handling duplicate symbols by
693         // printing an error and throwing a UserError().  This should not be
694         // done in the symbol's constructor, as the parent may not accept
695         // the symbol until it is fully constructed (the RTTI information
696         // changes, and in general partially constructed objects shouldn't
697         // be exposed to the rest of the system).
698
699         void add_user(Symbol *sym);
700
701         // Like add_user, but used by the import code.  Duplicate
702         // symbols result in internal errors, and the add is done with
703         // from_import set to true.  InvalidArgument results in an error
704         // message and a reraise as UserError.
705         //
706         // All conditions checked by the parent namespace's add() method
707         // (such as constness of data) must be satisfied prior to calling
708         // add_import().  On the other hand, add_import() must be called
709         // before any recursive importation is done which could
710         // conceivably try to import the current symbol (thus causing
711         // infinite recursion).
712
713         void add_import(Symbol *sym, const char *filename);
714
715         // SymbolNotFound is thrown if sym is not in this namespace.
716         virtual void del(Symbol *sym)
717         {
718                 fprintf(stderr, "Removing symbol %s\n",
719                         sym->get_fq_name()->flatten()->c_str());
720         
721                 if (tbl.erase(sym->name) == 0)
722                         throw SymbolNotFound();
723                 
724                 sym->ns = NULL;
725         }
726
727 private:        
728         Symbol *lookup_noex_noimport(const String *symname)
729         {
730                 const_iterator ret = tbl.find(symname);
731                 
732                 if (ret != tbl.end())
733                         return (*ret).second;
734                 
735                 return NULL;
736         }
737
738 public:
739         Symbol *lookup_noex(const String *symname, bool priv_ok = false)
740         {
741                 Symbol *ret = NameSpace::lookup_noex_noimport(symname);
742
743                 if (path && !ret)
744                         ret = load(symname);
745                 
746                 if (ret && !priv_ok && ret->priv)
747                         return NULL;
748         
749                 return ret;
750         }
751
752         Symbol *lookup(const String *symname, bool priv_ok = false)
753         {
754                 Symbol *ret = lookup_noex(symname, priv_ok);
755                 
756                 if (!ret)
757                         throw SymbolNotFound();
758                 
759                 return ret;
760         }
761         
762         // Like lookup_noex, but also checks imported namespaces,
763         // and returns the namespace containing the match rather
764         // than the match itself.
765         
766         NameSpace *search(const String *name, Symbol *exclude);
767         
768         void add_search(StrList *ns)
769         {
770                 import_strs.push_back(ns);
771         }
772
773         // Return a string containing case information manglement.
774         // See input.cc for more information.
775
776         static const String *mangle(const String *name);
777
778         const String *get_path()
779         {
780                 return path;
781         }
782         
783         // Import all members of this namespace.  A no-op if not an import
784         // namespace.  
785         void import_all();
786         
787         // As import_all, but also recursively applies to any sub-namespaces.
788         void import_all_recursive();
789         
790         const_iterator begin()
791         {
792                 return tbl.begin();
793         }
794
795         const_iterator end()
796         {
797                 return tbl.end();
798         }
799
800         virtual void lookup_imports();
801
802         virtual void lookup_chain()
803         {
804                 for (const_iterator i = begin(); i != end(); ++i) {
805                         Symbol *sym = (*i).second;
806                         sym->lookup_chain();
807                 }
808         }
809
810         virtual void lookup_misc()
811         {
812                 for (const_iterator i = begin(); i != end(); ++i) {
813                         Symbol *sym = (*i).second;
814                         sym->lookup_misc();
815                 }
816         }
817
818         virtual void final_analysis()
819         {
820                 for (const_iterator i = begin(); i != end(); ++i) {
821                         Symbol *sym = (*i).second;
822                         sym->final_analysis();
823                 }
824         }
825 };
826
827
828 extern NameSpaceRef cur_nspace;
829 extern list<NameSpaceRef> nspace_stack;
830         
831 typedef std::vector<StringRef> StringVec;
832
833 string *stringvec_to_path(StringVec &stringvec, const char *prepend);
834
835 // lookup_sym and lookup_type throw UserError on user error
836 // The context namespace is required for the proper
837 // set of namespaces to be searched.
838
839 Symbol *lookup_sym(NameSpace *topns, StrList *name, NameSpace *ctx,
840                    Symbol *exclude = NULL);
841
842 class Def {
843         const char *self;   // Pointer to the type-specific struct
844         int self_len;       // Length of the type-specific struct
845         
846 protected:
847         CompiledDefHeader hdr;
848
849         // sym is the symbol from which to get the path/name, and
850         // dir is true if it should be "name/.self" rather than 
851         // "name".
852         void output_self(const char *dir, Symbol *sym, bool dir);
853
854 public:
855         Def(const char *self, int self_len, CompiledDefHeader::Type type) :
856         self(self), self_len(self_len)
857         {
858                 hdr.magic = CompiledDefHeader::magic_normal;
859                 hdr.type = type;
860         }
861         
862         virtual ~Def()
863         {
864         }
865         
866         // Specific types may override this to output extra data
867         // to the .self file without having to reopen the file.
868         //
869         // Returns false on error.
870         
871         virtual bool output_extra(FILE *f)
872         {
873                 return true;
874         }
875 };
876
877 // Internal context struct used by input.cc to avoid passing
878 // lots of parameters around
879 struct ImportContext;
880
881 // This represents an actual IDL namespace {}, rather than
882 // a derived namespace such as a Struct or Interface.
883
884 class UserNameSpace : public NameSpace, public Def {
885 public:
886         CompiledNameSpace def;
887         StringRef mountpoint_name;
888
889         UserNameSpace(const String *name = NULL) :
890         Symbol(name),
891         Def((const char *)&def, sizeof(def), CompiledDefHeader::NameSpace)
892         {
893                 mountpoint_name = get_fq_name()->flatten();
894                 def.length = mountpoint_name->length();
895         }
896
897         virtual void output(const char *root);
898         bool output_extra(FILE *f);
899         
900         static void declare_import(const char *path);
901
902         static UserNameSpace *import(ImportContext &ctx);
903         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
904 };
905
906 typedef Ref<UserNameSpace> UserNameSpaceRef;
907 extern UserNameSpaceRef toplevel, cdl_toplevel;
908 extern UserNameSpace *output_ns;
909
910 class Type : public virtual Symbol {
911 public:
912         Type()
913         {
914         }
915         
916         virtual ~Type()
917         {
918         }
919         
920         virtual int get_default_bf_size()
921         {
922                 // Only allow types in bitfields that explicitly
923                 // support it.
924                 
925                 return -1;
926         }
927 };
928
929 typedef Ref<Type> TypeRef;
930
931 // ctx can be NULL if basic_types_only is true
932 Type *lookup_type(StrList *sl, NameSpace *ctx, bool basic_types_only = false);
933
934 class BasicType : public Type, public Def {
935 public:
936         CompiledBasicType def;
937         bool complete;
938         
939         BasicType(const String *name) :
940         Symbol(name),
941         Def((const char *)&def, sizeof(def), CompiledDefHeader::BasicType)
942         {
943                 complete = false;
944                 memset(&def, 0, sizeof(def));
945         }
946
947         void init(CompiledBasicType &DEF)
948         {
949                 assert(!complete);
950         
951                 def = DEF;
952                 complete = true;
953         }
954
955         static BasicType *declare(const String *name, NameSpace *parent,
956                                   CompiledBasicType &DEF)
957         {
958                 BasicType *bt = new BasicType(name);
959                 bt->init(DEF);
960         
961                 if (parent)
962                         parent->add_user(bt);
963
964                 return bt;
965         }
966
967         virtual void output(const char *root);
968
969         static BasicType *import(ImportContext &ctx);
970         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
971 };
972
973 static inline bool is_array(CompiledBasicType &bt)
974 {
975         return bt.array.bounds[0] || bt.array.bounds[1];
976 }
977
978 static inline bool is_array(CompiledBasicType *bt)
979 {
980         return is_array(*bt);
981 }
982
983 typedef Ref<Datum> DatumRef;
984
985 class Array : public RefCountable<Array>
986 {
987         NameSpace *lookup_ctx;
988         DatumRef datums[2];
989
990         // lower is [0], upper is [1]
991         StrListRef dcons[2];
992         Con cons[2];
993         
994         // Strings for error reporting on each constant.  If the constant
995         // is symbolic, then this is the fully qualified symbol name. 
996         // Otherwise, it is the numerical value converted to a string.  In
997         // each case, the file/line shall correspond to where the array
998         // bound was specified.
999         
1000         StringRef strs[2];
1001         
1002 public:
1003         // ca is not valid until after final_analysis() is called.
1004         CompiledArray ca;
1005
1006         Array(NameSpace *LOOKUP_CTX);
1007         void set_bound(Con &con, int bound);
1008         void final_analysis();
1009
1010         void set_unbounded();
1011 };
1012
1013 typedef Ref<Array> ArrayRef;
1014
1015 class Datum : public Symbol, public Def {
1016         StrListRef type_name;
1017         SymbolRef type_sym;
1018         StringRef type_fq_name;
1019
1020         StrListRef const_val_name;
1021         SymbolRef const_val_sym;
1022         DatumRef const_val;
1023
1024         bool basic;      // Datum is of a BasicType
1025         bool complete;
1026         bool const_init; // Datum's constant has been initialized; this is
1027                          // true after a successful verify_const().
1028         CompiledBasicType *cbt;
1029         
1030         ArrayRef array;
1031
1032         int chain_traversed;
1033
1034         // Recursively retrieve the actual value of a const datum
1035         // initialized with another named const datum.  Returns
1036         // the "end" of an infinite loop, if one is found.  Once
1037         // the full infinite loop has been printed, UserError is
1038         // thrown.
1039
1040         Datum *resolve_constant_chain();
1041
1042         void init_const_early(Con *con);
1043         
1044         void use_anon_type(const CompiledBasicType &CBT)
1045         {
1046                 def.basictype = CBT;
1047                 cbt = &def.basictype;
1048                 basic = true;
1049                 type = NULL;
1050                 def.type.length = 0;
1051         }
1052         
1053         void process_type();
1054         
1055         void set_array(Array *ARRAY)
1056         {
1057                 if (ARRAY)
1058                         array = ARRAY;
1059         }
1060
1061 public:
1062         CompiledDatum def;
1063         TypeRef type;
1064
1065         int con_type;    // Used to store the TOK_[IUF]CON of the Con struct
1066                          // for type checking once the type is known.
1067
1068         Datum(const String *name) :
1069         Symbol(name), 
1070         Def((const char *)&def, sizeof(def), CompiledDefHeader::Datum)
1071         {
1072                 complete = false;
1073                 const_init = false;
1074                 chain_traversed = 0;
1075                 memset(&def, 0, sizeof(def));
1076         }
1077
1078         void init(StrList *type, Array *ARRAY, Con *con = NULL);
1079         void init(CompiledBasicType &cbt, Array *ARRAY, Con *con = NULL);
1080
1081         static Datum *declare(const String *name, NameSpace *parent,
1082                               StrList *type, Array *ARRAY,
1083                               Con *con = NULL)
1084         {
1085                 assert(parent);
1086                 
1087                 Datum *d = new Datum(name);
1088                 d->init(type, ARRAY, con);
1089
1090                 parent->add_user(d);
1091                 return d;
1092         }
1093
1094         static Datum *declare(const String *name, NameSpace *parent,
1095                               CompiledBasicType &type, 
1096                               Array *ARRAY, Con *con = NULL)
1097         {
1098                 assert(parent);
1099         
1100                 Datum *d = new Datum(name);
1101                 d->init(type, ARRAY, con);
1102
1103                 parent->add_user(d);
1104                 return d;
1105         }
1106         
1107         void set_inline()
1108         {
1109                 def.flags.field.Inline = 1;
1110         }
1111         
1112         bool is_inline()
1113         {
1114                 return def.flags.field.Inline;
1115         }
1116         
1117         void set_immutable()
1118         {
1119                 def.flags.field.Immutable = 1;
1120         }
1121         
1122         bool is_immutable()
1123         {
1124                 return def.flags.field.Immutable;
1125         }
1126
1127         // Returns true if the constant was acceptable, false otherwise (an
1128         // error is also output to the user in this case).
1129         
1130         bool verify_const();
1131
1132         virtual void lookup_chain()
1133         {
1134                 assert(complete);
1135
1136                 if (const_val_name)
1137                         const_val_sym = lookup_sym(toplevel, const_val_name, get_ns());
1138
1139                 if (type_name) {
1140                         assert(!basic);
1141                         type_sym = lookup_type(type_name, get_ns(), true);
1142                         if (!type_sym)
1143                                 type_sym = lookup_sym(toplevel, type_name, get_ns());
1144                 } else {
1145                         assert(basic);
1146                 }
1147         }
1148
1149         virtual void lookup_misc()
1150         {
1151                 if (def.flags.field.Const) {
1152                         if (!const_init) {
1153                                 assert(def.flags.field.Const);
1154         
1155                                 traversal++;
1156                                 Datum *d = resolve_constant_chain();
1157                                 assert(!d);
1158                         }
1159                 
1160                         assert(const_init);
1161                 } else {
1162                         process_type();
1163                 }
1164         }
1165         
1166         virtual void final_analysis();
1167
1168         virtual void output(const char *root);
1169         bool output_extra(FILE *f);
1170
1171         static Datum *import(ImportContext &ctx);
1172         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1173
1174         uint64_t get_ucon(const String *err_str)
1175         {
1176                 if (!def.flags.field.Const) {
1177                         yyerrorfl(err_str->file, err_str->line, 
1178                                   "\"%s\" is not a const Datum.\n",
1179                                   get_fq_name()->flatten()->c_str());
1180                         throw UserError();
1181                 }
1182                 
1183                 assert(const_init);
1184                 return def.ucon;
1185         }
1186
1187         bool is_array()
1188         {
1189                 return ::is_array(def.basictype);
1190         }
1191 };
1192
1193 template<typename T>
1194 bool output_list(T *sym, FILE *f);
1195
1196 class BitField : public NameSpace, public Type, public Def {
1197         list<DatumRef> entries;
1198
1199         void add_elem(Datum *d);
1200
1201 public:
1202         CompiledBitField def;
1203         int cur_pos;
1204
1205         BitField(const String *name) :
1206         Symbol(name),
1207         Def((const char *)&def, sizeof(def), CompiledDefHeader::BitField)
1208         {
1209                 memset(&def, 0, sizeof(def));
1210         }
1211
1212         void init(int bits, NameSpace *parent)
1213         {
1214                 if (bits < 0 || bits > 64) {
1215                         yyerrorf("\"%s\" has invalid bitfield size %d", 
1216                                  name->c_str(), bits);
1217
1218                         bits = bits < 0 ? 0 : 64;
1219                 }
1220         
1221                 def.bits = bits;
1222         }
1223
1224         static BitField *declare(const String *name, NameSpace *parent,
1225                                  int bits)
1226         {
1227                 assert(parent);
1228                 
1229                 BitField *bf = new BitField(name);
1230                 bf->init(bits, parent);
1231         
1232                 parent->add_user(bf);
1233                 return bf;
1234         }
1235
1236         // Only integral Datums, Enums, and BitFields can be added.
1237
1238         void add(Symbol *sym, bool from_import);
1239
1240         virtual const char *description()
1241         {
1242                 return "bitfield";
1243         }
1244
1245         virtual void lookup_misc()
1246         {
1247                 NameSpace::lookup_misc();
1248         }
1249         
1250         virtual void final_analysis()
1251         {
1252                 // FIXME: check total size of elements
1253         
1254                 NameSpace::final_analysis();
1255         }
1256
1257         int get_default_bf_size()
1258         {
1259                 return def.bits;
1260         }
1261
1262         virtual void output(const char *root);
1263         bool output_extra(FILE *f);
1264
1265         static BitField *import(ImportContext &ctx);
1266         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1267
1268         typedef list<DatumRef>::const_iterator entries_iterator;
1269         typedef list<DatumRef>::const_reverse_iterator entries_reverse_iterator;
1270
1271         entries_iterator entries_begin()
1272         {
1273                 return entries.begin();
1274         }
1275
1276         entries_iterator entries_end()
1277         {
1278                 return entries.end();
1279         }
1280
1281         entries_reverse_iterator entries_rbegin()
1282         {
1283                 return entries.rbegin();
1284         }
1285
1286         entries_reverse_iterator entries_rend()
1287         {
1288                 return entries.rend();
1289         }
1290 };
1291
1292 class Struct;
1293 typedef Ref<Struct> StructRef;
1294 extern Struct *System_VStruct;
1295
1296 // FIXME: typedefed superstructs
1297 class Struct : public NameSpace, public Type, public Def {
1298         list<DatumRef> entries;
1299         StructRef super;
1300         SymbolRef supersym;
1301         StrListRef supername;
1302         bool attrs_resolved;
1303         
1304         void add_elem(Datum *d);
1305
1306         void resolve_attrs()
1307         {
1308                 if (attrs_resolved)
1309                         return;
1310                 
1311                 if (super && !super->attrs_resolved)
1312                         super->resolve_attrs();
1313                 
1314                 if (super && super->def.flags.field.Virtual)
1315                         def.flags.field.Virtual = 1;
1316                 
1317                 attrs_resolved = true;
1318         }
1319         
1320 public:
1321         CompiledStruct def;
1322         
1323         // This is not maintained by the generic code, but can be
1324         // used by language bindings to cache the result of the
1325         // summation. 
1326         
1327         int chainlen;
1328         
1329         Struct(const String *name) :
1330         Symbol(name),
1331         Def((const char *)&def, sizeof(def), CompiledDefHeader::Struct)
1332         {
1333                 memset(&def, 0, sizeof(def));
1334                 attrs_resolved = 0;
1335         }
1336         
1337         void init(StrList *SUPERNAME)
1338         {
1339                 supername = SUPERNAME;
1340         }
1341
1342         static Struct *declare(const String *name, NameSpace *parent,
1343                                StrList *SUPERNAME)
1344         {
1345                 assert(parent);
1346         
1347                 Struct *st = new Struct(name);
1348                 st->init(SUPERNAME);
1349
1350                 parent->add_user(st);
1351                 return st;
1352         }
1353         
1354         void set_virtual()
1355         {
1356                 def.flags.field.Virtual = 1;
1357         }
1358
1359         void set_inline()
1360         {
1361                 def.flags.field.Inline = 1;
1362         }
1363
1364         bool is_virtual()
1365         {
1366                 return def.flags.field.Virtual;
1367         }
1368
1369         bool is_inline()
1370         {
1371                 return def.flags.field.Inline;
1372         }
1373         
1374         // Only Datums and Types can be added.
1375
1376         void add(Symbol *sym, bool from_import);
1377
1378         virtual const char *description()
1379         {
1380                 return "struct";
1381         }
1382         
1383         Struct *get_super()
1384         {
1385                 assert(current_pass >= 4);
1386                 return super;
1387         }
1388
1389         virtual void lookup_chain()
1390         {
1391                 if (supername) {
1392                         supersym = lookup_sym(toplevel, supername, get_ns());
1393                         assert(supersym);
1394                 }
1395
1396                 NameSpace::lookup_chain();
1397         }
1398
1399 private:
1400         void lookup_super()
1401         {
1402                 if (supersym && !super) {
1403                         super = dynamic_cast<Struct *>(supersym->get_concrete_sym());
1404                 
1405                         if (!super) {
1406                                 const String *str = supername->back();
1407                                 yyerrorfl(str->file, str->line,
1408                                           "\"%s\" is not a struct.",
1409                                           supersym->get_fq_name()->flatten()->c_str());
1410                         }
1411                         
1412                         def.flags.field.Super = 1;
1413                         super->lookup_super();
1414                         
1415                         if (super->is_virtual())
1416                                 set_virtual();
1417                 }
1418                 
1419                 if (is_virtual() && !supersym && !super) {
1420                         assert(System_VStruct);
1421                         if (this != System_VStruct) {
1422                                 def.flags.field.Super = 1;
1423                                 super = System_VStruct;
1424                         }
1425                 }
1426         }
1427         
1428 public:
1429         virtual void lookup_misc()
1430         {
1431                 lookup_super();
1432
1433                 if (is_virtual() && def.guid[0] == 0 && def.guid[1] == 0)
1434                         yyerrorfl(name->file, name->line,
1435                                   "Virtual struct \"%s\" is missing a GUID.",
1436                                   get_fq_name()->flatten()->c_str());
1437
1438                 NameSpace::lookup_misc();
1439         }
1440         
1441         virtual void final_analysis()
1442         {
1443                 // FIXME: check for infinite loops in struct inheritance
1444
1445                 resolve_attrs();
1446                 NameSpace::final_analysis();
1447         }
1448
1449         virtual void output(const char *root);
1450         bool output_extra(FILE *f);
1451
1452         static Struct *import(ImportContext &ctx);
1453         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1454
1455         typedef list<DatumRef>::const_iterator entries_iterator;
1456
1457         entries_iterator entries_begin()
1458         {
1459                 return entries.begin();
1460         }
1461
1462         entries_iterator entries_end()
1463         {
1464                 return entries.end();
1465         }
1466
1467         void set_guid(uint64_t guid[2])
1468         {
1469                 if (def.guid[0] || def.guid[1])
1470                         yyerrorf("\"%s\" already has a GUID.",
1471                                  get_fq_name()->flatten()->c_str());
1472         
1473                 def.guid[0] = guid[0];
1474                 def.guid[1] = guid[1];
1475         }
1476 };
1477
1478 class Param : public Symbol, public Def {
1479         StrListRef type_name;
1480         StringRef type_fq_name;
1481
1482         bool basic;      // Datum is of a BasicType
1483         bool complete;
1484         
1485         ArrayRef array;
1486
1487         void use_named_type(BasicType *bt)
1488         {
1489                 assert(!bt || bt->def.flags.field.TypeDef);
1490                 
1491                 basic = false;
1492
1493                 type_fq_name = type->get_fq_name()->flatten();
1494                 def.type.length = type_fq_name->length();
1495         }
1496         
1497         void use_anon_type(const CompiledBasicType &cbt)
1498         {
1499                 def.basictype = cbt;
1500                 basic = true;
1501                 type = NULL;
1502         }
1503
1504         void set_array(Array *ARRAY)
1505         {
1506                 if (ARRAY)
1507                         array = ARRAY;
1508         }
1509
1510 public:
1511         CompiledParam def;
1512         TypeRef type;
1513
1514         Param(const String *name) :
1515         Symbol(name),
1516         Def((const char *)&def, sizeof(def), CompiledDefHeader::Param)
1517         {
1518                 memset(&def, 0, sizeof(def));
1519         }
1520
1521         void init(StrList *TYPE, CompiledParam::Flags flags, Array *ARRAY)
1522         {
1523                 type_name = TYPE;
1524                 def.flags = flags;
1525                 set_array(ARRAY);
1526         }
1527
1528         static Param *declare(const String *name, NameSpace *parent,
1529                               StrList *TYPE, CompiledParam::Flags flags,
1530                               Array *ARRAY);
1531
1532         virtual void lookup_misc()
1533         {
1534                 type = lookup_type(type_name, get_ns());
1535         }
1536         
1537         virtual void final_analysis()
1538         {
1539                 BasicType *bt = dynamic_cast<BasicType *>(type->get_concrete_sym());
1540
1541                 if (bt && !bt->def.flags.field.TypeDef) {
1542                         use_anon_type(bt->def);
1543                 } else {
1544                         use_named_type(bt);
1545
1546                         Struct *str = dynamic_cast<Struct *>(*type);
1547                         if (str && str->is_inline())
1548                                 set_inline();
1549                         
1550                         if (!str && is_inline()) {
1551                                 yyerrorfl(name->file, name->line,
1552                                           "\"%s\" is static but not a struct.",
1553                                           get_fq_name()->flatten()->c_str());
1554                         }
1555                 }
1556         
1557                 if (array) {
1558                         array->final_analysis();
1559                         def.basictype.array = array->ca;
1560                 } else {
1561                         def.basictype.array.bounds[0] = 0;
1562                         def.basictype.array.bounds[1] = 0;
1563                 }
1564         }
1565
1566         void set_inline()
1567         {
1568                 def.flags.field.Inline = 1;
1569         }
1570
1571         bool is_inline()
1572         {
1573                 return def.flags.field.Inline;
1574         }
1575         
1576         bool is_in()
1577         {
1578                 return def.flags.field.In;
1579         }
1580
1581         bool is_out()
1582         {
1583                 return def.flags.field.Out;
1584         }
1585
1586         virtual void output(const char *root);
1587         bool output_extra(FILE *f);
1588
1589         static Param *import(ImportContext &ctx);
1590         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1591         
1592         bool is_array()
1593         {
1594                 return ::is_array(def.basictype);
1595         }
1596 };
1597
1598 typedef Ref<Param> ParamRef;
1599
1600 class Method : public NameSpace, public Def {
1601         list<ParamRef> entries;
1602
1603         void add_elem(Param *p);
1604
1605 public:
1606         CompiledMethod def;
1607         
1608         Method(const String *name) :
1609         Symbol(name), 
1610         Def((const char *)&def, sizeof(def), CompiledDefHeader::Method)
1611         {
1612                 memset(&def, 0, sizeof(def));
1613         }
1614
1615         void set_async()
1616         {
1617                 def.flags.field.Async = 1;
1618         }
1619         
1620         bool is_async()
1621         {
1622                 return def.flags.field.Async;
1623         }
1624         
1625         static Method *declare(const String *name, NameSpace *parent);
1626
1627         void add(Symbol *sym, bool from_import);
1628
1629         virtual const char *description()
1630         {
1631                 return "method";
1632         }
1633
1634         virtual void output(const char *root);
1635         bool output_extra(FILE *f);
1636
1637         static Method *import(ImportContext &ctx);
1638         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1639
1640         typedef list<ParamRef>::const_iterator entries_iterator;
1641
1642         entries_iterator entries_begin()
1643         {
1644                 return entries.begin();
1645         }
1646
1647         entries_iterator entries_end()
1648         {
1649                 return entries.end();
1650         }
1651 };
1652
1653 typedef Ref<Method> MethodRef;
1654
1655 class Interface;
1656 typedef Ref<Interface> InterfaceRef;
1657
1658 extern Interface *System_Object;
1659
1660 // FIXME: typedefed superinterfaces
1661 class Interface : public NameSpace, public Type, public Def {
1662         list<MethodRef> methods;
1663         list<InterfaceRef> supers;
1664         IDListRef supernames;
1665
1666         void add_elem(Method *m);
1667
1668         // This is like Symbol::traversed[], but used internally by the
1669         // for_each_super function to ensure that common ancestors are only
1670         // visited once.
1671         
1672         int traversed_all_supers;
1673         static int all_supers_traversal;
1674         
1675 public:
1676         typedef void (*callback)(Interface *i, void *arg);
1677         
1678 private:
1679         template<callback cb>
1680         void for_each_super_internal(void *arg)
1681         {
1682                 for (supers_iterator i = supers_begin(); i != supers_end(); ++i) {
1683                         Interface *iface = *i;
1684                         
1685                         if (iface->traversed_all_supers < all_supers_traversal) {
1686                                 iface->traversed_all_supers = all_supers_traversal;
1687                                 cb(iface, arg);
1688                                 iface->for_each_super_internal<cb>(arg);
1689                         }
1690                 }
1691         }
1692
1693         // All interfaces in the map and vector are supers of this
1694         // interface, and thus retained that way, so plain pointers
1695         // can be used here.
1696
1697         typedef map<Interface *, int> chain_map_type;
1698         typedef chain_map_type::value_type chain_valtype;
1699         typedef chain_map_type::const_iterator chain_iter;
1700
1701         chain_map_type super_to_chain_map;
1702
1703 private:
1704         int num_chains;
1705         vector<Interface *> chain_heads;
1706
1707 public: 
1708         int super_to_chain(Interface *iface, bool must_find_it = true)
1709         {
1710                 chain_iter ret = super_to_chain_map.find(iface);
1711                 
1712                 if (ret == super_to_chain_map.end()) {
1713                         assert(!must_find_it);
1714                         return -1;
1715                 }
1716
1717                 return (*ret).second;
1718         }
1719
1720         Interface *get_chain_head(int chain)
1721         {
1722                 return chain_heads[chain];
1723         }
1724
1725         int get_num_chains()
1726         {
1727                 return num_chains;
1728         }
1729         
1730 private:        
1731         void set_chain(Interface *iface, int chain)
1732         {
1733                 pair<chain_iter, bool> ret = 
1734                         super_to_chain_map.insert(chain_valtype(iface, chain));
1735                 assert(ret.second);
1736         }
1737         
1738         // This is the inner depth-first search, which terminates
1739         // at each level upon finding that the node it had previously
1740         // recursed into found an unchained node.
1741         
1742         void pick_chain(Interface *iface, int chain)
1743         {
1744                 assert(super_to_chain(iface, false) == -1);
1745                 chain_heads.push_back(iface);
1746         
1747                 do {
1748                         set_chain(iface, chain);
1749                         
1750                         if (iface->supers.empty())
1751                                 break;
1752                         
1753                         iface = iface->supers.front();
1754                 } while (super_to_chain(iface, false) == -1);
1755         }
1756
1757         // This is the outer breadth-first-search, making sure every
1758         // super is assigned to a chain.
1759
1760         void sort_chains()
1761         {
1762                 list<Interface *> bfs;
1763                 num_chains = 0;
1764
1765                 bfs.push_back(this);
1766                 
1767                 while (!bfs.empty()) {
1768                         Interface *iface = bfs.front();
1769                         bfs.pop_front();
1770                 
1771                         for (supers_iterator i = iface->supers_begin();
1772                              i != iface->supers_end(); ++i)
1773                                 bfs.push_back(*i);
1774                 
1775                         if (super_to_chain(iface, false) == -1)
1776                                 pick_chain(iface, num_chains++);
1777                 }
1778         }
1779
1780 public:
1781         // Do not call after lookup_misc
1782         void add_super(Interface *i)
1783         {
1784                 assert(current_pass != 1);
1785         
1786                 supers.push_back(i);
1787                 def.num_supers++;
1788         }
1789
1790         CompiledInterface def;
1791         
1792         Interface(const String *name) :
1793         Symbol(name),
1794         Def((const char *)&def, sizeof(def), CompiledDefHeader::Interface)
1795         {
1796                 memset(&def, 0, sizeof(def));
1797                 traversed_all_supers = 0;
1798         }
1799         
1800         void init(IDList *SUPERNAMES)
1801         {
1802                 supernames = SUPERNAMES;
1803         }
1804
1805         static Interface *declare(const String *name, NameSpace *parent, 
1806                                   IDList *SUPERNAMES)
1807         {
1808                 assert(parent);
1809
1810                 Interface *i = new Interface(name);
1811                 i->init(SUPERNAMES);
1812                 
1813                 parent->add_user(i);
1814                 return i;
1815         }
1816         
1817         // Only Methods, Types, and const BasicType Datums can be added.
1818
1819         void add(Symbol *sym, bool from_import);
1820
1821         virtual const char *description()
1822         {
1823                 return "interface";
1824         }
1825
1826 private:
1827         void add_object_super()
1828         {
1829                 assert(System_Object);
1830                 if (this != System_Object && supers.empty())
1831                         add_super(System_Object);
1832         }
1833
1834 public: 
1835         virtual void lookup_misc()
1836         {
1837                 if (def.guid[0] == 0 && def.guid[1] == 0)
1838                         yyerrorfl(name->file, name->line,
1839                                   "Interface \"%s\" is missing a GUID.",
1840                                   get_fq_name()->flatten()->c_str());
1841         
1842                 if (supernames) {
1843                         for (IDList::iterator i = supernames->begin(); 
1844                              i != supernames->end(); ++i)
1845                         {
1846                                 Symbol *sym = lookup_sym(toplevel, *i, get_ns());
1847                                 Interface *iface = 
1848                                         dynamic_cast<Interface *>(sym->get_concrete_sym());
1849                                 
1850                                 if (!iface) {
1851                                         const String *str = (*i)->back();
1852                                         yyerrorfl(str->file, str->line,
1853                                                   "\"%s\" is not an interface.\n",
1854                                                   sym->get_fq_name()->flatten()->c_str());
1855         
1856                                         throw UserError();
1857                                 }
1858                                 
1859                                 add_super(iface);
1860                         }
1861                 }
1862                 
1863                 add_object_super();
1864                 NameSpace::lookup_misc();
1865         }
1866         
1867         virtual void final_analysis()
1868         {
1869                 // FIXME: check for infinite loops in inheritance
1870         
1871                 sort_chains();
1872                 NameSpace::final_analysis();
1873         }
1874         
1875         virtual void output(const char *root);
1876         bool output_extra(FILE *f);
1877
1878         static Interface *import(ImportContext &ctx);
1879         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
1880
1881         typedef list<MethodRef>::const_iterator methods_iterator;
1882         typedef list<InterfaceRef>::const_iterator supers_iterator;
1883
1884         supers_iterator supers_begin()
1885         {
1886                 assert(current_pass != 1);
1887                 return supers.begin();
1888         }
1889
1890         supers_iterator supers_end()
1891         {
1892                 return supers.end();
1893         }
1894         
1895         bool supers_empty()
1896         {
1897                 assert(current_pass != 1);
1898                 return supers.empty();
1899         }
1900
1901         methods_iterator methods_begin()
1902         {
1903                 return methods.begin();
1904         }
1905
1906         methods_iterator methods_end()
1907         {
1908                 return methods.end();
1909         }
1910         
1911         template<callback cb>
1912         void for_each_super(void *arg)
1913         {
1914                 assert(current_pass >= 4);
1915         
1916                 all_supers_traversal++;
1917                 for_each_super_internal<cb>(arg);
1918         }
1919
1920         void finalize_class_iface()
1921         {
1922                 add_object_super();
1923                 sort_chains();
1924         }
1925         
1926         void set_guid(uint64_t guid[2])
1927         {
1928                 if (def.guid[0] || def.guid[1])
1929                         yyerrorf("\"%s\" already has a GUID.",
1930                                  get_fq_name()->flatten()->c_str());
1931         
1932                 def.guid[0] = guid[0];
1933                 def.guid[1] = guid[1];
1934         }
1935 };
1936
1937 class IFaceList : public list<InterfaceRef>,
1938                   public RefCountable<IFaceList> {};
1939
1940 class Enum : public NameSpace, public Type, public Def {
1941         list<DatumRef> entries;
1942
1943         void add_elem(Datum *d);
1944
1945 public:
1946         unsigned int next_val;
1947         CompiledEnum def;
1948
1949         Enum(const String *name) :
1950         Symbol(name),
1951         Def((const char *)&def, sizeof(def), CompiledDefHeader::Enum),
1952         next_val(0)
1953         {
1954                 memset(&def, 0, sizeof(def));
1955         }
1956
1957         void init(int bits)
1958         {
1959                 if (bits < 0 || bits > 64) {
1960                         yyerrorf("\"%s\" has invalid enum size %d", 
1961                                  name->c_str(), bits);
1962
1963                         bits = bits < 0 ? 0 : 64;
1964                 }
1965         
1966                 def.bits = bits;
1967         }
1968
1969         static Enum *declare(const String *name, NameSpace *parent,
1970                              int bits)
1971         {
1972                 assert(parent);
1973                 
1974                 Enum *e = new Enum(name);
1975                 e->init(bits);
1976                 
1977                 parent->add_user(e);
1978                 return e;
1979         }
1980
1981         // Only const unsigned integer BasicType Datums are allowed.
1982
1983         void add(Symbol *sym, bool from_import);
1984
1985         virtual const char *description()
1986         {
1987                 return "enumeration";
1988         }
1989
1990         int get_default_bf_size()
1991         {
1992                 return def.bits;
1993         }
1994
1995         virtual void output(const char *root);
1996         bool output_extra(FILE *f);
1997
1998         static Enum *import(ImportContext &ctx);
1999         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
2000
2001         typedef list<DatumRef>::const_iterator entries_iterator;
2002
2003         entries_iterator entries_begin()
2004         {
2005                 return entries.begin();
2006         }
2007
2008         entries_iterator entries_end()
2009         {
2010                 return entries.end();
2011         }
2012 };
2013
2014 class Alias : public Symbol, public Def {
2015         bool lookup_begun;
2016         
2017         struct Cycle {
2018                 Alias *end;
2019                 
2020                 Cycle(Alias *END) : end(END)
2021                 {
2022                 }
2023         };
2024
2025 public:
2026         CompiledAlias def;
2027         
2028         SymbolRef real_sym;
2029         StringRef sym_fq_name;
2030         StrListRef sym_name;
2031         
2032         Alias(const String *name) :
2033         Symbol(name),
2034         Def((const char *)&def, sizeof(def), CompiledDefHeader::Alias)
2035         {
2036                 memset(&def, 0, sizeof(def));
2037                 lookup_begun = false;
2038         }
2039         
2040         void init(StrList *symname, bool is_private)
2041         {
2042                 sym_name = symname;
2043                 priv = is_private;
2044         }
2045
2046         static Alias *declare(const String *name, NameSpace *parent,
2047                               StrList *symname, bool is_private = false)
2048         {
2049                 assert(parent);
2050                 Alias *a = new Alias(name);
2051                 a->init(symname, is_private);
2052
2053                 parent->add_user(a);
2054                 return a;
2055         }
2056         
2057         void resolve_chain()
2058         {       
2059                 if (!real_sym) {
2060                         if (lookup_begun) {
2061                                 yyerrorfl(name->file, name->line,
2062                                           "Alias loop defining \"%s\"",
2063                                           get_fq_name()->flatten()->c_str());
2064                         
2065                                 throw Cycle(this);
2066                         }
2067                         
2068                         lookup_begun = true;
2069                         
2070                         try {
2071                                 real_sym = lookup_sym(toplevel, sym_name, get_ns(), this);
2072                         }
2073                         
2074                         catch (Cycle &c) {
2075                                 yyerrorfl(name->file, name->line, "   ...referenced by \"%s\"",
2076                                           get_fq_name()->flatten()->c_str());
2077
2078                                 if (c.end == this)
2079                                         throw UserError();
2080
2081                                 throw c;
2082                         }
2083                 }
2084         }
2085
2086         virtual Symbol *get_concrete_sym(bool follow_typedefs = true)
2087         {
2088                 resolve_chain();
2089                 return real_sym->get_concrete_sym(follow_typedefs);
2090         }
2091
2092         virtual void lookup_chain()
2093         {
2094                 get_concrete_sym(true);
2095         }
2096
2097         virtual void lookup_misc()
2098         {
2099                 real_sym = real_sym->get_concrete_sym(false);
2100                 sym_fq_name = real_sym->get_fq_name()->flatten();
2101                 
2102                 def.length = sym_fq_name->length();
2103         }
2104
2105         virtual void output(const char *root);
2106         bool output_extra(FILE *f);
2107
2108         static Alias *import(ImportContext &ctx);
2109         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
2110 };
2111
2112 class TypeDef : public Alias {
2113 public:
2114         TypeDef(const String *name) : Alias(name)
2115         {
2116                 memset(&def, 0, sizeof(def));
2117                 hdr.type = CompiledDefHeader::TypeDef;
2118         }
2119         
2120         static TypeDef *declare(const String *name, NameSpace *parent,
2121                                 StrList *symname)
2122         {
2123                 assert(parent);
2124                 TypeDef *td = new TypeDef(name);
2125                 td->init(symname, false);
2126                 
2127                 parent->add_user(td);
2128                 return td;
2129         }
2130
2131         virtual Symbol *get_concrete_sym(bool follow_typedefs = true)
2132         {
2133                 if (follow_typedefs) {
2134                         resolve_chain();
2135                         return real_sym->get_concrete_sym(follow_typedefs);
2136                 }
2137                 
2138                 return this;
2139         }
2140
2141         static TypeDef *import(ImportContext &ctx);
2142         virtual void output_lang(LangCallback *lcb, int arg = 0, void *arg2 = NULL);
2143 };
2144
2145 NameSpace *add_nspace(StrList *name, bool push);
2146 void pop_nspace();
2147
2148 // Declare an instance of "type" in "ns" for each element of "ids".
2149 // This function will report any errors, but not throw UserError.
2150
2151 void declare_data(NameSpace *ns, StrList *ids, StrList *type,
2152                   Array *array, StrList *attr);
2153 void declare_aliases(NameSpace *ns, StrList *ids, StrList *type,
2154                      bool is_typedef);
2155 void declare_basictypes(NameSpace *ns, StrList *ids,
2156                         BasicType *type, bool is_typedef);
2157
2158 // You'd think they'd have standard functions to do this these days.
2159 // All I could find that come close are the network-byte-order
2160 // functions, and they're no-ops on big-endian machines.
2161
2162 static inline uint32_t swap32(uint32_t in, bool swap)
2163 {
2164         if (swap)
2165                 return ((in & 0x000000ff) << 24) |
2166                        ((in & 0x0000ff00) <<  8) |
2167                        ((in & 0x00ff0000) >>  8) |
2168                        ((in & 0xff000000) >> 24);
2169         
2170         return in;
2171 }
2172
2173 static inline uint64_t swap64(uint64_t in, bool swap)
2174 {
2175         if (swap)
2176                 return (((uint64_t)swap32((uint32_t)in, true)) << 32) |
2177                        swap32((uint32_t)(in >> 32), true);
2178
2179         return in;
2180 }
2181
2182 struct File {
2183         FILE *f;
2184         
2185         File()
2186         {
2187                 f = NULL;
2188         }
2189         
2190         File(FILE *F)
2191         {
2192                 f = F;
2193         }
2194         
2195         File *operator =(FILE *F)
2196         {
2197                 f = F;
2198                 return this;
2199         }
2200         
2201         ~File()
2202         {
2203                 if (f)
2204                         fclose(f);
2205         }
2206         
2207         operator FILE *()
2208         {
2209                 return f;
2210         }
2211 };
2212
2213 // Verify that a prospective new import (or output namespace)
2214 // does not overlap an existing import.  Returns the conflicting
2215 // import, or NULL if none found.
2216
2217 NameSpace *check_for_imports(NameSpace *ns);
2218
2219 #endif