Example #1
0
 def change(self):
     """change component SIDL_SYMBOL options
     """
     project,graph = Globals().getProjectAndGraph(self.projectName)
     
     # delete uses or provides port
     if self.options.deletePortName:
         allmyports = [x.getName() for x in self._b_provides + self._b_uses]
         for p in self.options.deletePortName:
             if p not in allmyports:
                 err('There is not port named ' + p + ' in this component.')
     
         for pname in self.options.deletePortName:
             for theport in self._b_uses + self._b_provides:
                 if pname == theport.getName():
                     # TODO: Make sure this port is not in the implements or provides list under more than one name 
                     # before deleting the type
                     ptype = theport.getType()
                     if [x.getType()==ptype for x in self._b_uses + self._b_provides].count(True) + self._b_implements.keys().count(ptype) <= 0:
                         # remove edge
                         self.removeInEdge(ptype, kind = 'port', graph=graph)
                         if location == '%external%':
                             # Remove external file name in project defaults file
                             if not self._findExternal(ptype): project.removeDefaultValue(ptype,'External')
                             print >>DEBUGSTREAM, 'Removed external port or interface: ' + ptype
                             if ptype in self._b_externalSidlFiles.keys(): del self._b_externalSidlFiles[ptype]   
                     try: 
                         if theport in self._b_uses: self._b_uses.remove(theport)
                         elif theport in self._b_provides: self._b_provides.remove(theport)
                     except: err('Could not remove port %s, port not used or provided in component %s' % (pname, self.symbol))     
         
     # Let class handle everything it can (it also calls the builder update method)
     Sidlclass.change(self)
     return 0
Example #2
0
    def parseFile(self, filename, stripBocca=False):
        '''
        Parse the file and return an AST object
        '''
        if not os.path.exists(filename):
            err('[SIDL parser] file not found: ' + filename)
        self.filename = filename
        f = file(filename)
        s = f.read()
        f.close()
        # Strip bocca splice delimiters and protected blocks from old text
        if (stripBocca):
            lineList = s.split('\n')
            noBoccaList = [ l for l in lineList if l.find('DO-NOT-DELETE bocca.splicer.') == -1]
            inProtected=False
            noBlockList=[]
            for l in noBoccaList:
                if inProtected:
                    if l.find("DO-NOT-DELETE bocca.protected.end") != -1:
                        inProtected = False
                    continue
                else:
                    if l.find("DO-NOT-DELETE bocca.protected.begin") != -1:
                        inProtected = True
                        continue
                noBlockList.append(l)

            if inProtected:
                err('[SIDL parser] unterminated bocca.protected block in input.')
                
            s = '\n'.join(noBlockList)
        return self.parse(s)
Example #3
0
 def loadFile(self, input, key, preserveProtected=False):
     """Load a file as a set of blocks chunked up by key. returns (0, "ok") or (1, "errmsg"). If you don't have a file but have a list of lines, use loadList instead. """
     self.fin = input
     self.nsplices = 0
     try:
         f = fileManager.open(input, 'r')
         lines = f.readlines()
         f.close()
     except IOError, e:
         err('Error loading file ' + str(input) + '(' +  str(e) +')' )
Example #4
0
    def writeString(self, outFileName, verbose=False, rejectSave=True, rejectFileName="", rejectLines =[]):
        """return string representation of file for other's to output. outFileName is used to write rejects if specified or to issue error messages.
@return (status, resultString) where if status is True, string will be valid and if false, the input
source was apparently empty."""
        fname = outFileName
        writeRejects = (rejectSave and rejectLines != None)
        if writeRejects:
            rname = fname + ".rej"
            if len(rejectFileName) > 0:
                rname = rejectFileName
        if self.nsplices < 1:
            if verbose:
                print "Nothing new to write to ", fname
            if self.num < 1:
                print "Nothing old to copy to ", fname
                print "Reading ", self.fin, " failed?" 
                return (False, "")
        if verbose:
            if writeRejects:
                print "Writing rejects to ", rname
            print "Writing to string for ", fname
        if True: 
            outlist = []
            if writeRejects:
                try:
                    rejfile = fileManager.open(rname,"w")
                except:
                    err('splicer could not open rejects file for writing: ' + rname)
            for i in self.sections:
                isProtected = False
                for s in self.protectedSymbols:
                    if i == self.getProtectedBlock(s):
                        isProtected = True
                        break
                if isProtected:
                    continue
                lines = i.getLines() 
                for p in lines:
                    outlist.append( p.strip("\n") )
            stringified = "\n".join(outlist)
            if writeRejects:
                date = Line.stringdate()
                print >> rejfile, "#FROM %s on %s" % (fname, date)
                for p in rejectLines:
                    print >> rejfile , p.strip("\n")
            if verbose:
                if writeRejects:
                    print " Finished ", rname
                print " Finished ", fname
            return (True, stringified)
        else:
            print "Error writing for "+ fname
            return (False, "")
Example #5
0
    def __init__(self, modulePath, project):
        '''Constructor
        Must be called from every derived plugin before rest of plugin's init.
        @param modulePath the directory containing the implementation of the BuilderInterface
        '''
        if str(project.__class__) != 'project.Project':
            err("Builder plugin: invoking update on a vertex that is not a Project: " + str(project.__class__))

        self.project = project      
        # Load the local LocationManagerInterface implementation
        try:
            (file,filename,description) = imp.find_module('locations',[modulePath])
            locations = imp.load_module('locations', file, filename, description)
        except ImportError,e:
            err('Builder: Could not import locations module from ' + modulePath + ': ' + str(e))
Example #6
0
 def writeRejects(self, rejectFileName, rejectLines='', originalFile='', verbose=False, dryrun=False):
     if len(rejectLines) == 0:
         print "No rejection information to put into " + rejectFileName
         return False
     if dryrun:
         print "Dry run: Not writing to " + rejectFileName
         # For a dry run, don't do anything
         return True
     if verbose:
         print "Writing rejects to: " + rejectFileName
     outfile = None
     try:
         outfile = fileManager.open(rejectFileName,'w')
     except IOError, e:
         err('splicer could not open reject file %s for writing: %s' % (rejectFileName, str(e)))
Example #7
0
    def write(self, outFileName, verbose=False, dryrun=False, rejectSave=True, rejectFileName="", rejectLines =[]):
        """return true if succeeds writing to output file named."""
        fname = outFileName
        writeRejects = (rejectSave and rejectLines != None and len(rejectLines) > 0)
        if writeRejects:
            rname = fname + ".rej"
            if len(rejectFileName) > 0:
                rname = rejectFileName
        if self.nsplices < 1:
            if verbose:
                print "Nothing new to write to ", fname
            if self.num < 1:
                print "Nothing old to copy to ", fname
                print "Reading ", self.fin, " failed?" 
                return False
        if dryrun:
            return True
        if True: 
            outfile = None
            try:
                outfile = fileManager.open(fname,"w")
            except IOError,e:
                err('splicer could not open file for writing: ' + fname + '; ' + str(e))
            for i in self.sections:
                # Kludge to get around printing protected symbols in the merged file.
                isProtected = False
                for s in self.protectedSymbols:
                    if i == self.getProtectedBlock(s):
                        isProtected=True
                        break
                if isProtected:
                    continue

                lines = i.getLines()
                # print "writing section ", i.key(), " len = ", len(lines)
                for p in lines:
                    print >> outfile, "%s" % p.strip("\n")
            if writeRejects:
                if not self.writeRejects(rname, rejectLines, originalFile=outFileName, verbose=verbose, dryrun=dryrun):
                    return False
            if verbose:
                if writeRejects:
                    print " Finished ", rname
                print " Finished ", fname

            outfile.close()
            return True
Example #8
0
    def visitEnumeration(self, node):
        if self.parentVertex.kind in ['package','project','enum']:
            parentid = node.getParent().getFullIdentifier()
            id = node.getFullIdentifier()

            if self.matchPartialSymbols(id, self.symbols) or self.doAll:
                shortId = node.getIdentifier()
                if parentid in self.packages.keys():
                    pVertex = self.packages[parentid]
                else:
                    if self.parentVertex.kind not in ['package', 'project', 'enum']:
                        err('Enums can only be imported into Bocca packages')
                    pVertex = self.parentVertex
                    
                newId = pVertex.symbol + '.' + shortId
                if self.parentVertex.kind == 'project': 
                    newId = id
                slist = self.graph.findSymbol(newId, kind='any')
                if len(slist) == 1 and slist[0].kind == 'enum':
                    enum = slist[0]
                    enum.setASTNode(node)
                elif not slist:    
                    if self.parentVertex.kind != 'enum':
                        enum = cct.enum.Enum(action='create', args=[newId], version=pVertex.version, project=self.project,
                                             modulePath=self.project.modulePath, graph=self.graph)
                    else:
                        enum = self.parentVertex
                    
                    enum.setASTNode(node)
                    if len(node.getContents()): 
                        enum.genDummy = False
                    if self.parentVertex.kind != 'enum': 
                        enum.create()
                    comment = node.getStartComment()
                    if comment: enum.setComment(comment)
                else:
                    self._symbolConflictError(slist)
                edge = BEdge(pVertex, enum, self.graph, action='contains')
                self.enums[id] = enum

        self.visitVertex(node)
        pass        
Example #9
0
 def portArgsToDict(self, arg):
     """ Return dictionary of port arguments, where 
         Dictionary keys = Port Names
         Dictionary entries = Port Types
     """
     # Make sure we have a unified list of portType:portName pairs, possible
     # derived from multiple sub-lists on the command line
     # TODO: Check whether this way of specifying oprt arguments is too flexible.
     argList = ','.join(arg).split(',')
     d = {}
     for p in argList:
         l = p.split(':')
         if (len(l)!= 2):
             err("Invalid port specification : " + p +"\nPort specification of the form portType:portnAME", 2)
         if l[1] in d.keys():
             err("Duplicate specification of port name \"", p[1], "\"", 2)
         print >> DEBUGSTREAM, "port name = ", l[1]
         print >> DEBUGSTREAM, "port type = ", l[0]
         d[l[1]] = l[0]
     return d    
Example #10
0
 def defineArgs(self, action):
     '''Defines command line options and defaults for this command. This is 
        invoked in the constructor of the parent class Subcommand.
     '''
     if (action == 'create'):
         self.defineArgsCreate()
     elif action == 'copy':
         Sidlclass.defineArgsCopy(self)
     elif action == 'rename':
         pass
     elif action == 'display':
         Sidlclass.defineArgs(self, action)
     elif action == 'change':
         self.defineArgsChange()
     elif action == 'edit' or action == 'whereis':
         Sidlclass.defineArgs(self, action)
     elif action == 'remove':
         Sidlclass.defineArgsRemove(self)
     else:
         err('Component verb "' + action + '" NOT implemented yet.', 3)
     return
Example #11
0
    def visitInterface(self,node):
        if self.parentVertex.kind in ['package','project']:
            parentid = node.getParent().getFullIdentifier()
            id = node.getFullIdentifier()
            if self.matchPartialSymbols(id, self.symbols) or self.doAll:
                shortId = node.getIdentifier()
                if parentid in self.packages.keys():
                    pVertex = self.packages[parentid]
                else:
                    if self.parentVertex.kind not in ['project','package']:
                        err('Interfaces can only be imported into Bocca packages')
                    pVertex = self.parentVertex
                    
                newId = pVertex.symbol + '.' + shortId
                if self.parentVertex.kind == 'project': 
                    newId = id
                slist = self.graph.findSymbol(newId,kind='any')
                if len(slist) == 1 and slist[0].kind in ['interface','port']:
                    interface = slist[0]
                    interface.setASTNode(node)
                elif not slist:    
                    if 'gov.cca.Port' in node.getParentIds():
                        interface = cct.port.Port(action='create', args=[newId], version=pVertex.version, project=self.project, 
                                                  modulePath=self.project.modulePath, graph=self.graph)
                    else:
                        interface = cct.interface.Interface(action='create', args=[newId], version=pVertex.version, project=self.project, 
                                                            modulePath=self.project.modulePath, graph=self.graph)
                    
                    interface.setASTNode(node)
                    interface.create()
                    comment = node.getStartComment()
                    if comment: interface.setComment(comment)
                    self.methods[newId]=[]
                else:
                    self._symbolConflictError(slist)
                edge = BEdge(pVertex, interface, self.graph, action='contains')
                self.interfaces[id] = interface

        self.visitVertex(node)
        pass
Example #12
0
    def visitClass(self,node):
        if self.parentVertex.kind in ['package','project']:
            parentid = node.getParent().getFullIdentifier()
            id = node.getFullIdentifier()
            if self.matchPartialSymbols(id, self.symbols) or self.doAll:
                shortId = node.getIdentifier()
                if parentid in self.packages.keys():
                    pVertex = self.packages[parentid]
                else:
                    if self.parentVertex.kind not in ['project','package']:
                        err('Classes can only be imported into Bocca packages')
                    pVertex = self.parentVertex
    
                newId = pVertex.symbol + '.' + shortId
                if self.parentVertex.kind == 'project': 
                    newId = id
                slist = self.graph.findSymbol(newId,kind='any')
                if len(slist) == 1 and slist[0].kind in ['class','component']:
                    klass = slist[0]
                    klass.setASTNode(node)
                elif not slist:
                    if 'gov.cca.Component' in [p.getIdentifier() for p in node.getInterfacesAll()]:
                        klass = cct.component.Component(action='create', args=[newId], version=pVertex.version, project=self.project, 
                                                        modulePath=self.project.modulePath, graph=self.graph)
                    else:
                        klass = cct.sidlclass.Sidlclass(action='create', args=[newId], version=pVertex.version, project=self.project, 
                                                        modulePath=self.project.modulePath, graph=self.graph)
                    klass.setASTNode(node)
                    klass.create()
                    comment = node.getStartComment()
                    if comment: klass.setComment(comment)
                    self.methods[newId]=[]
                else:
                    self._symbolConflictError(slist)

                edge = BEdge(pVertex, klass, self.graph, action='contains')
                self.classes[id] = klass
                    
        self.visitVertex(node)
        pass
Example #13
0
    def visitMethod(self,node):
        parent = node.getParent()
        if parent is None: print 'parent is None'
        if parent:
            parentid = parent.getFullIdentifier()
            if self.matchPartialSymbols(parentid, self.symbols)  or self.doAll:
                if self.parentVertex.kind in ['package','project'] and self.matchPartialSymbols(parentid, self.interfaces.keys()):
                    symbol = self.interfaces[parentid].symbol
                elif self.parentVertex.kind in ['package','project'] and self.matchPartialSymbols(parentid, self.classes.keys()):
                    symbol = self.classes[parentid].symbol
                elif self.parentVertex.kind in ['interface', 'port', 'class', 'component']:
                    symbol = self.parentVertex.symbol
                else:
                    err('cannot import methods into a ' + self.parentVertex.kind + ' (only into project, package, interface, port, class, or component)')
                        
                if not self.methods.has_key(symbol): self.methods[symbol]=[]
                if node not in self.methods[symbol]:
                    print >>DEBUGSTREAM,'adding method ' + node.getIdentifier() + ' to ' + symbol 
                    self.methods[symbol].append(node)

        self.visitVertex(node)
        pass
Example #14
0
 def processArgs(self, action):
     """ Dispatch argument processing based in required action
     """
     print >> DEBUGSTREAM, "Component called with options ", \
                           str(self.options) , " leaving args " , str(self.args)
     if (action == 'create'):
         self.processCreateArgs()
     elif (action == 'change'):
         self.processChangeArgs()
     elif (action == 'display'):
         Sidlclass.processDisplayArgs(self)
     elif (action == 'rename'):
         self.processRenameArgs()
     elif (action == 'edit' or action == 'whereis'):
         Sidlclass.processArgs(self, action)
     elif (action == 'remove'):
         Sidlclass.processRemoveArgs(self)
     elif (action == 'copy'):
         Sidlclass.processCopyArgs(self)
     else:
         err("Action "+ action + " NOT implemented yet", 3)
     return
Example #15
0
def go_option_callback(option, opt, value, parser):
    """ handler for --go[=portname]. There is an auxiliary value GoPortStatus which is 0
if the user did not apply --go during the current invocation. This needs to get stored
in the permanent data structure eventually. This allows us to differentiate a user specified
go port (-p) and a generated goport prototype --go. The expected values of GoPortStatus are:
0: --go never appeared. If goport is found, came from -p.
1: --go appeared and a default go impl should be generated.
2: [future] --go-done. We used --go before, but future updates if uses list changes
   should be suppressed.
3: [future] --go-delegate=portname[:delegateclass] delegated goport instead of inherited.
"""
    if opt == "--go" or opt == "-g":
        porttype="gov.cca.ports.GoPort"
        if value == None or len(value) < 1 :
            portname="GO"
        else:
            portname=value
        if parser.values.providesPort == None:
            parser.values.providesPort=[]
        if portname[0] == '-':
            err("--go needs an argument. Got another switch.", 2)
        parser.values.providesPort.append(porttype+"@"+portname)
        parser.values.GoPortStatus=1
Example #16
0
    def processCommonCreateAndChangeArgs(self):
        print >>DEBUGSTREAM, "component: processCommonCreateAndChangeArgs"
        options, args = self.options, self.args

        # print "UH_component:processCommonCreateAndChangeArgs"
        # dpathdata = self._processDpathOptions()
        # self._updateDpaths(dpathdata)

        # relocatd base call from end of method.
        Sidlclass.processCommonCreateAndChangeArgs(self)

        if options.usesPort:
            self.newUses = self._processSymbolAssociationOptions(options.usesPort, '--uses/-u')
                
        if options.providesPort:
            self.newProvides = self._processSymbolAssociationOptions(options.providesPort, '--provides/-p')
            
        print >>DEBUGSTREAM, "\nComponent: newProvides = ", self.newProvides, \
                            "\nComponent: newUses = ", self.newUses

        for newp in self.newUses + self.newProvides:
            for p in [x.getName() for x in self._b_uses + self._b_provides]:
                if p == newp.getName():
                    err('This component already uses or provides a port of this name: ' + str(p) 
                           + ' (port names must be unique within a component),')
        for newp in self.newProvides:
            for i in [x.getType() for x in self._b_provides] + self._b_implements.keys():
                if i == newp.getType():
                    err('This component already implements this interface or provides a port of this type: ' + str(i))
                    
            if [x.getType() for x in self.newProvides].count(newp) > 1:
                err('A port cannot be provided more than once: ' + str(newp))
                            
        # relocating base call to beginning of method
        
        return
Example #17
0
 def t_error(self,t):
     col = self.find_column(t.lexer.lexdata,t)
     err("[SIDL parse] illegal character '%s' at line %s, column %s (%s)" % (t.value[0], t.lexer.lineno, col, str(t)))
     t.lexer.skip(1)
Example #18
0
 def _symbolConflictError(self, symlist):
     buf = ''
     for sym in symlist: 
         buf += str(sym) + ', '
     buf.rstrip(',')
     err('cannot import package into ' + self.parentVertex.symbol + ' due to a symbol conflict:\n' + buf)
Example #19
0
    def getBabelCommandString(self, vertex, checkSIDLOnly=False):
        '''Returns the string containing the complete babel invocation for generating
        client or server code for the specified vertex.
        
        @param vertex: the vertex correponding to the SIDL symbol for which code
                    will be generated by the constructed Babel command
        @param checkSIDLOnly: if True, do not generate code, just check the syntax of 
                    the SIDL definition corresponding to vertex.
        @return the Babel command string.
        '''
        if self.__class__ is BuilderDefault: raise NotImplementedError
        
        if vertex.kind not in ['interface', 'port', 'class', 'component', 'enum']: return ''
        if vertex.getAttr('removed'): return ''
        
        babelcmd = ''
        extra_babel_options = ''

        project, pgraph = Globals().getProjectAndGraph()
        ccaVars = Globals().getCCAVars()
        if len(ccaVars) == 0:
            err('[sidlclass] could not load CCA settings from defaults file')

        sidlIncludes = Set()
        if vertex.kind in ['port', 'component']:
            sidlIncludes.add(Globals().getCCAVars(projectName=project.symbol)['CCA_sidl'])
       
        if vertex._b_xmlRepos: otherRepos = ' -R'.join([' '] + vertex._b_xmlRepos)
        else: otherRepos = ''
        
        # Keep a list of unique paths in inclpaths and check each new path against it before
        # adding an -I option for it (since Babel 1.0.8 crashes for duplicate paths), bocca issue 217
        inclpaths = []
        if vertex._b_externalSidlFiles: 
            extFiles = []
            for sym in vertex._b_externalSidlFiles.keys():
                files = vertex._getExternalSIDLPath(sym).split(',')
                if files:
                    for f in files:
                        fname = f.strip()
                        if fname and not fname in inclpaths: 
                            extFiles.append(fname)
                            inclpaths.append(fname)
            for f in extFiles: 
                sidlIncludes.add(f)
        
        extFiles = []
        for v in vertex.dependencies():

            if v.kind not in ['port', 'interface', 'component','class', 'enum']: continue
            if v.getAttr('removed'): continue
            
            thepath = ''
            if v.symbol.startswith('gov.cca'):
                sidlIncludes.add(Globals().getCCAVars(projectName=project.getName())['CCA_sidl'])
                continue
            if v._b_sidlFile:
                if not v._b_sidlFile.startswith(os.sep):
                    thepath = os.path.join(project.getDir(), v._b_sidlFile)
                else:
                    thepath = v._b_sidlFile
                if not thepath.strip() in inclpaths:
                    if thepath.strip():
                        sidlIncludes.add(thepath)
                        inclpaths.append(thepath)
            # Check for external SIDL files in 
            if v._b_externalSidlFiles: 
                extFiles = []
                for sym in v._b_externalSidlFiles.keys():
                    files = v._getExternalSIDLPath(sym).split(',')
                    if files:
                        for f in files:
                            if not f in inclpaths: 
                                extFiles.append(f)
                                inclpaths.append(f)
                for f in extFiles: sidlIncludes.add(f)
        
        if len(sidlIncludes) > 0:
            sidlIncludesString = ' -I'.join(sidlIncludes)
            sidlIncludesString = ' -I'+sidlIncludesString
        else:
            sidlIncludesString = ''
            
        print >>DEBUGSTREAM, 'SIDL files this class depends on:\n\t' \
                + sidlIncludesString \
                + '\n\texternal: ' + str(extFiles)
       
        if not ccaVars["CCASPEC_BABEL_BRANCH"].startswith('1.0'):
            extra_babel_options = ' --cca-mode --rename-splicers '
 
        if checkSIDLOnly and self.autochecksidl == 'enabled':

            babelcmd = '%s -p %s %s %s %s' % (ccaVars['CCASPEC_BABEL_BABEL'], \
                                              sidlIncludesString, otherRepos,
                                              extra_babel_options,
                                              os.path.join(project.getDir(), vertex._b_sidlFile))
            
        if vertex.kind in ['class','component']:
            if vertex.project: theproject = vertex.project
            else: theproject = project
            # Generate Impl files
            outdir = os.path.join(project.getDir(), 'components', vertex.symbol)
            babelOptions = '-s %s -u -m .%s. -o %s' % \
                   (vertex._b_language, vertex.symbol, outdir)
            print >> DEBUGSTREAM, 'Builder execute prep babelOptions: ' + babelOptions
            print >> DEBUGSTREAM, 'Builder execute prep sidlIncludesString: ' + sidlIncludesString
            babelcmd = '%s %s %s %s %s %s' % (ccaVars['CCASPEC_BABEL_BABEL'], babelOptions, 
                                              sidlIncludesString, otherRepos, extra_babel_options,
                                              os.path.join(theproject.getDir(), vertex._b_sidlFile))
   
        return babelcmd
Example #20
0
def p_error(t):
    line,col = find_column(t.lexer.lexdata,t)
    pos = (col-1)*' '
    err("[SIDL parsing] unexpected symbol '%s' at line %s, column %s:\n\t%s\n\t%s^" % (t.value, t.lexer.lineno, col, line, pos))
Example #21
0
    def getWriter (self, language, dialect, babelVersion='', kind = 'component'):
        ccaVars = Globals().getCCAVars()
        if len(ccaVars) == 0:
            err('[BoccaWriterFactory] could not load CCA settings from defaults file')
        if babelVersion is '': 
            # The CCASPEC_BABEL_VERSION has a timestamp instead of a version for nightly
            # tarballs, so call babel to determine version
            cmd = ccaVars['CCASPEC_BABEL_BABEL'] + ' --version'
            try:
                f = os.popen(cmd)
                lines = f.readlines()
                for l in lines:
                    cl = l.strip()
                    if cl.startswith('Babel version'): babelVersion = l.split()[-1]
            except:
                err('[BoccaWriterFactory] Could not determine Babel version')
                
        print >> DEBUGSTREAM, '[BoccaWriterFactory] Babel version is ' + str(babelVersion)
        
        # Handle nightly Babel tarballs, which don't have a regular version number
        if babelVersion.count('.') == 0:
            if 'CCASPEC_BABEL_SNAPSHOT' in ccaVars.keys():
                if ccaVars['CCASPEC_BABEL_SNAPSHOT'] == '1':
                    babelVersion = ccaVars['CCASPEC_BABEL_BRANCH']
        
        if babelVersion.count('.') == 0:
            # Sometimes the version number is in that variable, whether it's a snapshot or not
            if 'CCASPEC_BABEL_BRANCH' in ccaVars.keys():
                babelVersion = ccaVars['CCASPEC_BABEL_BRANCH']

        if babelVersion.count('.') == 0:
            err('[BoccaWriterFactory] Invalid Babel version encountered')

        for key in self.writers.keys():
            (lang, versionList, dial) = key.split(':')
            versionList = versionList.split('|')
            if (lang != language):
                continue
            if (dial != dialect):
                continue
            (major, minor, patch) = babelVersion.upper().split('.')
            matchingVer = ''
            for v in versionList:
                v_elements = v.upper().split('.')
                v_major = v_elements[0]
                v_minor='X'
                v_patch='X'
                if (len(v_elements) > 3):
                    err('Invalid supported Babel version number ' + 
                        v + ' in class ' + str(self.writers[key][0]), 2)
                if(len(v_elements) == 2):
                    v_minor = v_elements[1]
                elif (len(v_elements) == 3):
                    v_minor = v_elements[1]
                    v_patch = v_elements[2]
                match = False
                if (v_major == 'X'):
                    match = True
                    matchingVer = v
                    break
                if (v_major != major):
                    continue
                if (v_minor == 'X'):
                    match = True
                    matchingVer = v
                    break
                if (v_minor != minor):
                    continue
                if (v_patch == 'X'):
                    match = True
                    matchingVer = v
                    break
                if (v_patch != patch):
                    continue
            if (not match):
                print >> DEBUGSTREAM, 'Babel version', babelVersion , 'NOT matched by writer versions', versionList
                continue
            print >> DEBUGSTREAM, 'Babel version', babelVersion , 'is matched by writer version', matchingVer
            (classRef, classInstance) = self.writers[key]
            if (classInstance == None):
                classInstance = classRef(kind)
                self.writers[key] = (classRef, classInstance)
            classInstance.setBabelVersion(babelVersion)
            return classInstance
        err('No writer supports ' + language + ' for Babel version ' + babelVersion + ' and dialect ' + dialect, 1)