import re
import sys
import fn
import mem
#20 Feb 2012 - modified var declaration end mark. There is no BLOCK 0.
#modified logic which sets memFlag. Earlier it wasn't getting set - Suhas
#31 Mar 2012 - added logic to preprocess block beginnings and convert
# "Block n...." to <bb n>. This is what the script was expecting and probably
#due to change in the dump format in later versions of gcc, it failed.
#Suhas
#3 Apr 2012 - re_var was matching floating point consts too. Fixed it - Suhas
#7 Oct 2012 - removed ';' when prefixing a comment symbol to tail call 
#8 Oct 2012 - added pattern 'Invalid sum of outgoing probabilities' 
#             as a line to be commented.
#8-10 Oct 2012 - removing [*_expr] sort of patterns. 

def process(sourceFile,fnHash):
  labelStart = "bb "; #assuming that all labels names start with BB. 
                     #Change if label prefix changes - Suhas, 31 March 2012
  f=open(sourceFile+".127t.blocks");#".t99.blocks");
  line=f.readline();
  printFlag=1;
  memFlag=0;
  currentFunction="NONE";
  var_decl=[];                             #list to prevent redefinitions of variables
  declFlag=0;
  re_comments=re.compile('\s*#')                 #Lines  beginning with '#'
  re_functionStart=re.compile(';; Function');    #Start of Function
  #re_label1=re.compile('<[\s\w]+>:;');	         #Labels
  re_label1=re.compile('<[\s\w]+>:');	         #Labels
  #re_label2=re.compile('<\w+>');                 #Labels in goto statements
  re_label2=re.compile('<[\s\w]+>');                 #Labels in goto statements
  re_label3=re.compile('<.+>\s*\((<\w+>)\)');
  #re_var=re.compile('(\w+)\.(\d+)');     #For Compiler defined Variables with a '.' in them
  re_var=re.compile('([a-zA-Z]+\w*)\.(\d+)');  #For Compiler defined Variables with a '.' in them
                                               #But doesn't change floating point constants.
  re_numBytes=re.compile('(\s+-*\d+)B');
  #re_tailCall=re.compile('(\[tail call\];)');
  re_tailCall=re.compile('(\[tail call\])'); #removed ';' in regexp - Suhas, 12 Sep 2012
  re_Block=re.compile('\s*# BLOCK ');   #first occurrence marks end of variable declarations
  re_hexnum=re.compile('\s+(0[0-9a-f]+)');
  re_absExpr=re.compile('ABS_EXPR <([\w\.-]+)>');
  re_minExpr=re.compile('MIN_EXPR <([\w\.-]+), ([\w\.-]+)>');
  re_maxExpr=re.compile('MAX_EXPR <([\w\.-]+), ([\w\.-]+)>');
  re_rotrExpr=re.compile('([\w\.-]+)\s*r>>\s*([0-9]+)');
  re_rotlExpr=re.compile('([\w\.-]+)\s*r<<\s*([0-9]+)');
  re_exprToBeRemoved = re.compile('\[(rshift|lshift|plus|minus|mult|bit_and|bit_ior|bit_xor|pointer_plus)_expr\]');

  while line:
        if declFlag == 1:
          if re_Block.search(line):
            memFlag=1;
            declFlag=0;
            del var_decl[:];                      #clear this list
        if declFlag==1:
            if not (line in var_decl) :         #prevent redefinitions of variables
	        var_decl.append(line);
                # replace type of pointer variables
                decl = re.split(r'([\w_.]+;)', line)
                if len(decl) == 3 and decl[0].find("unsigned") >= 0:
                  var = decl[1][:-1]
                  if var not in fnHash[currentFunction].getVars().keys() and \
                    (var.startswith("ivtmp.") or var.startswith("D.") or \
                     var.startswith("W.")):
                    line = re.split(r'\S+',decl[0])[0] + "uintptr_t " + decl[1] + decl[2]
                if len(decl) == 3 and decl[0].find('*') >= 0:
                  line = re.sub(r'\[[0-9]+\]','',decl[0]) + decl[1] + decl[2]
            else :
	        printFlag=0;
	if (re_comments.match(line)):
          m = re_Block.search(line)
          if m != None:
            temp = line[m.end():]
            n = re.search('[0-9]+', temp) #search and extract basic block number
            if n != None:
              bbNum = temp[:n.end()]
              line = '<' + labelStart + bbNum + '>' + ':' 
              #print "Debug!! " + line
          else:  
	    line = "//" +line;
        if re.match('Invalid sum of incoming frequencies',line):
          line= "//"+ line;
        elif re.match('Invalid sum of outgoing probabilities', line):
          line = "//" + line;
        elif (re_functionStart.match(line)):
	  printFlag = 0;
          m=re.search('\w+\s*\(',line);
          m=re.search('\w+',m.group());
	  currentFunction = m.group();
	  f.readline();
	  f.readline();
	  printFlag=0;
          print fnHash[currentFunction].getDesc(),;
          declFlag=1;
          memFlag=0;
        elif currentFunction != "NONE":
          line=re_numBytes.sub('\g<1>',line);
          m=re_absExpr.search(line)
          if m:
            if m.group(1) in fnHash[currentFunction].getVars().keys():
              v_t=fnHash[currentFunction].getVars()[m.group(1)]
              if v_t.find("long double") >= 0:
                line=re_absExpr.sub('fabsl(\g<1>)',line)
              elif v_t.find("double") >= 0:
                line=re_absExpr.sub('fabs(\g<1>)',line)
              elif v_t.find("float") >= 0:
                line=re_absExpr.sub('fabsf(\g<1>)',line)
              elif v_t.find("long long") >= 0:
                line=re_absExpr.sub('llabs(\g<1>)',line)
              elif v_t.find("long") >= 0:
                line=re_absExpr.sub('labs(\g<1>)',line)
              elif v_t.find("int") >= 0 or v_t.find("short") >= 0:
                line=re_absExpr.sub('abs(\g<1>)',line)
          line=re_absExpr.sub('(\g<1>>0)?\g<1>:-\g<1>',line);
          line=re_minExpr.sub('(\g<1><\g<2>)?\g<1>:\g<2>',line);
          line=re_maxExpr.sub('(\g<1>>\g<2>)?\g<1>:\g<2>',line);
          line=re_rotrExpr.sub('(\g<1><<\g<2>)|(\g<1>>>(sizeof(\g<1>)*CHAR_BIT-\g<2>))',line);
          line=re_rotlExpr.sub('(\g<1>>>\g<2>)|(\g<1><<(sizeof(\g<1>)*CHAR_BIT-\g<2>))',line);
          line = re_exprToBeRemoved.sub('',line); #remove other types of [*_expr] tags
          if memFlag:
	    line=mem.memAccess(line,fnHash[currentFunction]);
          line= re_label3.sub('\g<1>',line);
          #line1= re_label3.sub('\g<1>',line); #uncomment above line and comment these 4 not debugging
          #if line1 != line:
          #  print "Label type 3 matched"
          #  print line; #DEBUG print only
          #line = line1
	  if re_label1.search(line):
	    m=re.search('[\s\w]+',line);
	    line =  (currentFunction+m.group()+":\n")
            line = re.sub( '\s+', '_', line,1)
            #print "Label type 1 matched"
            #print line; #DEBUG print only
	  else: 
	    m=re_label2.findall(line)
	    for i in m :
                m2=re.search('[\s\w]+',i)
                subString = currentFunction+m2.group()
                subString = re.sub( '\s+', '_', subString, 1)
		#line = re_label2.sub(currentFunction+m2.group(),line,1)	
		line = re_label2.sub(subString,line,1)	
		#line1 = re_label2.sub(currentFunction+m2.group(),line,1)	
                #if line1 == line: #if substitution did not take place
                #  line = line1    #retain line
                #else:             # else replace space by underscore
                #  line = re.sub( '\s+', '_', line1,1)
                #print "Label type 2 matched"
                #print line; #DEBUG print only
          line=re_var.sub('\g<1>_\g<2>',line);
          line=re_tailCall.sub('//\g<1>',line);
          line=re_hexnum.sub(' 0x\g<1>',line);
	if printFlag == 1:
	  print line,
        printFlag = 1;
	line = f.readline()
  return 1;
