Synopsis - Cross-Reference
File: Synopsis/Parsers/IDL/omni.py1# 2# Copyright (C) 2000 Stefan Seefeld 3# All rights reserved. 4# Licensed to the public under the terms of the GNU LGPL (>= 2), 5# see the file COPYING for details. 6# 7 8from Synopsis import IR, ASG 9from Synopsis.QualifiedName import QualifiedCxxName as QName 10from Synopsis.SourceFile import * 11import idlast, idltype, idlvisitor, idlutil 12import _omniidl 13import sys, getopt, os, os.path, string, types 14 15sourcefile = None 16 17def strip_filename(filename): 18 "This is aliased as strip if -b used and basename set" 19 20 if len(basename) > len(filename): return filename 21 if filename[:len(basename)] == basename: 22 return filename[len(basename):] 23 return filename 24 25class TypeTranslator(idlvisitor.TypeVisitor): 26 """maps idltype objects to ASG.TypeId objects in a ASG.Dictionary""" 27 28 def __init__(self, types): 29 self.types = types 30 self.__result = None 31 self.__basetypes = {idltype.tk_void: QName(('void',)), 32 idltype.tk_short: QName(('short',)), 33 idltype.tk_long: QName(('long',)), 34 idltype.tk_ushort: QName(('unsigned short',)), 35 idltype.tk_ulong: QName(('unsigned long',)), 36 idltype.tk_float: QName(('float',)), 37 idltype.tk_double: QName(('double',)), 38 idltype.tk_boolean: QName(('boolean',)), 39 idltype.tk_char: QName(('char',)), 40 idltype.tk_octet: QName(('octet',)), 41 idltype.tk_any: QName(('any',)), 42 idltype.tk_TypeCode: QName(('CORBA','TypeCode',)), 43 idltype.tk_Principal: QName(('CORBA','Principal',)), 44 idltype.tk_longlong: QName(('long long',)), 45 idltype.tk_ulonglong: QName(('unsigned long long',)), 46 idltype.tk_longdouble: QName(('long double',)), 47 idltype.tk_wchar: QName(('wchar',))} 48 49 def internalize(self, idltype): 50 51 idltype.accept(self) 52 return self.__result 53 54 def has_key(self, name): return self.types.has_key(name) 55 56 def add(self, name, type): 57 self.types[name] = type 58 59 def get(self, name): 60 return self.types[name] 61 62 def visitBaseType(self, idltype): 63 64 type = ASG.BuiltinTypeId('IDL', self.__basetypes[idltype.kind()]) 65 self.types[type.name] = type 66 self.__result = type.name 67 68 def visitStringType(self, idltype): 69 70 # FIXME: Should we create a ParametrizedTypeId with the appropriate bound parameters ? 71 if idltype.bound() == 0: 72 qname = QName(('string',)) 73 else: 74 qname = QName(('string<%s>'%idltype.bound(),)) 75 if qname not in self.types: 76 self.types[qname] = ASG.BuiltinTypeId('IDL', qname) 77 self.__result = qname 78 79 def visitWStringType(self, idltype): 80 81 # FIXME: Should we create a ParametrizedTypeId with the appropriate bound parameters ? 82 if idltype.bound() == 0: 83 qname = QName(('wstring',)) 84 else: 85 qname = QName(('wstring<%s>'%idltype.bound(),)) 86 if qname not in self.types: 87 self.types[qname] = ASG.BuiltinTypeId('IDL', qname) 88 self.__result = qname 89 90 def visitSequenceType(self, idltype): 91 92 qname = QName(('sequence',)) 93 if not self.types.has_key(qname): 94 self.types[qname] = ASG.BuiltinTypeId("IDL", qname) 95 idltype.seqType().accept(self) 96 ptype = self.types[self.__result] 97 type = ASG.ParametrizedTypeId("IDL", self.types[qname], [ptype]) 98 qname = QName(('sequence<%s>'%str(ptype.name),)) 99 self.types[qname] = type 100 self.__result = qname 101 102 def visitDeclaredType(self, idltype): 103 104 self.__result = QName(idltype.decl().scopedName()) 105 106class ASGTranslator(idlvisitor.AstVisitor): 107 108 def __init__(self, declarations, types, primary_file_only): 109 110 self.declarations = declarations 111 self.primary_file_only = primary_file_only 112 self.types = types 113 self.__scope = [] 114 self.__operation = None 115 self.__enum = None 116 117 def scope(self): return self.__scope[-1].name 118 119 def add_declaration(self, declaration): 120 self.__scope[-1].declarations.append(declaration) 121 122 def addType(self, name, type): 123 124 if self.types.has_key(name): 125 if isinstance(self.types.get(name), ASG.UnknownTypeId): 126 self.types.add(name, type) 127 else: 128 pass 129 return 130 self.types.add(name, type) 131 132 def getType(self, name): return self.types.get(QName(name)) 133 def visitAST(self, node): 134 135 self.__scope.append(ASG.Scope(sourcefile, 0, 'file', QName())) 136 # add an 'Object' Type to the Type Dictionary. Don't declare it in the ASG since 137 # there is no corresponding declaration 138 qname = QName(('CORBA', 'Object')) 139 object = ASG.Class(sourcefile, 0, 'interface', qname) 140 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, object)) 141 for n in node.declarations(): 142 n.accept(self) 143 for d in self.__scope[-1].declarations: 144 self.declarations.append(d) 145 146 def visitModule(self, node): 147 148 visible = node.mainFile() or not self.primary_file_only 149 qname = QName(list(self.scope()) + [node.identifier()]) 150 module = ASG.Module(sourcefile, node.line(), 'module', qname) 151 if visible: 152 self.add_declaration(module) 153 self.__scope.append(module) 154 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, module)) 155 if not self.primary_file_only or node.mainFile(): 156 comments = [c.text() for c in node.comments()] 157 if comments: 158 module.annotations['comments'] = comments 159 for n in node.definitions(): 160 n.accept(self) 161 self.__scope.pop() 162 163 def visitInterface(self, node): 164 165 visible = node.mainFile() or not self.primary_file_only 166 qname = QName(list(self.scope()) + [node.identifier()]) 167 class_ = ASG.Class(sourcefile, node.line(), 'interface', qname) 168 if visible: 169 self.add_declaration(class_) 170 self.__scope.append(class_) 171 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, class_)) 172 if not self.primary_file_only or node.mainFile(): 173 comments = [c.text() for c in node.comments()] 174 if comments: 175 class_.annotations['comments'] = comments 176 for i in node.inherits(): 177 parent = self.getType(i.scopedName()) 178 class_.parents.append(ASG.Inheritance("", parent, [])) 179 for c in node.contents(): c.accept(self) 180 self.__scope.pop() 181 182 def visitForward(self, node): 183 184 visible = node.mainFile() or not self.primary_file_only 185 name = list(self.scope()) 186 qname = QName(name + [node.identifier()]) 187 forward = ASG.Forward(sourcefile, node.line(), 'interface', qname) 188 if visible: 189 self.add_declaration(forward) 190 self.addType(qname, ASG.UnknownTypeId('IDL', qname)) 191 192 def visitConst(self, node): 193 194 visible = node.mainFile() or not self.primary_file_only 195 name = list(self.scope()) 196 qname = QName(name + [node.identifier()]) 197 type = self.types.internalize(node.constType()) 198 if node.constType().kind() == idltype.tk_enum: 199 value = "::" + idlutil.ccolonName(node.value().scopedName()) 200 else: 201 value = str(node.value()) 202 const = ASG.Const(sourcefile, node.line(), 'const', 203 self.getType(type), qname, value) 204 if visible: 205 self.add_declaration(const) 206 comments = [c.text() for c in node.comments()] 207 if comments: 208 const.annotations['comments'] = comments 209 210 def visitTypedef(self, node): 211 212 visible = node.mainFile() or not self.primary_file_only 213 # if this is an inline constructed type, it is a 'Declared' type 214 # and we need to visit the declaration first 215 if node.constrType(): 216 node.aliasType().decl().accept(self) 217 type = self.types.internalize(node.aliasType()) 218 comments = [c.text() for c in node.comments()] 219 for d in node.declarators(): 220 # reinit the type for this declarator, as each declarator of 221 # a single typedef declaration can have a different type. *sigh* 222 dtype = type 223 if d.sizes(): 224 array = ASG.ArrayTypeId('IDL', self.getType(type), [str(s) for s in d.sizes()]) 225 dtype = map(None, type[:-1]) 226 dtype.append(type[-1] + string.join(map(lambda s:"["+ str(s) +"]", d.sizes()),'')) 227 self.addType(QName(dtype), array) 228 name = list(self.scope()) 229 qname = QName(name + [d.identifier()]) 230 typedef = ASG.Typedef(sourcefile, node.line(), 'typedef', qname, self.getType(dtype), node.constrType()) 231 d_comments = comments + [c.text() for c in d.comments()] 232 if d_comments: 233 typedef.annotations['comments'] = d_comments 234 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, typedef)) 235 if visible: 236 self.add_declaration(typedef) 237 238 def visitMember(self, node): 239 240 visible = node.mainFile() or not self.primary_file_only 241 # if this is an inline constructed type, it is a 'Declared' type 242 # and we need to visit the declaration first 243 if node.constrType(): 244 node.memberType().decl().accept(self) 245 type = self.types.internalize(node.memberType()) 246 comments = [c.text() for c in node.comments()] 247 for d in node.declarators(): 248 # reinit the type for this declarator, as each declarator of 249 # a single typedef declaration can have a different type. *sigh* 250 dtype = type 251 if d.sizes(): 252 array = ASG.ArrayTypeId('IDL', self.getType(type), [str(s) for s in node.sizes()]) 253 dtype = type[:-1] 254 dtype.append(type[-1] + string.join(map(lambda s:"["+s+"]", d.sizes()),'')) 255 self.addType(dtype, array) 256 qname = QName(list(self.scope()) + [d.identifier()]) 257 member = ASG.Variable(sourcefile, node.line(), 'variable', qname, self.getType(dtype), node.constrType()) 258 d_comments = comments + [c.text() for c in d.comments()] 259 if d_comments: 260 member.annotations['comments'] = d_comments 261 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, member)) 262 if visible: 263 self.add_declaration(member) 264 265 def visitStruct(self, node): 266 267 visible = node.mainFile() or not self.primary_file_only 268 qname = QName(list(self.scope()) + [node.identifier()]) 269 if self.primary_file_only and not node.mainFile(): 270 forward = ASG.Forward(sourcefile, node.line(), 'struct', qname) 271 if visible: 272 self.add_declaration(forward) 273 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, forward)) 274 return 275 struct = ASG.Class(sourcefile, node.line(), 'struct', qname) 276 if visible: 277 self.add_declaration(struct) 278 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, struct)) 279 comments = [c.text() for c in node.comments()] 280 if comments: 281 struct.annotations['comments'] = comments 282 self.__scope.append(struct) 283 for member in node.members(): member.accept(self) 284 self.__scope.pop() 285 286 def visitException(self, node): 287 288 visible = node.mainFile() or not self.primary_file_only 289 qname = QName(list(self.scope()) + [node.identifier()]) 290 if self.primary_file_only and not node.mainFile(): 291 forward = ASG.Forward(sourcefile, node.line(), 'exception', qname) 292 if visible: 293 self.add_declaration(forward) 294 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, forward)) 295 return 296 exc = ASG.Class(sourcefile, node.line(), 'exception', qname) 297 if visible: 298 self.add_declaration(exc) 299 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, exc)) 300 self.__scope.append(exc) 301 comments = [c.text() for c in node.comments()] 302 if comments: 303 exc.annotations['comments'] = comments 304 for member in node.members(): member.accept(self) 305 self.__scope.pop() 306 307 # def visitCaseLabel(self, node): return 308 309 def visitUnionCase(self, node): 310 311 # if this is an inline constructed type, it is a 'Declared' type 312 # and we need to visit the declaration first 313 if node.constrType(): 314 node.caseType().decl().accept(self) 315 type = self.types.internalize(node.caseType()) 316 declarator = node.declarator() 317 if declarator.sizes(): 318 array = ASG.ArrayTypeId('IDL', self.getType(type), [str(s) for s in declarator.sizes()]) 319 type = type[:-1] 320 type.append(type[-1] + string.join(map(lambda s:"["+s+"]",node.sizes()),'')) 321 self.addType(type, array) 322 qname = QName(list(self.scope()) + [node.declarator().identifier()]) 323 self.__scope[-1].declarations.append( 324 ASG.Operation(sourcefile, node.line(), 'case', 325 [], self.getType(type), [], qname, qname[-1])) 326 327 def visitUnion(self, node): 328 329 visible = node.mainFile() or not self.primary_file_only 330 qname = QName(list(self.scope()) + [node.identifier()]) 331 if self.primary_file_only and not node.mainFile(): 332 forward = ASG.Forward(sourcefile, node.line(), 'union', qname) 333 if visible: 334 self.add_declaration(forward) 335 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, forward)) 336 return 337 class_ = ASG.Class(sourcefile, node.line(), 'union', qname) 338 self.add_declaration(class_) 339 self.__scope.append(class_) 340 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, class_)) 341 comments = [c.text() for c in node.comments()] 342 if comments: 343 class_.annotations['comments'] = comments 344 for c in node.cases(): c.accept(self) 345 self.__scope.pop() 346 347 def visitEnumerator(self, node): 348 349 qname = QName(list(self.scope()) + [node.identifier()]) 350 enum = ASG.Enumerator(sourcefile, node.line(), qname, '') 351 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, enum)) 352 self.__enum.enumerators.append(enum) 353 354 def visitEnum(self, node): 355 356 visible = node.mainFile() or not self.primary_file_only 357 qname = QName(list(self.scope()) + [node.identifier()]) 358 if self.primary_file_only and not node.mainFile(): 359 forward = ASG.Forward(sourcefile, node.line(), 'enum', qname) 360 if visible: 361 self.add_declaration(forward) 362 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, forward)) 363 return 364 self.__enum = ASG.Enum(sourcefile, node.line(), qname, []) 365 if visible: 366 self.add_declaration(self.__enum) 367 self.addType(qname, ASG.DeclaredTypeId('IDL', qname, self.__enum)) 368 comments = [c.text() for c in node.comments()] 369 if comments: 370 self.__enum.annotations['comments'] = comments 371 for enumerator in node.enumerators(): enumerator.accept(self) 372 self.__enum = None 373 374 def visitAttribute(self, node): 375 376 visible = node.mainFile() or not self.primary_file_only 377 scopename = list(self.scope()) 378 if self.primary_file_only and not node.mainFile(): return 379 # Add real Operation objects 380 pre = [] 381 if node.readonly(): pre.append("readonly") 382 type = self.types.internalize(node.attrType()) 383 comments = [c.text() for c in node.comments()] 384 for id in node.identifiers(): 385 qname = QName(scopename + [id]) 386 attr = ASG.Operation(sourcefile, node.line(), 'attribute', 387 pre, self.getType(type), [], qname, qname[-1]) 388 if comments: 389 attr.annotations['comments'] = comments 390 if visible: 391 self.add_declaration(attr) 392 393 def visitParameter(self, node): 394 395 operation = self.__operation 396 pre = [] 397 if node.direction() == 0: pre.append("in") 398 elif node.direction() == 1: pre.append("out") 399 else: pre.append("inout") 400 post = [] 401 name = self.types.internalize(node.paramType()) 402 operation.parameters.append(ASG.Parameter(pre, self.getType(name), post, node.identifier())) 403 404 def visitOperation(self, node): 405 406 visible = node.mainFile() or not self.primary_file_only 407 pre = [] 408 if node.oneway(): pre.append("oneway") 409 return_type = self.types.internalize(node.returnType()) 410 qname = QName(list(self.scope()) + [node.identifier()]) 411 self.__operation = ASG.Operation(sourcefile, node.line(), 'operation', pre, self.getType(return_type), [], qname, qname[-1]) 412 comments = [c.text() for c in node.comments()] 413 if comments: 414 self.__operation.annotations['comments'] = comments 415 for p in node.parameters(): p.accept(self) 416 for e in node.raises(): 417 exception = self.getType(e.scopedName()) 418 self.__operation.exceptions.append(exception) 419 420 if visible: 421 self.add_declaration(self.__operation) 422 self.__operation = None 423 424# def visitNative(self, node): return 425# def visitStateMember(self, node): return 426# def visitFactory(self, node): return 427# def visitValueForward(self, node): return 428# def visitValueBox(self, node): return 429# def visitValueAbs(self, node): return 430# def visitValue(self, node): return 431 432def parse(ir, cppfile, src, primary_file_only, 433 base_path, verbose, debug): 434 global basename, strip, sourcefile 435 436 if base_path: 437 basename = base_path 438 439 _omniidl.keepComments(1) 440 _omniidl.noForwardWarning() 441 tree = _omniidl.compile(open(cppfile, 'r+')) 442 if tree == None: 443 sys.stderr.write("omni: Error parsing %s\n"%cppfile) 444 sys.exit(1) 445 446 sourcefile = SourceFile(strip_filename(src), src, 'IDL') 447 sourcefile.annotations['primary'] = True 448 new_ir = IR.IR() 449 new_ir.files[sourcefile.name] = sourcefile 450 type_trans = TypeTranslator(new_ir.asg.types) 451 ast_trans = ASGTranslator(new_ir.asg.declarations, type_trans, primary_file_only) 452 tree.accept(ast_trans) 453 sourcefile.declarations[:] = new_ir.asg.declarations 454 ir.merge(new_ir) 455 _omniidl.clear() 456 return ir 457
Generated on Tue May 13 02:39:21 2008 by
synopsis (version 0.10)
synopsis (version 0.10)