"""Class to parse CONFIG files for library"""
import string
import re
import UserDict
import types
import os
# relative imports needed
from . import setup_globals
from .setup_globals import gvars, SetupError
from ..utils import strip_comments
[docs]class FlashLib(UserDict.UserDict):
"""Encapsulates library information as expressed in Config files.
Data is accessed through dictionary methods, ex:
FlashLib('pfft')['LIBRARY']
Currently the only supported keyword in Config files in lib directory is LIBRARY keyword
NOTE: we need to be in "lib" directory when instantiating this
All the code are copied from FlashUnit (this code is a subset of that of FlashUnit)
"""
def __init__(self, pathName, ignoreConfig=0):
UserDict.UserDict.__init__(self)
self.COMMENT = '#'
self.QUOTE = '"'
self.FILEBASE = 'Config'
self.regexps = {}
self.parsers = []
pathname = pathName.lower()
# This is just a clever way to list the methods in the
# class. The dir(self.__class__) lists all the attributes
# like __cmp__ , __init___, __setitem__, __len__ etc and
# then also the user defined methods, in this case,
# get_parent, initParser, match, parseDEFAULT, parseEXCLUSIVE etc.
for name in dir(self.__class__):
if not re.compile(r'parse[A-Z]+$').match(name): continue
if type(getattr(self, name))==types.MethodType:
self.parsers.append(name)
try: getattr(self, name)('') #initialize regexps, dictionary
except SetupError: pass
self.update( {'LIBRARY': {}, 'TYPE': 'EXTERNAL'})
if not os.path.isdir(pathname): # given name does not make sense
msg = 'Directory {0} not found. Assuming external library'
msg = msg.format(os.path.join(os.getcwd(), pathname))
gvars.out.put(msg, setup_globals.DEBUG)
ignoreConfig = 1
self.name = os.path.normpath(pathname) #something like 'pfft'
if (not ignoreConfig) and \
os.path.isfile(os.path.join(self.name, self.FILEBASE)):
self.filename = os.path.join(self.name, self.FILEBASE)
self.parse()
else:
self.filename = ''
def __cmp__(self, other):
"""Alphabetical comparison on unit names (like 'source/io/amr')"""
if type(other)==types.StringType:
return cmp(self.name, other)
else:
return cmp(self.name, other.name)
def __repr__(self):
return self.name
def match(self, keyword, line):
match = self.regexps[keyword].match(line)
if not match:
raise SetupError('input doesn\'t match regular expression "%s"'%\
self.regexps[keyword].pattern)
return match
def parse(self):
lineno = 0
for line in open(self.filename).readlines():
lineno += 1
rawline = line
if rawline and rawline[-1]=='\n': rawline = rawline[:-1]
line=strip_comments(line, self.COMMENT,self.QUOTE)
line=string.strip(line)
if not line: continue
pkeyword = "parse%s" % string.split(line)[0]
if pkeyword not in self.parsers:
raise SetupError('Unknown keyword: file %s, line '\
'%d\n%s'%(self.filename, lineno, rawline))
try:
getattr(self,pkeyword)(line)
except SetupError, msg:
raise SetupError('Bad syntax: file %s, line %d:\n%s\n\n%s' % \
(os.path.join("lib",self.filename), lineno, rawline, str(msg)))
def initParser(self, keyword, initvalue, regexp=None):
if self.has_key(keyword): return
self[keyword]=initvalue
if regexp:
self.regexps[keyword]=re.compile(regexp)
def parseLIBRARY(self, line):
self.initParser('LIBRARY', {}, 'LIBRARY\s+(\S+)\s*(.*)$')
libmatch = self.match('LIBRARY',line)
libname = libmatch.group(1).lower()
libargs = string.join(libmatch.group(2).split()) # trims and removes multiple spaces
self['LIBRARY'][libname] = libargs
def parseTYPE(self,line):
self.initParser('TYPE', "EXTERNAL",'TYPE\s+(INTERNAL|EXTERNAL)\s*$')
self['TYPE']= self.match('TYPE',line).group(1)