Advertisement
Guest User

Untitled

a guest
Nov 22nd, 2017
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 19.00 KB | None | 0 0
  1. from __future__ import print_function
  2.  
  3. #
  4. # Made by duponc_j, modified by sourio_b while supervised by sbriss_a in case he fucked things up (and he did)
  5. # Slightly modified by Arignir
  6. # Version: 1.4.1
  7. #
  8.  
  9. '''
  10. An Epitech norme checker
  11.  
  12. Usage: python norme.py <dir to scan> [-nocheat] [-verbose] [-score] [-libc]
  13.  
  14. -verbose: affiche les messages impossible d\'ouvrir
  15. -nocheat: desactive la detection de la triche
  16. -score: affiche le nombre de faute de norme
  17. -libc: active la verification des fonctions de la libc
  18. -malloc: desactive le controle du malloc
  19. -printline: affiche la ligne provoquant une erreur
  20. -return: active verifier le retour des fonctions (return ;)
  21. -comment: ne pas verifier les commentaire
  22.  
  23. Non geree:
  24. - Indentation
  25. - +<escape>
  26. - verification de la presence de gl_
  27.  
  28. Bug:
  29. Il est arrivee que le checker ne trouve aucune faute alors qu\'il en existe, si
  30. ce bug vous arrive maillez moi.
  31. '''
  32.  
  33. import sys,re,os,pwd
  34.  
  35. blind_logins = [ "{EPITECH.}" ]
  36.  
  37. def static_var(varname, value):
  38.     def decorate(func):
  39.         setattr(func, varname, value)
  40.         return func
  41.     return decorate
  42.  
  43. class norme:
  44.     def __init__(self):
  45.         self.user = []
  46.         self.verbose = 0
  47.         self.cheat = 1
  48.         self.comment = 1
  49.         self.score = 0
  50.         self.note = 0
  51.         self.libc = 1
  52.        # self.malloc = 1
  53.         self.malloc = 0
  54.         self.printline = 0
  55.         self.creturn = 1
  56.         self.the_dir = ""
  57.  
  58.     def new_file(self):
  59.         self.nb_line = 1
  60.         self.nb_return = 0
  61.         self.nb_funcline = 0
  62.         self.nb_func = 0
  63.         self.sys_include = 0
  64.         self.double_inclusion = 0
  65.         self.is_func = 0
  66.         self.in_comment = 0
  67.         self.out_comment = 0
  68.         self.typedef = 0
  69.         if self.verbose == 1:
  70.             print("Scan: %s" % self.file)
  71.  
  72.     @static_var("passed", 0)
  73.     def check_header(self):
  74.         norme = -1
  75.         if self.check_header.passed:
  76.             norme = 0
  77.         for blind in blind_logins:
  78.             if (blind in self.user):
  79.                 return
  80.         if (self.nb_line == 1):
  81.             if (self.line[:2] != '/*'):
  82.                 self.print_error('Header incorrect', norme)
  83.                 self.check_header.__func__.passed = 1
  84.         elif (self.nb_line == 6):
  85.             if (self.line[:2] != '*/'):
  86.                 self.print_error('Header incorrect', norme)
  87.                 self.check_header.__func__.passed = 1
  88.  
  89.  
  90.     @static_var("passed", 0)
  91.     def check_virgule(self):
  92.         norme = -1
  93.         if self.check_virgule.passed:
  94.             norme = 0
  95.         n = 0
  96.         quote = 0
  97.         while n < len(self.line) and self.line[n] != '\n' :
  98.             if self.line[n] == '\'' or self.line[n] == '"':
  99.                 if quote:
  100.                     quote = 0
  101.                 else:
  102.                     quote = 1
  103.             if (self.line[n] == ',') and quote == 0:
  104.                 if self.line[n + 1] != ' ' and self.line[n + 1] != '\n' and self.line[n + 1] != '\t':
  105.                     if self.line[-2:-1] == '\\':
  106.                         pass
  107.                     self.print_error('Point-virgule ou virgule mal place', norme)
  108.                     self.check_virgule.__func__.passed = 1
  109.                     break
  110.             n = n + 1
  111.  
  112.     @static_var("passed", 0)
  113.     def check_space_par(self):
  114.         norme = -1
  115.         if self.check_space_par.passed:
  116.             norme = 0
  117.         n = 0
  118.         quote = 0
  119.         while n < len(self.line) and self.line[n] != '\n' :
  120.             if self.line[n] == '\'' or self.line[n] == '"':
  121.                 if quote:
  122.                     quote = 0
  123.                 else:
  124.                     quote = 1
  125.             if (self.line[n] == '(') and quote == 0:
  126.                 if self.line[n + 1] == ' ':
  127.                     self.print_error('Espace après une parenthese ouvrante', norme)
  128.                     self.check_space_par.__func__.passed = 1
  129.                     break
  130.             if (self.line[n] == ')') and quote == 0:
  131.                 if self.line[n - 1] == ' ':
  132.                     self.print_error('Espace avant une parenthese fermante', norme)
  133.                     self.check_space_par.__func__.passed = 1
  134.                     break
  135.             n = n + 1
  136.  
  137.     @static_var("passed", 0)
  138.     def check_nbchar(self):
  139.         norme = -5
  140.         if self.check_nbchar.passed:
  141.             norme = 0
  142.         line = self.line.replace('\t', "    ")
  143.         if len(line) > 84:
  144.             note =  len(line) - 80
  145.             self.print_error('Chaine de plus de 80 caracteres', norme)
  146.             self.check_nbchar.__func__.passed = 1
  147.  
  148.     @static_var("passed", 0)
  149.     def check_return(self):
  150.         norme = -1
  151.         if self.check_return.passed:
  152.             norme = 0
  153.         if (self.line[:1] == '\n'):
  154.             if (self.nb_return == 1):
  155.                 self.print_error('Double retour a la ligne', norme)
  156.                 self.check_return.__func__.passed = 1
  157.             else:
  158.                 self.nb_return = 1
  159.         else:
  160.             self.nb_return = 0
  161.  
  162.     @static_var("passed", 0)
  163.     def check_nbline(self):
  164.         norme = -5
  165.         if self.check_nbline.passed:
  166.             norme = 0
  167.         if self.file[-2:] == ".c":
  168.             if self.line[:1] == '}':
  169.                 self.is_func = 0
  170.                 self.nb_funcline = 0
  171.             if self.line[:2] == '};':
  172.                 self.is_func = 0
  173.                 self.nb_funcline = 0
  174.                 self.nb_func = self.nb_func -1
  175.             if self.line[:1] == '{' and self.typedef == 0:
  176.                 self.is_func = 1
  177.                 self.nb_funcline = 0
  178.                 self.nb_func = self.nb_func + 1
  179.                 if self.nb_func == 6:
  180.                     self.print_error('Plus de 5 fonctions dans le même fichier', norme)
  181.                     self.check_nbline.__func__.passed = 1
  182.             else:
  183.                 if self.nb_func >= 1 and self.is_func:
  184.                     self.nb_funcline = self.nb_funcline + 1
  185.                     if self.nb_funcline >= 21:
  186.                         self.print_error('Fonction de plus de 20 lignes', norme)
  187.                         self.check_nbline.__func__.passed = 1
  188.  
  189.     @static_var("passed", 0)
  190.     def check_cfunc(self):
  191.         norme = -1
  192.         if self.check_cfunc.passed:
  193.             norme = 0
  194.         p = re.compile('[ \t](if|else|return|while|for|break)(\()')
  195.         test = re.search(p, self.line)
  196.         if test:
  197.             self.print_error('Pas d\'espace apres mot clef', norme)
  198.             self.check_cfunc.__func__.passed = 1
  199.  
  200.     @static_var("passed", 0)
  201.     def check_arg(self):
  202.         norme = -5
  203.         if self.check_arg.passed:
  204.             norme = 0
  205.         if self.line[-2:] == ")\n" and self.line[:1] != '\t'  and self.line[:1] != ' ':
  206.             p = re.compile('(.*),(.*),(.*),(.*),(.*)\)$')
  207.             test = re.search(p, self.line)
  208.             if test and self.line.find(')') == self.line.rfind(')'):
  209.                 note = 1
  210.                 if len(test.groups()) > 0:
  211.                     note = len(test.groups()) - 4
  212.                 self.print_error('Plus de 4 arguments passes en parametre', norme)
  213.                 self.check_arg.__func__.passed = 1
  214.  
  215.     @static_var("passed", 0)
  216.     def check_sys_include(self):
  217.         return
  218.         if self.check_sys_include.passed:
  219.             return
  220.         if self.line[:1] == "#" and self.line[-2:] == "\"\n":
  221.             self.sys_include = 1
  222.         else:
  223.             if self.line[:1] == "#" and self.line[-2:] == ">\n" and self.sys_include == 1:
  224.                 self.print_error('Header systeme mal placee')
  225.                 self.check_sys_include.__func__.passed = 1
  226.  
  227.     @static_var("passed", 0)
  228.     def check_comment(self):
  229.         norme = -5
  230.         if self.check_comment.passed:
  231.             norme = 0
  232.         if self.is_func and self.comment:
  233.             p = re.compile('(//|/\*)')
  234.             test = re.search(p, self.line)
  235.             if test:
  236.                 note = 1
  237.                 if len(test.groups()) > 0:
  238.                     note = len(test.groups())
  239.                     self.print_error('Commentaires dans le code', norme)
  240.                     self.check_comment.__func__.passed = 1
  241.  
  242.     @static_var("passed", 0)
  243.     def check_malloc(self):
  244.         if self.check_malloc.passed:
  245.             return
  246.         p = re.compile('[^x](malloc)(\()')
  247.         test = re.search(p, self.line)
  248.         if test and (self.file != "xmalloc.c"):
  249.             self.print_error('Malloc non verifiee')
  250.             self.check_malloc.__func__.passed = 1
  251.  
  252.     @static_var("passed", 0)
  253.     def check_double(self):
  254.         return
  255.         norme = -1
  256.         if self.check_double.passed:
  257.             norme = 0
  258.         if self.file[-2:] == ".h":
  259.             if self.line[:1] != '\n':
  260.                 if self.double_inclusion != 1:
  261.                     self.double_inclusion = 1
  262.                     if self.line[-4:] != "_H_\n":
  263.                         self.print_error('Header non protegee', norme)
  264.                         self.check_double.__func__.passed = 1
  265.                     else:
  266.                         self.double_inclusion = 1
  267.  
  268.     @static_var("passed", 0)
  269.     def check_operateur(self, op):
  270.         norme = -1
  271.         if self.check_operateur.passed:
  272.             norme = 0
  273.         n = 0
  274.         quote = 0
  275.         while n < len(self.line) and self.line[n] != '\n' :
  276.             if self.line[n] == '\'' or self.line[n] == '"':
  277.                 if quote:
  278.                     quote = 0
  279.                 else:
  280.                     quote = 1
  281.             if (self.line[n] == op) and quote == 0:
  282.                 if (self.line[n + 1] != ' ' or self.line[n - 1] != ' ') and self.line[n + 1] != ';' and self.line[n + 1] != '=' and self.line[n + 1] != '\n':
  283.                     if self.line[n - 1] != op and self.line[n + 1] != op and not self.line[:n].isspace():
  284.                         msg = 'Operateur %c mal placé' % op
  285.                         self.print_error(msg, norme)
  286.                         self.check_operateur.__func__.passed = 1
  287.             n = n + 1
  288.  
  289.     def check_typedef(self):
  290.         if self.line[:7] == "typedef":
  291.             self.typedef = 1
  292.         else:
  293.             self.typedef = 0
  294.  
  295.     @static_var("passed", 0)
  296.     def check_regex(self, regex, msg):
  297.         norme = -42
  298.         if self.check_regex.passed:
  299.             norme = 0
  300.         p = re.compile(regex)
  301.         test = re.search(p, self.line)
  302.         if test:
  303.             note = 1
  304.             if len(test.groups()) > 0:
  305.                 note = len(test.groups())
  306.                 self.print_error(msg, norme)
  307.                 self.check_regex.__func__.passed = 1
  308.  
  309.     @static_var("passed", 0)
  310.     def check_returns(self):
  311.         norme = -1
  312.         if self.check_returns.__func__.passed:
  313.             norme = 0
  314.         dot = self.line.rfind(';')
  315.         if dot == -1:
  316.             return
  317.         pos = dot - 1
  318.         left = self.line[:dot]
  319.         while pos >= 0 and (left[pos] == ' ' or left[pos] == '\t'):
  320.             pos = pos - 1
  321.         pos = pos + 1
  322.         ret = self.line.find("return")
  323.         if ret == -1:
  324.             ret = self.line.find("break")
  325.         par = self.line.find("(")
  326.         if (ret != -1 and par == -1):
  327.             pos = pos + 1
  328.         if pos < dot:
  329.             self.print_error("Espaces avant le ';'", norme)
  330.             self.check_returns.__func__.passed = 1
  331.  
  332.     @static_var("passed", 0)
  333.     def check_endlinespaces(self):
  334.         norme = -1
  335.         if self.check_endlinespaces.passed:
  336.             norme = 0
  337.         dot = self.line.find('\n')
  338.         if dot == -1:
  339.             return
  340.         pos = dot - 1
  341.         left = self.line[:dot]
  342.         while pos >= 0 and (left[pos] == ' ' or left[pos] == '\t'):
  343.             pos = pos - 1
  344.         pos = pos + 1
  345.         if pos < dot:
  346.             self.print_error("Espace(s) en fin de ligne", norme)
  347.             self.check_endlinespaces.__func__.passed = 1
  348.  
  349.     @static_var("passed", 0)
  350.     def check_line(self):
  351.         norme = -5
  352.         if self.is_func != 1 and self.line.find("/*") != -1:
  353.             self.out_comment = 1
  354.         if  self.out_comment:
  355.             if self.is_func != 1 and self.line.find("*/") != -1:
  356.                 self.nb_return = 0
  357.                 self.out_comment = 0
  358.             return
  359.  
  360.         if self.is_func == 1 and self.comment and self.line.find("/*") != -1 and self.line.find('\"') == -1:
  361.             self.in_comment = 1
  362.             if self.check_line.passed:
  363.                 norme = 0
  364.             self.print_error("Commentaires dans le code", norme)
  365.             self.check_line.__func__.passed = 1
  366.             if self.line.find("*/") != -1:
  367.                 self.nb_return = 0
  368.                 self.in_comment = 0
  369.                 return
  370.         self.check_nbline() # DOIT TOUJORS ETRE EN PREMIER
  371. #        self.check_sys_include()
  372.         self.check_virgule()
  373.         self.check_space_par()
  374.         self.check_endlinespaces()
  375.         self.check_returns()
  376.         if self.libc == 0:
  377.             self.check_regex('[^_](printf|atof|atoi|atol|strcmp|strlen|strcat|strncat|strncmp|strcpy|strncpy|fprintf|strstr|strtoc|sprintf|asprintf|perror|strtod|strtol|strtoul)(\()', \
  378.                              'Fonction de la lib C')
  379.         self.check_nbchar()
  380.         self.check_cfunc()
  381.         self.check_arg()
  382.         self.check_return()
  383.         self.check_double()
  384.         self.check_operateur('+')
  385.         self.check_operateur('|')
  386.         self.check_typedef() #DOIT TOUJOURS ETRE EN DERNIER
  387.         if self.malloc:
  388.             self.check_malloc()
  389.  
  390.     def print_error(self, msg, val = -1):
  391.         self.note = self.note + val
  392.         print("Erreur dans %s a la ligne %s:%s => %s"% (self.the_dir + self.file, self.nb_line, msg, val))
  393.         if self.printline:
  394.             print(self.line)
  395.  
  396.     def get_score(self):
  397.         if self.note < -10:
  398.             return (1)
  399.         elif self.note < -5:
  400.             return (-10)
  401.         return (self.note)
  402.  
  403.     def cant_open(self, file):
  404.         if (self.verbose or file == sys.argv[1]):
  405.             print("Impossible d'ouvrir", file)
  406.     def scanfile(self, file):
  407.         if file[-2:] == '.c' or file[-2:] == '.h':
  408.             self.file = file
  409.             self.new_file()
  410.             try:
  411.                 fd = open(file, 'r')
  412.             except IOError:
  413.                 self.cant_open(file)
  414.             else:
  415.                 for self.line in fd.readlines():
  416.                     if self.nb_line <= 9:
  417.                         self.check_header()
  418.                     else:
  419.                         self.check_line()
  420.                     self.nb_line = self.nb_line + 1
  421.                     fd.close()
  422.  
  423.     def scandir(self, thedir):
  424.         try:
  425.             dir = os.listdir(thedir)
  426.         except:
  427.             self.cant_open(thedir)
  428.         else:
  429. #            check_makefile(thedir)
  430.             for file in dir:
  431.                 try:
  432.                     if os.path.islink(thedir + file):
  433.                         continue
  434.                     if (os.path.isdir(thedir + file)):
  435.                         self.scandir(thedir + "/" + file + "/")
  436.                     self.the_dir = thedir
  437.                     if file[-2:] == '.c' or file[-2:] == '.h':
  438.                         self.file = file
  439.                         self.new_file()
  440.                         file = thedir + file
  441.                         try:
  442.                             fd = open(file, 'r')
  443.                         except IOError:
  444.                             self.cant_open(file)
  445.                         else:
  446.                             for self.line in fd.readlines():
  447.                                 if self.nb_line <= 9:
  448.                                     self.check_header()
  449.                                 else:
  450.                                     self.check_line()
  451.                                 self.nb_line = self.nb_line + 1
  452.                                 fd.close()
  453.                 except:
  454.                     print("Issue on %s: Please do the norm manually"% file)
  455.  
  456.     def get_user(self):
  457.         try:
  458.             fd = open(sys.argv[1] + 'auteur')
  459.         except IOError:
  460.             user = os.getenv('USER')
  461.             self.user.append(user)
  462.             try:
  463.                 self.user.append(pwd.getpwnam(user)[4]) #Recuperation du nom complet de l'utilisateur
  464.             except:
  465.                 pass
  466.         else:
  467.             buffer = fd.read()
  468.             fd.close()
  469.             p = re.compile('([\w]*)')
  470.             test = re.findall(p, buffer)
  471.             for user in test:
  472.                 if user:
  473.                     self.user.append(user)
  474.                     self.user.append(pwd.getpwnam(user)[4])
  475.  
  476.  
  477. def check_makefile(thedir):
  478.     file = thedir + "Makefile"
  479.     if os.path.isfile(file):
  480.         try:
  481.             fd = open(file, 'r')
  482.         except IOError:
  483.             print("Impossible d'ouvrir le Makefile")
  484.         else:
  485.             buffer = fd.read()
  486.             p = re.compile('(-g|-pg|-lefence)')
  487.             test = re.search(p, buffer)
  488.             if test:
  489.                 print("Options de debug dans le Makefile")
  490.             p = re.compile('(-Wall)')
  491.             test = re.search(p, buffer)
  492.             if not test:
  493.                 print("-Wall n'est pas dans le Makefile")
  494.             if buffer[:2] != "##":
  495.                 print("Header du Makefile invalide")
  496.             fd.close()
  497.  
  498. def help():
  499.     print("Aide")
  500.     print("Usage: norme.py <dir_to_scan>")
  501.     print("-verbose: affiche les messages impossible d'ouvrir")
  502.     print("-nocheat: desactive la detection de la triche")
  503.     print("-score: affiche le nombre de faute de norme")
  504.     print("-libc: active la verification des fonctions de la libc")
  505.     print("-malloc: desactive le controle du malloc")
  506.     print("-printline: affiche la ligne provoquant une erreur")
  507.     print("-return: active verifier le retour des fonctions (return ;)")
  508.     print("-comment: ne pas verifier les commentaire")
  509.     sys.exit()
  510.  
  511. def main():
  512.     if len(sys.argv) == 1:
  513.         print("Usage: norme.py <dir_to_scan>")
  514.         sys.exit()
  515.     moulin = norme()
  516.     if '-verbose' in sys.argv[1:]:
  517.         moulin.verbose = 1
  518.     if '-comment' in sys.argv[1:]:
  519.         moulin.comment = 0
  520.     if '-nocheat' in sys.argv[1:]:
  521.         moulin.cheat = 0
  522.     if '-score' in sys.argv[1:]:
  523.         moulin.score = 1
  524.     if '-libc' in sys.argv[1:]:
  525.         moulin.libc = 0
  526.     if '-malloc' in sys.argv[1:]:
  527.         moulin.malloc = 0
  528.     if '-printline' in sys.argv[1:]:
  529.         moulin.printline = 1
  530.     if '-return' in sys.argv[1:]:
  531.         moulin.creturn = 0
  532.     if '--user' in sys.argv[1:]:
  533.         try:
  534.             moulin.user.append(sys.argv[sys.argv.index("--user") + 1])
  535.         except:
  536.             pass
  537.     if '-help' in sys.argv[1:]:
  538.         help()
  539. #    if sys.argv[1][-1:] != '/':
  540. #        sys.argv[1] = sys.argv[1] + '/'
  541.     if moulin.cheat == 1:
  542.         moulin.get_user()
  543.     try:
  544.         moulin.scanfile(sys.argv[1])
  545.     except NameError:
  546.         print("Usage: norme.py <dir_to_scan>")
  547.     if moulin.score:
  548.         print(moulin.get_score(), file=sys.stderr)
  549.  
  550. if __name__ == "__main__":
  551.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement