apicompatanamdw/compatanalysercmd/checkbc/scripts/cds/lib/fileimage.py
changeset 0 638b9c697799
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apicompatanamdw/compatanalysercmd/checkbc/scripts/cds/lib/fileimage.py	Tue Jan 12 14:52:39 2010 +0530
@@ -0,0 +1,391 @@
+#
+# Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:  File image handling functions for CDS script
+#
+
+import sys, pprint
+from array import array
+
+_DBG = False
+def dbg(str):
+    if _DBG:
+        print str
+
+TT_UNKNOWN = '?'; TT_COMMENT = '#'; TT_STRING = '"'; TT_CODE = '.'
+def translate_mark_for_print(mark):
+    if mark == "\n":
+        return "\\n"
+    elif mark == "\r":
+        return "\\r"
+    elif mark == "\t":
+        return "\\t"
+    return mark
+    
+    
+class CCLineImage(object):
+    def __init__(self, data, mask, lineno=0, startPos=-1, endPos=-1):
+        self.__data = data
+        self.__mask = mask
+        self.lineno = lineno
+        self.startPos = startPos
+        self.endPos = endPos
+        self.datalen = len(data)
+
+    def data(self):
+        return self.__data[:]
+
+    def code(self, useBlanks=True):
+        return self._get_line((TT_CODE,), useBlanks)
+
+    def comments(self, useBlanks=True):    
+        return self._get_line((TT_COMMENT,), useBlanks)
+    
+    def strings(self, useBlanks=True):    
+        return self._get_line((TT_STRING,), useBlanks)
+
+    def code_and_strings(self, useBlanks=True):    
+        return self._get_line((TT_STRING, TT_CODE), useBlanks)
+
+    def text(self):    
+        return self._get_line((TT_STRING, TT_CODE, TT_COMMENT), False)
+        
+    def mask(self):
+        return self.__mask.tostring()
+
+    def _get_line(self, typez, useBlanks):
+        line = array('c')
+        for i in xrange(self.datalen):
+            if self.__data[i] == '\n':
+                break
+            elif self.__mask[i] in typez:
+                line.append(self.__data[i])
+            elif useBlanks:
+                line.append(' ')
+        return line.tostring()
+        
+            
+class CCTextBlockImage(object):
+    delimitPairs = (('(', ')'), ('{', '}'), ('[', ']'), ('<', '>'))
+    delimitChars = [e for s, e in delimitPairs] + [s for s, e in delimitPairs]
+    endDelimiters = [e for s, e in delimitPairs]
+    startDelimiters = [s for s, e in delimitPairs]
+    
+    def __init__(self):
+        self.data = array('c')
+        self.datamask = array('c')
+        
+        self.chPrev = None
+        self.ch = None
+        self.chNext = None
+        self.pos = 0
+        self.continueScan = True
+        self.dataLen = 0
+        self.lineFeeds = []
+        self.lineFeedLen = 0
+
+    def load(self, textblock):
+        import sys
+        del self.data
+        self.data = array('c', textblock)
+        self.datamask = array('c', TT_UNKNOWN * len(self.data))
+        self.dataLen = len(textblock)
+                
+    def _dbg_chars(self):
+        if _DBG:
+            dbg("pos=%d, len=%d, prev=%s, cur=%s, next=%s" % (self.pos, self.dataLen, 
+                                                            translate_mark_for_print(self.chPrev),
+                                                            translate_mark_for_print(self.ch), 
+                                                            translate_mark_for_print(self.chNext)))
+
+    # moves current data pointer and marks passed chars as charType
+    def _seek(self, amount, prevType=None, curType=None, nextType=None):
+
+        if not self.dataLen > 0:
+            return
+        if prevType:
+            self.datamask[self.pos-1] = prevType
+        if curType:
+            self.datamask[self.pos] = curType
+        if nextType:
+            self.datamask[self.pos+1] = nextType
+            
+        oldPos = self.pos
+        self.pos += amount
+        assert (oldPos <= self.pos) and (amount <= 2)
+
+        if self.pos <= 0:
+            self.pos = 0; self.chPrev = None; self.ch = self.data[0]
+            if self.dataLen > 1:
+                self.chNext = self.data[1]
+            
+            self._dbg_chars()
+        elif self.pos == self.dataLen - 1:
+            self.chNext = None; self.ch = self.data[-1]; self.chPrev = self.data[-2]
+            self._dbg_chars()
+        elif self.pos > self.dataLen - 1:
+            self.pos = self.dataLen - 1
+            dbg("FINISHING SCAN")
+            self.continueScan = False
+        else:
+            self.ch = self.data[self.pos]; self.chNext = self.data[self.pos+1]; self.chPrev = self.data[self.pos-1]
+            self._dbg_chars()
+
+
+
+    def scan(self, bytePrintFmtStr='', bytePrintTreshold=20000):
+        if self.dataLen == 0:
+            return
+
+        SINGLELINE = 1; MULTILINE = 2; STRING = 3; CODE = 4
+        self.pos = 0; self.continueScan = True
+
+        state = CODE
+        self._seek(0)
+        while self.continueScan:
+            if (self.pos > 1) and (self.pos % bytePrintTreshold == 0) and bytePrintFmtStr:
+                print bytePrintFmtStr % (self.pos, self.dataLen, ((self.pos * 100) / self.dataLen))
+            if state == CODE:
+                if (self.ch == '/') and (self.chNext == '/'):
+                    dbg("FOUND // -> ENTER SINGLELINE STATE")
+                    self._seek(2, curType=TT_COMMENT, nextType=TT_COMMENT)
+                    state = SINGLELINE
+                elif (self.ch == '/') and (self.chNext == '*'):
+                    dbg("FOUND /* -> ENTER MULTILINE STATE")
+                    self._seek(2, curType=TT_COMMENT, nextType=TT_COMMENT)
+                    state = MULTILINE
+                elif (self.ch == '"'):
+                    dbg('FOUND " --> ENTER STRING STATE')
+                    self._seek(1, curType=TT_STRING)
+                    state = STRING
+                else:
+                    if (self.ch == '\n'):
+                        self.lineFeeds.append(self.pos)
+                    self._seek(1, curType=TT_CODE)
+            elif state == STRING:
+                if (self.ch == '\n'):
+                    if (self.chPrev != '\\'):
+                        dbg("FOUND line-end on string --> ENTER CODE STATE")
+                        state = CODE
+                    self.lineFeeds.append(self.pos)
+                    self._seek(1, curType=TT_STRING)
+                elif (self.ch == '"'):
+                    dbg('FOUND " on string --> ENTER CODE STATE')
+                    self._seek(1, curType=TT_STRING)                                   
+                    state = CODE
+                else:
+                    self._seek(1, curType=TT_STRING)
+            elif state == MULTILINE:
+                if (self.ch == '*') and (self.chNext == '/'):
+                    dbg("FOUND multiline end --> ENTER CODE STATE")
+                    self._seek(2, curType=TT_COMMENT, nextType=TT_COMMENT)
+                    state = CODE
+                else:
+                    if (self.ch == '\n'):
+                        self.lineFeeds.append(self.pos)
+                    self._seek(1, curType=TT_COMMENT)
+            elif state == SINGLELINE:
+                if (self.ch == '\n'):
+                    dbg("FOUND line-end on singleline comment --> ENTER CODE STATE")
+                    self.lineFeeds.append(self.pos)                    
+                    self._seek(1, curType=TT_COMMENT)
+                    state = CODE
+                else:
+                    self._seek(1, curType=TT_COMMENT)
+                    
+        self.lineFeedLen = len(self.lineFeeds)
+
+
+    def __str__(self):
+        rawdata = array('c')
+        for mark in self.data:
+            rawdata.append(translate_mark_for_print(mark))
+        return rawdata.tostring()
+
+    def iter_lineimages(self, startPos=-1, forward=True, lineCount=-1):
+        curline = array('c')
+        curmask = array('c')
+        pos = 0
+        linesLeft = 9999999
+        datalen = len(self.data)
+        
+        if startPos != -1:
+            pos = startPos
+            assert (pos >= 0) and (pos < datalen)
+        if lineCount != -1:
+            assert lineCount > 0
+            linesLeft = self.get_lineno(pos)
+            if forward:
+                linesLeft = self.get_linecount() - self.get_lineno(pos)
+            if lineCount < linesLeft:
+                linesLeft = lineCount
+            #print "%d - %d" % (self.get_linecount(), self.get_lineno(pos))
+            assert linesLeft >= 0
+            
+        lineStartPos = 0
+        lineNo = 1
+        while (pos >= 0) and (pos < datalen) and (linesLeft > 0):
+            mark = self.data[pos]
+            maskmark = self.datamask[pos]
+            if mark == '\n':
+                yield CCLineImage(curline, curmask, lineNo, lineStartPos, pos)
+                linesLeft -= 1
+                curline = array('c')
+                curmask = array('c')
+                lineStartPos = pos + 1
+                lineNo += 1
+            else:
+                curline.append(mark)
+                curmask.append(maskmark)
+            if forward:
+                pos += 1
+            else:
+                pos -= 1
+        if len(curline) > 0:
+            yield CCLineImage(curline, curmask, lineNo, lineStartPos, pos)
+
+    def get_line_startpos(self, pos):
+        if pos > (self.dataLen - 1):
+            return -1
+        if self.lineFeedLen == 0:
+            return 0
+        for i in xrange(lineFeedLen):
+            if self.lineFeeds[i] > pos:
+                if i > 0:
+                    return self.lineFeeds[i-1] + 1
+                return 0
+        return pos - self.lineFeeds[-1]
+
+    def get_linecount(self):
+        return len(self.lineFeeds) + 1
+    
+    def get_lineno(self, pos):
+        if pos > (self.dataLen - 1):
+            return -1
+        lineFeedLen = len(self.lineFeeds)
+        if lineFeedLen == 0:
+            return 1
+        for i in xrange(lineFeedLen):
+            if self.lineFeeds[i] > pos:
+                #print "if %d > %d" % (self.lineFeeds[i], pos)
+                return i
+        return lineFeedLen
+            
+    def get_colno(self, pos):
+        if pos > (len(self.data) - 1):
+            return -1
+        if len(self.lineFeeds) == 0:
+            return pos
+        for i in xrange(len(self.lineFeeds)):
+            if self.lineFeeds[i] < pos:
+                return pos - self.lineFeeds[i]
+
+    def get_lineimages(self, startPos=-1, endPos=-1):
+        lineImgs = []
+        curline = array('c')
+        curmask = array('c')
+        lastInd = len(self.data) - 1
+        if startPos < 0: startPos = 0
+        if startPos > lastInd: startPos = lastInd
+        if endPos < 0: endPos = 0
+        if endPos > lastInd: endPos = lastInd
+        pos = startPos
+        while pos <= endPos:
+            if self.data[pos] == '\n':
+                lineImgs.append(CCLineImage(curline, curmask, self.get_lineno(pos), self.get_line_startpos(pos), pos))
+                curline = array('c')
+                curmask = array('c')
+            else:
+                curline.append(self.data[pos])
+                curmask.append(self.datamask[pos])
+            pos += 1
+        if len(curline) > 0:
+            lineImgs.append(CCLineImage(curline, curmask, self.get_lineno(pos), self.get_line_startpos(pos), pos))
+
+        return lineImgs                        
+
+    def find_matching_delimiter(self, pos):
+        if (len(self.data) < pos) or (pos < 0):
+            return -1
+        
+        data = self.data
+        startChar = data[pos]
+        if startChar not in self.delimitChars:
+            return -1
+        
+        forward = True
+        if startChar in self.endDelimiters:
+            forward = False
+
+        endChar = ''
+        for s, e in self.delimitPairs:
+            if startChar == s:
+                endChar = e
+            elif startChar == e:
+                endChar = s
+
+        curStackPos = 0
+        datalen = len(data)
+        while pos < datalen:
+            if data[pos] == startChar:
+                curStackPos += 1
+            elif data[pos] == endChar:
+                curStackPos -= 1
+            if curStackPos <= 0:
+                return pos
+            if forward:
+                pos += 1
+            else:
+                pos -= 1
+        return -1
+
+    def get_surrounding_lineimages(self, linesFw, linesBw, pos):
+        if (len(self.data) < pos) or (pos < 0) or (linesFw < 0) or (linesBw < 0):
+            return []
+        lineImgs = []
+        if linesBw and (pos > 0):
+            pos -= 1
+            while linesBw > 0:
+                if self.data[pos] == '\n':
+                    linesBw -= 1; linesFw += 1
+                if pos < 0:
+                    break
+                pos -= 1
+
+        for lineImg in self.iter_lineimages(pos, forward=True, lineCount=linesFw):
+            lineImgs.append(lineImg)
+        return lineImgs
+
+class CCFileImage(CCTextBlockImage):
+    def __init__(self):
+        super(CCFileImage, self).__init__()
+
+    def load(self, filename):
+        rawdata = open(filename, 'r').read()
+        self.load_from_rawdata(rawdata)
+        
+    def load_from_rawdata(self, rawdata):
+        super(CCFileImage, self).load(rawdata)
+        
+if __name__=="__main__":
+    f = CCFileImage()
+    f.load(sys.argv[1])
+    f.scan()
+    for img in f.iter_lineimages():
+        print img.mask()
+        print img.text()
+        #print img.code()
+        #print img.comments()
+        #print img.code_and_strings()
+        #print img.strings()
+        print ''
\ No newline at end of file