Add function dectection, for detection, comments detection, typedef, struct, enum, union detection, global variable detection, prototype detection
Checks variables alignement in struct and union Checks typedef names Checks line number in functions Checks ; before and after spaces Starting check for for instruction Fix check alignement of macros Fix line number Fix tabulation alignment
This commit is contained in:
parent
98095ca4ed
commit
e83d2e5efc
491
c.py
491
c.py
@ -21,21 +21,23 @@ def validatePreprocDirective(path, content, start, start_lign, states):
|
||||
lign = start_lign
|
||||
current = start
|
||||
contentSize = len(content)
|
||||
cOnLine = 1
|
||||
cOnLine = 0
|
||||
eolAlign = -1 #Alignement de la fin de ligne
|
||||
state = 0
|
||||
directive = "" #The name of the directive
|
||||
content = "" #The rest of the line
|
||||
restol = "" #The rest of the line
|
||||
ident = 0;
|
||||
while current < contentSize and (content[current] != '\n' or content[current - 1] == '\\'):
|
||||
current += 1
|
||||
if content[current] == '\n' and content[current - 1] == '\\':
|
||||
print "new line"
|
||||
lign += 1
|
||||
cOnLine = 0
|
||||
cOnLine = -1
|
||||
if content[current - 1] == '\t':
|
||||
cOnLine += 7
|
||||
if cOnLine % 8 == 0:
|
||||
cOnLine += 8 + 1
|
||||
else:
|
||||
cOnLine += cOnLine % 8 + 1
|
||||
elif content[current] != '\n':
|
||||
cOnLine += 1
|
||||
|
||||
#Check indentation
|
||||
@ -46,12 +48,10 @@ def validatePreprocDirective(path, content, start, start_lign, states):
|
||||
|
||||
#Wrap
|
||||
if content[current] == '\\':
|
||||
print '\\'
|
||||
if eolAlign <= 0:
|
||||
eolAlign = cOnLine
|
||||
elif cOnLine != eolAlign:
|
||||
perr(path, "Bad endline", lign)
|
||||
print '\\'
|
||||
perr(path, "Bad endline preprocessor alignement (expected: {0}, real: {1})".format(eolAlign, cOnLine), lign)
|
||||
|
||||
#Spaces state
|
||||
if state == 2 or state == 4:
|
||||
@ -77,6 +77,459 @@ def validatePreprocDirective(path, content, start, start_lign, states):
|
||||
eaten = { 'chars': current - start - 1, 'lines': lign, 'col': cOnLine }
|
||||
return eaten
|
||||
|
||||
def validateType(path, content, current, lign, states):
|
||||
content += " " #Add a sentinel
|
||||
contentSize = len(content)
|
||||
state = 0
|
||||
while current + 1 < contentSize:
|
||||
if content[current] == '*' and content[current - 1] != ' ':
|
||||
perr(path, "No space before *", lign)
|
||||
elif content[current] == '=' and content[current - 1] != ' ':
|
||||
perr(path, "No space before =", lign)
|
||||
elif content[current] == '=' and content[current + 1] != ' ':
|
||||
perr(path, "No space after =", lign)
|
||||
elif content[current] == '=':
|
||||
state = 1
|
||||
elif state == 1:
|
||||
if content[current] == '*' and content[current + 1] != ' ':
|
||||
perr(path, "No space after *", lign)
|
||||
elif content[current] == '+' and content[current + 1] != ' ':
|
||||
perr(path, "No space after +", lign)
|
||||
elif content[current] == '+' and content[current - 1] != ' ':
|
||||
perr(path, "No space before +", lign)
|
||||
elif content[current] == '-' and content[current + 1] != ' ':
|
||||
perr(path, "No space before -", lign)
|
||||
elif content[current] == '-' and content[current - 1] != ' ':
|
||||
perr(path, "No space before -", lign)
|
||||
elif content[current] == '/' and content[current + 1] != ' ':
|
||||
perr(path, "No space before /", lign)
|
||||
elif content[current] == '/' and content[current - 1] != ' ':
|
||||
perr(path, "No space before /", lign)
|
||||
elif content[current] == '%' and content[current + 1] != ' ':
|
||||
perr(path, "No space before %", lign)
|
||||
elif content[current] == '%' and content[current - 1] != ' ':
|
||||
perr(path, "No space before %", lign)
|
||||
elif content[current] == '(' and content[current - 1] != ' ':
|
||||
perr(path, "Warning: it seems there is a function calling with a declaration", lign)
|
||||
|
||||
current += 1
|
||||
|
||||
def validateStruct(path, content, start, start_lign, states):
|
||||
lign = start_lign
|
||||
current = start
|
||||
contentSize = len(content)
|
||||
cOnLine = 0
|
||||
varAlign = -1
|
||||
state = 0
|
||||
lastBlank = 0
|
||||
typeName = ""
|
||||
strEc = ""
|
||||
while current < contentSize and content[current] != '}':
|
||||
if content[current] == ' ' and content[current + 1] != ';':
|
||||
typeName += strEc + ' '
|
||||
strEc = ""
|
||||
else:
|
||||
strEc += content[current]
|
||||
|
||||
#Search the struct begining
|
||||
if state == 0:
|
||||
if content[current] == '{':
|
||||
state = 1
|
||||
cOnLine = 0
|
||||
strEc = ""
|
||||
typeName = ""
|
||||
|
||||
if state == 1:
|
||||
if content[current] == ' ' or content[current] == '\t':
|
||||
lastBlank = cOnLine
|
||||
elif content[current] == '\n' and lastBlank != 0:
|
||||
#Check type
|
||||
validateType(path, typeName.strip().rstrip(), 0, start_lign, states)
|
||||
strEc = ""
|
||||
typeName = ""
|
||||
|
||||
#Check variable alignment
|
||||
if varAlign == -1:
|
||||
varAlign = lastBlank
|
||||
elif lastBlank != varAlign:
|
||||
perr(path, "Bad variable alignement in a struct (expected: {0}, real: {1})".format(varAlign, lastBlank), lign)
|
||||
elif content[current] == ',':
|
||||
perr(path, "Two variable declarations aren't allowed on the same line", lign)
|
||||
elif content[current] == ';' and content[current - 1] == ' ':
|
||||
perr(path, "There are a space before ;", lign)
|
||||
|
||||
if content[current] == '\n':
|
||||
lign += 1
|
||||
cOnLine = -1
|
||||
lastBlank = 0
|
||||
current += 1
|
||||
if content[current - 1] == '\t':
|
||||
if cOnLine % 8 == 0:
|
||||
cOnLine += 9
|
||||
else:
|
||||
cOnLine += cOnLine % 8 + 1
|
||||
else:
|
||||
cOnLine += 1
|
||||
|
||||
while current < contentSize and content[current] != ';':
|
||||
cOnLine += 1
|
||||
current += 1
|
||||
if content[current] == ';' and content[current - 1] == ' ':
|
||||
perr(path, "There is a space before ;", lign)
|
||||
|
||||
eaten = { 'chars': current - start - 1, 'lines': lign, 'col': cOnLine }
|
||||
return eaten
|
||||
|
||||
def validateUnion(path, content, start, start_lign, states):
|
||||
lign = start_lign
|
||||
current = start
|
||||
contentSize = len(content)
|
||||
cOnLine = 0
|
||||
varAlign = -1
|
||||
state = 0
|
||||
lastBlank = 0
|
||||
typeName = ""
|
||||
strEc = ""
|
||||
while current < contentSize and content[current] != '}':
|
||||
if content[current] == ' ' and content[current + 1] != ';':
|
||||
typeName += strEc + ' '
|
||||
strEc = ""
|
||||
else:
|
||||
strEc += content[current]
|
||||
|
||||
#Search the union begining
|
||||
if state == 0:
|
||||
if content[current] == '{':
|
||||
state = 1
|
||||
cOnLine = 0
|
||||
strEc = ""
|
||||
typeName = ""
|
||||
|
||||
if state == 1:
|
||||
if content[current] == ' ' or content[current] == '\t':
|
||||
lastBlank = cOnLine
|
||||
elif content[current] == '\n' and lastBlank != 0:
|
||||
#Check type
|
||||
validateType(path, typeName.strip().rstrip(), 0, start_lign, states)
|
||||
strEc = ""
|
||||
typeName = ""
|
||||
|
||||
#Check variable alignment
|
||||
if varAlign == -1:
|
||||
varAlign = lastBlank
|
||||
elif lastBlank != varAlign:
|
||||
perr(path, "Bad variable alignement in an union (expected: {0}, real: {1})".format(varAlign, lastBlank), lign)
|
||||
elif content[current] == ',':
|
||||
perr(path, "Two variable declarations aren't allowed on the same line", lign)
|
||||
elif content[current] == ';' and content[current - 1] == ' ':
|
||||
perr(path, "There is a space before ;", lign)
|
||||
|
||||
if content[current] == '\n':
|
||||
lign += 1
|
||||
cOnLine = -1
|
||||
lastBlank = 0
|
||||
current += 1
|
||||
if content[current - 1] == '\t':
|
||||
if cOnLine % 8 == 0:
|
||||
cOnLine += 9
|
||||
else:
|
||||
cOnLine += cOnLine % 8 + 1
|
||||
else:
|
||||
cOnLine += 1
|
||||
|
||||
while current < contentSize and content[current] != ';':
|
||||
cOnLine += 1
|
||||
current += 1
|
||||
if content[current] == ';' and content[current - 1] == ' ':
|
||||
perr(path, "There is a space before ;", lign)
|
||||
|
||||
eaten = { 'chars': current - start - 1, 'lines': lign, 'col': cOnLine }
|
||||
return eaten
|
||||
|
||||
def validateEnum(path, content, start, start_lign, states):
|
||||
lign = start_lign
|
||||
current = start
|
||||
contentSize = len(content)
|
||||
cOnLine = 0
|
||||
varAlign = -1
|
||||
state = 0
|
||||
while current < contentSize and content[current] != '}':
|
||||
#Search the enum begining
|
||||
if state == 0:
|
||||
if content[current] == '{':
|
||||
state = 1
|
||||
cOnLine = 0
|
||||
|
||||
if state == 1:
|
||||
if content[current] == '=' and content[current + 1] != ' ':
|
||||
perr(path, "Missing space after =", lign)
|
||||
if content[current] == '=' and content[current - 1] != ' ':
|
||||
perr(path, "Missing space before =", lign)
|
||||
if content[current] == ',' and content[current + 1] != '\n':
|
||||
perr(path, "Two statements on the same line", lign)
|
||||
|
||||
if content[current] == '\n':
|
||||
lign += 1
|
||||
cOnLine = -1
|
||||
if content[current - 1] == '\t':
|
||||
if cOnLine % 8 == 0:
|
||||
cOnLine += 9
|
||||
else:
|
||||
cOnLine += cOnLine % 8 + 1
|
||||
else:
|
||||
cOnLine += 1
|
||||
current += 1
|
||||
|
||||
while current < contentSize and content[current] != ';':
|
||||
cOnLine += 1
|
||||
current += 1
|
||||
if content[current] == ';' and content[current - 1] == ' ':
|
||||
perr(path, "There is a space before ;", lign)
|
||||
|
||||
eaten = { 'chars': current - start - 1, 'lines': lign, 'col': cOnLine }
|
||||
return eaten
|
||||
|
||||
|
||||
def validateTypedef(path, content, start, start_lign, states):
|
||||
lign = start_lign
|
||||
current = start
|
||||
contentSize = len(content)
|
||||
cOnLine = 0
|
||||
newname = "" #The name of the typedef
|
||||
restol = "" #The rest of the line
|
||||
state = 0
|
||||
while current < contentSize and (content[current] != ';' or state > 0):
|
||||
current += 1
|
||||
if content[current] == '\n':
|
||||
lign += 1
|
||||
cOnLine = -1
|
||||
if content[current - 1] == '\t':
|
||||
if cOnLine % 8 == 0:
|
||||
cOnLine += 9
|
||||
else:
|
||||
cOnLine += cOnLine % 8 + 1
|
||||
else:
|
||||
cOnLine += 1
|
||||
|
||||
if content[current] == '{':
|
||||
state += 1
|
||||
elif content[current] == '}':
|
||||
state -= 1
|
||||
|
||||
if content[current] == ' ' and content[current + 1] != ';':
|
||||
restol += newname + ' '
|
||||
newname = ""
|
||||
else:
|
||||
newname += content[current]
|
||||
|
||||
if content[current - 1] == ' ' and content[current] == ';':
|
||||
perr(path, "There is a space before ;", lign)
|
||||
|
||||
restol = restol.strip().rstrip();
|
||||
if restol.find("struct") == 0:
|
||||
validateStruct(path, restol + ";", 0, start_lign, states)
|
||||
if newname[0] != 's' or newname[1] != '_':
|
||||
perr(path, "Bad typedef name for a struct (expected: s_; real: {0}{1})".format(newname[0], newname[1]), lign)
|
||||
elif restol.find("union") == 0:
|
||||
validateUnion(path, restol + ";", 0, start_lign, states)
|
||||
if newname[0] != 'u' or newname[1] != '_':
|
||||
perr(path, "Bad typedef name for an union (expected: u_; real: {0}{1})".format(newname[0], newname[1]), lign)
|
||||
elif restol.find("enum") == 0:
|
||||
validateEnum(path, restol + ";", 0, start_lign, states)
|
||||
if newname[0] != 'e' or newname[1] != '_':
|
||||
perr(path, "Bad typedef name for an enum (expected: e_; real: {0}{1})".format(newname[0], newname[1]), lign)
|
||||
else:
|
||||
validateType(path, restol, 0, start_lign, states)
|
||||
if newname[0] != 't' or newname[1] != '_':
|
||||
perr(path, "Bad typedef name (expected: t_; real: {0}{1})".format(newname[0], newname[1]), lign)
|
||||
|
||||
eaten = { 'chars': current - start - 1, 'lines': lign, 'col': cOnLine }
|
||||
return eaten
|
||||
|
||||
|
||||
def validateFor(path, content, start, start_lign, states):
|
||||
lign = start_lign
|
||||
current = start
|
||||
contentSize = len(content)
|
||||
cOnLine = 0
|
||||
stack = -1
|
||||
while current < contentSize and (content[current] != ')' or stack >= 0):
|
||||
current += 1
|
||||
if content[current] == '\n':
|
||||
lign += 1
|
||||
cOnLine = -1
|
||||
if content[current - 1] == '\t':
|
||||
if cOnLine % 8 == 0:
|
||||
cOnLine += 9
|
||||
else:
|
||||
cOnLine += cOnLine % 8 + 1
|
||||
elif content[current] != '\n':
|
||||
cOnLine += 1
|
||||
|
||||
if content[current] == ';':
|
||||
if content[current - 1] == ' ' and content[current - 2] != ';':
|
||||
perr(path, "There is a space before ;", lign)
|
||||
if content[current + 1] != ' ':
|
||||
perr(path, "There is no space after ;", lign)
|
||||
|
||||
if content[current] == '(':
|
||||
stack += 1
|
||||
elif content[current] == ')':
|
||||
stack -= 1
|
||||
|
||||
if content[current] == ')':
|
||||
if content[current - 1] == ' ' and content[current - 2] != ';':
|
||||
perr(path, "There is a space before )", lign)
|
||||
if content[current - 1] == ';':
|
||||
perr(path, "There is no space before ), expected one in this case", lign)
|
||||
|
||||
eaten = { 'chars': current - start + 1, 'lines': lign, 'col': cOnLine }
|
||||
return eaten
|
||||
|
||||
|
||||
def validateComment(path, content, start, start_lign, states):
|
||||
lign = start_lign
|
||||
current = start
|
||||
contentSize = len(content)
|
||||
while current + 1 < contentSize and content[current] != '*' and content[current + 1] != '/':
|
||||
current += 1
|
||||
|
||||
eaten = { 'chars': current - start - 1, 'lines': lign }
|
||||
return eaten
|
||||
|
||||
|
||||
def validateFunction(path, content, start, start_lign, states, prototype):
|
||||
lign = start_lign
|
||||
nbLign = 0
|
||||
current = start
|
||||
contentSize = len(content)
|
||||
cOnLine = 0
|
||||
stack = 0
|
||||
while current < contentSize and (content[current] != '}' or stack >= 0):
|
||||
current += 1
|
||||
if content[current] == '\n':
|
||||
if cOnLine > 0:
|
||||
nbLign += 1
|
||||
lign += 1
|
||||
cOnLine = -1
|
||||
if content[current - 1] == '\t':
|
||||
if cOnLine % 8 == 0:
|
||||
cOnLine += 9
|
||||
else:
|
||||
cOnLine += cOnLine % 8 + 1
|
||||
elif content[current] != '\n':
|
||||
cOnLine += 1
|
||||
|
||||
if content[current - 2] == 'f' and content[current - 1] == 'o' and content[current] == 'r':
|
||||
eaten = validateFor(path, content, current, lign, states)
|
||||
cOnLine = eaten['col'];
|
||||
current += eaten['chars'];
|
||||
lign = eaten['lines'];
|
||||
|
||||
if content[current - 1] == ';' and content[current] != '\n':
|
||||
perr(path, "There is a ; without new line after", lign)
|
||||
|
||||
if content[current] == '{':
|
||||
stack += 1
|
||||
elif content[current] == '}':
|
||||
stack -= 1
|
||||
|
||||
#Skip lines containing comments in the count
|
||||
if content[current] == "/" == content[current - 1]:
|
||||
nbLign -= 1
|
||||
elif content[current] == "/" and content[current - 1] == "*":
|
||||
eaten = validateComment(path, content, current, lign, states)
|
||||
current += eaten['chars']
|
||||
lign += eaten['lines']
|
||||
|
||||
if nbLign > 25:
|
||||
perr(path, "To many line in this function: {0}".format(nbLign), start_lign)
|
||||
#else:
|
||||
# perr(path, "This function is a {0} lines function, good :)".format(nbLign), start_lign)
|
||||
|
||||
eaten = { 'chars': current - start - 1, 'lines': lign, 'col': cOnLine }
|
||||
return eaten
|
||||
|
||||
|
||||
def validateVarOrProto(path, content, start, start_lign, states):
|
||||
return 1
|
||||
|
||||
|
||||
def validateFunOrGlobal(path, content, start, start_lign, states):
|
||||
lign = start_lign
|
||||
current = start
|
||||
contentSize = len(content)
|
||||
cOnLine = 0
|
||||
restol = "" #The rest of the line
|
||||
while current < contentSize and content[current] != ';' and content[current] != '{':
|
||||
current += 1
|
||||
if content[current] == '\n':
|
||||
lign += 1
|
||||
cOnLine = -1
|
||||
if content[current - 1] == '\t':
|
||||
if cOnLine % 8 == 0:
|
||||
cOnLine += 9
|
||||
else:
|
||||
cOnLine += cOnLine % 8 + 1
|
||||
elif content[current] != '\n':
|
||||
cOnLine += 1
|
||||
|
||||
if content[current] != '\n':
|
||||
restol += content[current]
|
||||
|
||||
if content[current] == '{':
|
||||
eaten = validateFunction(path, content, current, lign, states, restol)
|
||||
|
||||
current += eaten['chars']
|
||||
cOnLine = eaten['col']
|
||||
lign = eaten['lines']
|
||||
else:
|
||||
eaten = validateVarOrProto(path, content, current, lign, states)
|
||||
|
||||
eaten = { 'chars': current - start, 'lines': lign, 'col': cOnLine }
|
||||
return eaten
|
||||
|
||||
|
||||
def validateExternalWord(path, content, start, start_lign, states):
|
||||
lign = start_lign
|
||||
current = start
|
||||
contentSize = len(content)
|
||||
cOnLine = 0
|
||||
directive = "" #The name of the directive
|
||||
while current < contentSize and content[current] != '\n':
|
||||
#Search keyword
|
||||
if content[current] != ' ' and content[current] != '\t':
|
||||
directive += content[current]
|
||||
else:
|
||||
if directive == "typedef":
|
||||
eaten = validateTypedef(path, content, current, lign, states)
|
||||
elif directive == "struct":
|
||||
eaten = validateStruct(path, content, current, lign, states)
|
||||
elif directive == "enum":
|
||||
eaten = validateEnum(path, content, current, lign, states)
|
||||
elif directive == "union":
|
||||
eaten = validateUnion(path, content, current, lign, states)
|
||||
else:
|
||||
eaten = validateFunOrGlobal(path, content, current, lign, states)
|
||||
|
||||
current += eaten['chars']
|
||||
cOnLine = eaten['col']
|
||||
lign = eaten['lines']
|
||||
|
||||
current += 1
|
||||
if content[current - 1] == '\t':
|
||||
if cOnLine % 8 == 0:
|
||||
cOnLine += 9
|
||||
else:
|
||||
cOnLine += cOnLine % 8 + 1
|
||||
else:
|
||||
cOnLine += 1
|
||||
|
||||
|
||||
eaten = { 'chars': current - start - 1, 'lines': lign, 'col': cOnLine }
|
||||
return eaten
|
||||
|
||||
|
||||
def checkFile(path, opt):
|
||||
numLign = 1
|
||||
with open(path, "r") as fp:
|
||||
@ -101,23 +554,37 @@ def checkFile(path, opt):
|
||||
perr(path, "Preprocessor directive mark not on the first column", numLign)
|
||||
eaten = validatePreprocDirective(path, content, current, numLign, states)
|
||||
current += eaten['chars']
|
||||
cOnLine += eaten['col']
|
||||
cOnLine = eaten['col']
|
||||
numLign = eaten['lines']
|
||||
|
||||
#String
|
||||
elif content[current] == '"':
|
||||
print "str"
|
||||
eatenChar = validateString(path, content, current, numLign)
|
||||
current += eatenChar
|
||||
cOnLine += eatenChar
|
||||
|
||||
#Comments
|
||||
elif content[current] == '*' and content[current - 1] == '/':
|
||||
eaten = validateComment(path, content, current, numLign, states)
|
||||
current += eaten['chars']
|
||||
cOnLine = 0
|
||||
numLign = eaten['lines']
|
||||
|
||||
#Skip empty lines
|
||||
elif content[current] != '\n':
|
||||
eaten = validateExternalWord(path, content, current, numLign, states)
|
||||
current += eaten['chars']
|
||||
cOnLine = eaten['col']
|
||||
numLign = eaten['lines']
|
||||
|
||||
if last_nblank == cOnLine and content[current] == ' ' or content[current] == '\t':
|
||||
last_nblank += 1
|
||||
current += 1
|
||||
cOnLine += 1
|
||||
|
||||
print("Ce fichier contient {0} lignes".format(numLign + 1))
|
||||
#print("Ce fichier contient {0} lignes".format(numLign))
|
||||
|
||||
import sys
|
||||
#import sys
|
||||
|
||||
checkFile(sys.argv[1], dict())
|
||||
#checkFile(sys.argv[1], dict())
|
||||
|
Reference in New Issue
Block a user