def cStruct_build_info(self, db): """Defines the structure layout for this class, according to the gcc cxx ABI for virtual classes. The returned value is a triplet, (vptr, M, V) where - vptr is a virtual indicator, - M is the list of non-virtual fields, - V is the ordered dict of virtual fields. """ self.unfold(db) M, V = [], OrderedDict() vptr = 0 # iterate over classes' fields for (x, y, _) in self: qal, t = x mn, n = y # we don't care about scope & comments # we start by handling parent classes: if qal == "parent": n = cxx_type(n) nn = n.show_base() name = n.show_base(True, True) x = ccore._cache_.get(name, None) try: if x._is_typedef: x = ccore._cache_.get(x, None) except Exception: pass if x is None: raise TypeError("unkown type '%s'" % n) assert x._is_class # get layout of the parent class: vtbl, m, v = x.cStruct_build_info(db) if t == "virtual": vptr = 2 if nn not in V: V[nn] = (vtbl, m) else: if vtbl: vptr += vtbl if len(m) > 0: if not m[0][1].startswith("__vptr"): t = cxx_type("void *") M.append((t, "__vptr$%s" % nn)) M.extend(m) V.update(v) elif qal == "using": continue elif "virtual" in qal: vptr = 1 else: t = cxx_type(t) if not t.is_method: M.append((t, n)) return (vptr, M, V)
def cTemplate_C(obj, db, recursive): identifier = obj.get_basename() template = obj.get_template() # get the cxx type object, for namespaces: tn = cxx_type(identifier) #namespace = tn.show_base(kw=False,ns=False) #prepare query if recursion is needed: if isinstance(recursive, set): #Q = True recursive.update(struct_letters) recursive.add(tn.lbase) for t in obj['params']: if t.startswith('typename '): t = t.replace('typename ', '') recursive.add(t) else: #Q = None pass R = [] #S holds template output lines: S = [u'template%s' % template] if 'cClass' in obj: from ccrawl.core import cClass o = cClass(obj['cClass']) o.identifier = identifier x = cClass_C(o, db, recursive) if 'cFunc' in obj: from ccrawl.core import cFunc o = cFunc(obj['cFunc']) o.identifier = identifier x = cFunc_C(o, db, recursive) x = x.split('\n\n') S.append(x.pop()) if len(x): R.append(x[0]) return '\n'.join(R) + '\n'.join(S)
def get_c_or_cxx_type(x): if not ('&' in x): try: t = c_type(x) except pp.ParseException: pass else: return t t = cxx_type(x) return t
def cStruct_build_info(self, db): self.unfold(db) M, V = [], OrderedDict() vptr = 0 for (x, y, _) in self: qal, t = x mn, n = y if qal == 'parent': n = cxx_type(n) nn = n.show_base() name = n.show_base(True, True) x = ccore._cache_.get(name, None) try: if x._is_typedef: x = ccore._cache_.get(x, None) except Exception: pass if x is None: raise TypeError("unkown type '%s'" % n) assert x._is_class vtbl, m, v = x.cStruct_build_info(db) if t == 'virtual': vptr = 2 if nn not in V: V[nn] = (vtbl, m) else: if vtbl: vptr += vtbl if len(m) > 0: if not m[0][1].startswith('__vptr'): t = cxx_type('void *') M.append((t, '__vptr$%s' % nn)) M.extend(m) V.update(v) elif 'virtual' in qal: vptr = 1 else: t = cxx_type(t) if not t.is_method: M.append((t, n)) return (vptr, M, V)
def as_cStruct(self, db): if self.identifier.startswith("union "): x = cUnion() else: x = cStruct() name = cxx_type(self.identifier) x.identifier = "struct __layout$%s" % (name.show_base(kw=False, ns=True)) # now get the structure information for this class: x.subtypes = None vptr, M, V = self.cStruct_build_info(db) if len(M) > 0 and vptr: if not M[0][1].startswith("__vptr"): n = cxx_type(self.identifier) x.append(("void *", "__vptr$%s" % n.show_base(), "")) for t, n in M: x.append((t.show(), n, "")) for nn, v in V.items(): vptr, m = v if vptr: x.append(("void *", "__vptr$%s" % nn, "")) for t, n in m: x.append((t.show(), n, "")) return x
def base_specifier_list(self): spe = [] for x, y, z in self: qal, t = x if 'parent' in qal: mn, n = y n = cxx_type(n) p, _ = z s = '' if t: s += ' virtual' s += ' %s %s' % (p.lower(), n.show_base()) spe.append(s) if len(spe) > 0: return ' :' + (','.join(spe)) else: return ''
def base_specifier_list(self): spe = [] for x, y, z in self: qal, t = x if "parent" in qal: mn, n = y n = cxx_type(n) p, _ = z s = "" if t: s += " virtual" s += " %s %s" % (p.lower(), n.show_base()) spe.append(s) if len(spe) > 0: return " :" + (",".join(spe)) else: return ""
def unfold(self, db, limit=None): if self.subtypes is None: self.subtypes = OrderedDict() T = list(struct_letters.keys()) T.append(self.identifier) for (x, y, _) in self: qal, t = x mn, n = y if qal == 'parent': elt = n else: if mn or ('virtual' in qal): continue elt = cxx_type(t) elt = elt.show_base(kw=True, ns=True) if (elt not in T): T.append(elt) self.add_subtype(db, elt, limit) return self
def as_cStruct(self, db): if self.identifier.startswith('union '): x = cUnion() else: x = cStruct() x.identifier = self.identifier x.subtypes = None vptr, M, V = self.cStruct_build_info(db) if len(M) > 0 and vptr: if not M[0][1].startswith('__vptr'): n = cxx_type(self.identifier) x.append(('void *', '__vptr$%s' % n.show_base(), '')) for t, n in M: x.append((t.show(), n, '')) for nn, v in V.items(): vptr, m = v if vptr: x.append(('void *', '__vptr$%s' % nn, '')) for t, n in m: x.append((t.show(), n, '')) return x
def unfold(self, db, limit=None): if self.subtypes is None: self.subtypes = OrderedDict() T = list(struct_letters.keys()) T.append(self.identifier) for (x, y, _) in self: qal, t = x mn, n = y if qal == "parent": elt = [n] elif qal == "using": elt = t else: if mn or ("virtual" in qal): continue elt = cxx_type(t) elt = elt.show_base(kw=True, ns=True) elt = [elt] for e in elt: if e not in T: T.append(e) self.add_subtype(db, e, limit) return self
def cClass_C(obj, db, recursive): # get the cxx type object: tn = cxx_type(obj.identifier) # get the current class name without keyword or namespace: classname = tn.show_base(kw=False, ns=False) # prepare query if recursion is needed: if isinstance(recursive, set): Q = True recursive.update(struct_letters) recursive.add(tn.lbase) else: Q = None # R holds recursive definition strings needed for obj R = [] # S holds obj title and fields declaration strings # we need obj.identifier here and not tn.show() because # template specialization need to keep the template string. S = [u"%s%s {" % (obj.identifier, obj.base_specifier_list())] # P holds lists for each public/protected/private/friend members P = {"": [], "PUBLIC": [], "PROTECTED": [], "PRIVATE": []} # now, iterate through all fields: for (x, y, z) in obj: qal, t = x # parent/virtual qualifier & type mn, n = y # mangled name & name p, c = z # public/protected/private & comment if qal == "parent": # the parent class name is found in n: r = cxx_type(n) e = r.lbase if Q and (e not in recursive): q = db.tag & (where("id") == e) x = obj.from_db(db.get(q)).show(db, recursive, form="C") R.append(x) recursive.add(e) continue elif qal == "using": # inherited type of attribute from parent is provided as a list in t: what = "::".join((cxx_type(u).show_base(kw=False) for u in t)) using = " using %s" % what # inherited name of attribute from parent is provided in n: # we append the attribute name unless its the class constructor using += "::%s;" % n if n != classname else ";" S.append(using) continue elif qal.startswith("template<"): P[p].append(" " + qal) qal = "" # decompose C-type t into specific parts: r = cxx_type(t) # get "element base" part of type t: e = r.lbase # is t a nested class ? nested = r.ns.split("::")[-1].startswith(classname) # is t a nested enum ? nested |= e.startswith("enum ?_") # query field element raw base type if needed: if Q and ((e not in recursive) or nested): # prepare query q = db.tag & (where("id") == e) # deal with nested type: if nested: q &= where("src") == tn.lbase if db.contains(q): # retreive the field type: x = obj.from_db(db.get(q)) x = x.show(db, recursive, form="C") if not nested: # if not nested, insert it directly in R R.append(x) recursive.add(e) else: x = x.replace("%s::" % classname, "") # nested struct/union/class: we need to transfer # any predefs into R x = x.split("\n\n") r.lbase = x.pop().replace("\n", "\n ").strip(";") if len(x): xr = x[0].split("\n") for xrl in xr: if xrl and xrl not in R: R.append(xrl) else: secho("identifier %s not found" % r.lbase, fg="red", err=True) # finally add field type and name to the structure lines: fo = "" if qal: if "," in qal: qal, fo = qal.split(",") qal = "%s " % qal P[p].append(u" {}{}{};".format(qal, r.show(n, kw=nested), fo)) # access specifier (empty is for friend members): for p in ("PUBLIC", "PROTECTED", "PRIVATE", ""): if len(P[p]) > 0: if p: S.append(" %s:" % p.lower()) for v in P[p]: S.append(v) # join R and S: if len(R) > 0: R.append("\n") S.append("};") return "\n".join(R) + "\n".join(S)
def cClass_C(obj, db, recursive): # get the cxx type object: tn = cxx_type(obj.identifier) # get the current class namespace: namespace = tn.show_base(kw=False, ns=False) #prepare query if recursion is needed: if isinstance(recursive, set): Q = True recursive.update(struct_letters) recursive.add(tn.lbase) else: Q = None #R holds recursive definition strings needed for obj R = [] #S holds obj title and fields declaration strings #we need obj.identifier here and not tn.show() because #template specialization need to keep the template string. S = [u'%s%s {' % (obj.identifier, obj.base_specifier_list())] #P holds lists for each public/protected/private/friend members P = {'': [], 'PUBLIC': [], 'PROTECTED': [], 'PRIVATE': []} #now, iterate through all fields: for (x, y, z) in obj: qal, t = x # parent/virtual qualifier & type mn, n = y # mangled name & name p, c = z # public/protected/private & comment if qal == 'parent': r = cxx_type(n) e = r.lbase if Q and (e not in recursive): q = (where('id') == e) x = obj.from_db(db.get(q)).show(db, recursive, form='C') R.append(x) recursive.add(e) continue elif qal == 'using': what = '::'.join((cxx_type(u).show_base() for u in t)) using = ' using %s' % what using += '::%s;' % n if n != namespace else ';' S.append(using) continue elif qal.startswith('template<'): P[p].append(' ' + qal) qal = '' #decompose C-type t into specific parts: r = cxx_type(t) #get "element base" part of type t: e = r.lbase #is t a nested class ? nested = r.ns.split('::')[-1].startswith(namespace) #is t a nested enum ? nested |= e.startswith('enum ?_') #query field element raw base type if needed: if Q and ((e not in recursive) or nested): #prepare query q = (where('id') == e) #deal with nested type: if nested: q &= (where('src') == tn.lbase) if db.contains(q): #retreive the field type: x = obj.from_db(db.get(q)) x = x.show(db, recursive, form='C') if not nested: #if not nested, insert it directly in R R.append(x) recursive.add(e) else: x = x.replace('%s::' % namespace, '') # nested struct/union/class: we need to transfer # any predefs into R x = x.split('\n\n') r.lbase = x.pop().replace('\n', '\n ').strip(';') if len(x): xr = x[0].split('\n') for xrl in xr: if xrl and xrl not in R: R.append(xrl) else: secho('identifier %s not found' % r.lbase, fg='red', err=True) #finally add field type and name to the structure lines: fo = '' if qal: if ',' in qal: qal, fo = qal.split(',') qal = '%s ' % qal P[p].append(u' {}{}{};'.format(qal, r.show(n, kw=nested), fo)) # access specifier (empty is for friend members): for p in ('PUBLIC', 'PROTECTED', 'PRIVATE', ''): if len(P[p]) > 0: if p: S.append(' %s:' % p.lower()) for v in P[p]: S.append(v) #join R and S: if len(R) > 0: R.append('\n') S.append('};') return '\n'.join(R) + '\n'.join(S)