1. import sys
  2. from operator import itemgetter, attrgetter
  3. from xml.etree.ElementTree import ElementTree
  4.  
  5. # parsing config
  6. CONFIG_FILE = "D:/python/cparser.xml"
  7.  
  8. tr = ElementTree()
  9. m=tr.parse(CONFIG_FILE)
  10. path = m.find("includeDir").text
  11. startXML = ""
  12. sXML = m.find("startXML")
  13. oXML = m.find("outputXML").text
  14. if sXML.attrib["active"] == "true":
  15.     startXML = sXML.text
  16. # parsing config
  17.  
  18. inc = []
  19. arr = []
  20. defineID = 2
  21. funcID = 1
  22.  
  23. def trim(l):
  24.     nl = []
  25.     for i in l:
  26.         if len(i) > 0:
  27.             nl.append(i)
  28.     return nl
  29.  
  30. def stripList(l):
  31.     for i in range(0,len(l)):
  32.         l[i] = l[i].strip()
  33.     return l
  34.  
  35. def contains(lst, srch):
  36.     for x in lst:
  37.         if x == srch:return True
  38.     return False
  39.  
  40. def filter_existant(ar):
  41.     tmp = []
  42.     apTmp = []
  43.     for x in range(0,len(ar)):
  44.         if len(ar[x][1])<3 or str.isdigit(ar[x][1][0]) or ar[x][1].find(" ")>-1 or ar[x][1].find("\t")>=1:
  45.             continue
  46.         if not contains(tmp, ar[x][1]):
  47.             apTmp.append(ar[x])
  48.             tmp.append(ar[x][1])
  49.     return apTmp
  50.    
  51.  
  52.  
  53.  
  54. tree = ElementTree()
  55. try:
  56.     if len(startXML) != 0:
  57.         m=tree.parse(startXML)
  58.         #m=m.find("NotepadPlus")
  59.         l=list(m.iter("KeyWord"))
  60.         for x in l:
  61.             name = x.attrib["name"]
  62.             func = funcID if x.attrib.__contains__("func") else defineID
  63.             retval = ""
  64.             parm = []
  65.             if func:
  66.                 ov = x.find("Overload")
  67.                 if ov is not None:
  68.                     retval = ov.attrib["retVal"]
  69.                     p = list(ov.iter("Param"))
  70.                     for i in p:
  71.                         parm.append(i.attrib["name"])
  72.             arr.append((func, name, retval, parm))
  73. except:
  74.     if startXML != "":
  75.         print("loading startXML failed")
  76.    
  77. def parseDefine(s):
  78.     global arr, defineID, funcID
  79.     s=s.replace("\t", " ")
  80.     ls = trim(s.split(" "))
  81.     arr.append((defineID, ls[1], '' if len(ls)<3 else ls[2], []))
  82. def parseFunc(s):
  83.     global arr, defineID, funcID
  84.     l = s.split("(")
  85.     ps = l[1].split(")")
  86.     ps = ')'.join(ps[:len(ps)-1]).split(",")
  87.     stripList(ps)
  88.     l[0] = l[0].replace(chr(0x9), ' ')
  89.     tl = trim(l[0].split(" "))
  90.     try:
  91.         arr.append( (funcID, tl[len(tl)-1], ' '.join(tl[0:len(tl)-1]), ps) )
  92.     except:
  93.         if len(s) == 2:
  94.             arr.append( (funcID, tl[len(tl)-1], ' ', []) )
  95.  
  96. def parseC(file):
  97.     global inc
  98.     global arr
  99.     if file not in inc:
  100.         inc.append(file)
  101.     else:
  102.         return
  103.     nav = False
  104.     ncom = 0
  105.     stInd = 0
  106.     ndef = False
  107.     nusl = 0
  108.     s = ""
  109.     zag = 0
  110.     bTyp = False
  111.     nZag2 = 0
  112.     bInc = False
  113.    
  114.     try:
  115.         fl = open(file, "r")
  116.         print("parsing file: "+file)
  117.     except:
  118.         return
  119.     f = fl.read()
  120.     fl.close()
  121.    
  122.     for i in range(0,len(f)):
  123.            
  124.         if f[i:i+2] == "/*":
  125.             ncom = 1
  126.             i+=1
  127.             continue
  128.            
  129.         if f[i:i+2] == "*/":
  130.             ncom = 0
  131.             i+=1
  132.             stInd = i+1
  133.             continue
  134.  
  135.         if ncom == 1:
  136.             continue
  137.            
  138.         if f[i]=="{" and f[stInd:i].find("extern")==-1:
  139.             nZag2 += 1
  140.         if f[i]=="}":
  141.             nZag2 -= 1
  142.            
  143.         if nZag2 > 0:
  144.             continue
  145.            
  146.         if f[i]!="\"" and nav:
  147.             continue
  148.            
  149.         if f[i:i+7] == "#define":
  150.             stInd = i
  151.             ndef = True
  152.            
  153.         if f[i:i+8] == "#include":
  154.             bInc = True
  155.             stInd = i
  156.            
  157.         if f[i]=="#":
  158.             nusl = 1
  159.            
  160.         if f[i]==";":
  161.             if zag and not bTyp:
  162.                 s = f[stInd:i]
  163.                 try:
  164.                     parseFunc(s)
  165.                 except:
  166.                     pass
  167.                 zag = False
  168.             else:
  169.                 bTyp = False
  170.             stInd = i+2
  171.            
  172.         if f[i]==")" and zag>0 and not ndef and not nusl and not bTyp:
  173.             zag -= 1
  174.             if zag == 0:
  175.                 s = f[stInd:i+1]
  176.                 try:
  177.                     parseFunc(s)
  178.                 except:
  179.                     pass
  180.                 zag = False
  181.                 stInd = i+1
  182.            
  183.         if f[i]=="\"":
  184.             nav^=True
  185.            
  186.         if (f[i]=="\r" or f[i]=="\n"):
  187.             nusl = 0
  188.             if bInc:
  189.                 s = f[stInd:i]
  190.                 s1 = s.split("<")
  191.                 if len(s1) > 1:
  192.                     parseC(path+s1[1].split(">")[0].strip())
  193.                 else:
  194.                     spl = s.split("\"")
  195.                     if len(spl) == 3:
  196.                         parseC(spl[1])
  197.             if ndef:
  198.                 ndef = False
  199.                 s = f[stInd:i]
  200.                 try:
  201.                     parseDefine(s)
  202.                 except:
  203.                     pass
  204.                 s = ""
  205.                 continue
  206.             stInd = i+1
  207.            
  208.        
  209.         if f[i] == "(" and not ndef and not nusl:
  210.             zag += 1
  211.            
  212.         if f[i:i+7] == "typedef" and not nusl and not ndef:
  213.             stInd = i
  214.             bTyp = True
  215.    
  216. parseC(sys.argv[1])
  217.  
  218. arr = filter_existant(arr)
  219. arr = sorted(arr, key=lambda x: x[1].upper())
  220.  
  221. # export
  222. fl = open(oXML, "w")
  223. fl.write("<?xml version=\"1.0\" encoding=\"Windows-1252\" ?>\n")
  224. fl.write("<NotepadPlus>\n")
  225. fl.write("\t<AutoComplete language=\"C\">\n")
  226. fl.write("\t\t<Environment ignoreCase=\"yes\" startFunc=\"(\" stopFunc=\")\" paramSeparator=\",\" terminal=\";\" />\n")
  227. for i in arr:
  228.     if(i[0] == defineID):
  229.         fl.write("\t\t\t<KeyWord name=\""+i[1]+"\"/>\n")
  230.     if(i[0] == funcID):
  231.         fl.write("\t\t\t<KeyWord name=\""+i[1]+"\" func=\"yes\">\n")
  232.         fl.write("\t\t\t\t<Overload retVal=\""+i[2].replace('\n', ' ')+"\">\n")
  233.         for j in i[3]:
  234.             fl.write("\t\t\t\t\t<Param name=\""+j.strip()+"\"/>\n")
  235.            
  236.         fl.write("\t\t\t\t</Overload>\n")
  237.         fl.write("\t\t\t</KeyWord>\n")
  238.        
  239. fl.write("\t</AutoComplete>\n")
  240. fl.write("</NotepadPlus>\n")
  241. fl.close()