From b3a3c82d754c6bbb893428e1adc320ad4eb03a33 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Fri, 18 Aug 2017 01:37:01 +0200 Subject: [PATCH] [DEV] correct some parsing, add separate of internal valiable and correct : at end of element --- MANIFEST.in | 1 - README.rst | 104 ++++++++++------ bin/prude | 144 +--------------------- common/.prude_lua | 152 +++++++++++++++++++++++ prude/__init__.py | 160 ++++++++++++++++++++++-- prude/debug.py | 32 ----- prude/env.py | 118 +++++++----------- prude/module.py | 209 ++++++++++++++++++++----------- prude/multiprocess.py | 66 ---------- prude/target.py | 0 prude/tools.py | 281 ------------------------------------------ test/the_test_cpp.cpp | 26 ++++ 12 files changed, 575 insertions(+), 718 deletions(-) create mode 100644 common/.prude_lua delete mode 100644 prude/multiprocess.py delete mode 100644 prude/target.py create mode 100644 test/the_test_cpp.cpp diff --git a/MANIFEST.in b/MANIFEST.in index 7f08518..9561fb1 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1 @@ include README.rst -include bash-autocompletion/monk diff --git a/README.rst b/README.rst index 633a213..12d0957 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ Prude ===== -`prude` is a generic C++ annalysing code to check language error (english). +`prude` is a generic code annalyser to check ```language``` error. The ```language``` check is the english. .. image:: https://badge.fury.io/py/prude.png @@ -14,45 +14,16 @@ Release (master) :target: https://travis-ci.org/HeeroYui/prude -.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=master&tag=Linux - :target: http://atria-soft.com/ci/HeeroYui/prude -.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=master&tag=MacOs - :target: http://atria-soft.com/ci/HeeroYui/prude -.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=master&tag=Mingw - :target: http://atria-soft.com/ci/HeeroYui/prude - - -.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=master&tag=Android - :target: http://atria-soft.com/ci/HeeroYui/prude -.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=master&tag=IOs - :target: http://atria-soft.com/ci/HeeroYui/prude - - Developement (dev) ------------------ .. image:: https://travis-ci.org/HeeroYui/prude.svg?branch=dev :target: https://travis-ci.org/HeeroYui/prude - -.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=dev&tag=Linux - :target: http://atria-soft.com/ci/HeeroYui/prude -.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=dev&tag=MacOs - :target: http://atria-soft.com/ci/HeeroYui/prude -.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=dev&tag=Mingw - :target: http://atria-soft.com/ci/HeeroYui/prude - - -.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=dev&tag=Android - :target: http://atria-soft.com/ci/HeeroYui/prude -.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=dev&tag=IOs - :target: http://atria-soft.com/ci/HeeroYui/prude - - Instructions ------------ -This is a tool to annalyse C, C++ file and determone if it have some english word that does not exist. +This is a tool to annalyse C, C++ file and determine if it have some english word that does not exist. Prude is under a FREE license that can be found in the COPYING file. @@ -63,11 +34,6 @@ git repository http://github.com/HeeroYui/prude/ -Documentation -------------- - -http://github.io/HeeroYui/prude/ - Installation ------------ @@ -89,6 +55,72 @@ Install pip on MacOs: sudo easy_install pip +developpement for prude: + + git clone http://github.com/HeeroYui/prude/ + cd prude + ./setup.py develop --user + +Documentation +------------- + +Usage +****** + +Go to your coding directory and execute: + + prude yourFileToParce.cpp + # OR (multiple files) + prude yourFileToParce.cpp other_file.py and.txt + # simply the path + prude . + +You can use some options: + + --color/-C to have beautifull color check + --recursive/-r Parse all under directories + +Create exceptions: +****************** + +prude parse all upper folder to find all file ".prude_*" and add it in the list of exceptions error. + +The search end when find the file ".prude". + +you can have: + + root_path + --> .prude + --> .prude_lua + --> .prude_tinyxml + --> module + --> submodule + --> .prude_local + --> .prude_local2 + --> my_file_cpp.cpp + --> sub_second + --> file_c.c + +The check of the file ```my_file_cpp.cpp``` use all the .prude* file and the file ```file_c.c``` only use the file on the root_path + +A prude file is contituated like: + + * ```#``` Comment the line + * ```+``` Use the end of the line to check the exact match of the string (ex: +MY_VariableStupidName) + * direct element is use to comare each word in lower case to exclude error on it (ex: destructor) + * ```!``` Command to apply at the configuration. + - ```!NO_CAPITAL_LETTER``` ==> disable the check of the word in capital letter + - ```!CAPITAL_LETTER``` ==> enable the check of the word in capital letter (default) + +Some tricky things (removed because it is errored at the declaration and no more need in library using it): + + * The namespace call are disable (ex namespace::prout) + * The parameter access are disable (ex: variable.hello() or variable->hello()) + * The "#include ..." and the "# include ..." + +Now you can play. + +Note: in the http://github.com/HeeroYui/prude/common/ you have some common C library that declare stupid thing in global... License (APACHE v2.0) --------------------- diff --git a/bin/prude b/bin/prude index f78a9cb..00bab42 100755 --- a/bin/prude +++ b/bin/prude @@ -1,148 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -## ## @author Edouard DUPIN -## ## @copyright 2012, Edouard DUPIN, all right reserved -## ## @license APACHE v2.0 (see license file) -## - -# for path inspection: -import sys -import os -import copy -import prude -import prude.debug as debug -import prude.arg as arguments -import prude.env as env -import prude.tools as tools -import prude.module as module - -myArgs = arguments.doxyArg() -myArgs.add(arguments.ArgDefine("h", "help", desc="Display this help")) -myArgs.add(arguments.ArgDefine("H", "HELP", desc="Display this help (with all compleate information)")) -myArgs.add_section("option", "Can be set one time in all case") -myArgs.add(arguments.ArgDefine("v", "verbose", list=[["0","None"],["1","error"],["2","warning"],["3","info"],["4","debug"],["5","verbose"],["6","extreme_verbose"]], desc="display makefile debug level (verbose) default =2")) -myArgs.add(arguments.ArgDefine("C", "color", desc="Display makefile output in color")) - -myArgs.add_section("cible", "generate in order set") -localArgument = myArgs.parse() - -""" - display the help of this makefile -""" -def usage(full=False): - color = debug.get_color_set() - # generic argument displayed : - myArgs.display() - print(" ex: " + sys.argv[0] + " myFile1.cpp") - exit(0) - -def check_boolean(value): - if value == "" \ - or value == "1" \ - or value == "true" \ - or value == "True" \ - or value == True: - return True - return False - -# preparse the argument to get the verbose element for debug mode -def parseGenericArg(argument, active): - debug.extreme_verbose("parse arg : " + argument.get_option_name() + " " + argument.get_arg() + " active=" + str(active)) - if argument.get_option_name() == "help": - if active==False: - usage() - return True - if argument.get_option_name() == "HELP": - if active==False: - usage(True) - return True - elif argument.get_option_name() == "verbose": - if active==True: - debug.set_level(int(argument.get_arg())) - return True - elif argument.get_option_name() == "color": - if active==True: - if check_boolean(argument.get_arg()) == True: - debug.enable_color() - else: - debug.disable_color() - return True - return False - -# parse default unique argument: -for argument in localArgument: - parseGenericArg(argument, True) - -# initialize the system ... -prude.init() - -actionDone = False; - -summary = [] - -# parse all argument -number_of_error = 0 -for argument in localArgument: - if parseGenericArg(argument, False) == True: - continue - else: - argument_value = argument.get_arg() - debug.debug("something request : '" + argument_value + "'") - if argument.get_option_name() != "": - debug.warning("Can not understand argument : '" + argument.get_option_name() + "'") - usage() - break; - if os.path.isfile(argument_value) == True: - # Single file: - tmp_count_error = module.annalyse(argument_value) - summary.append([argument_value, tmp_count_error]) - number_of_error += tmp_count_error - else: - # a full path - list_files = os.listdir(argument_value) - real_list = [] - for ff_file in list_files: - if os.path.isfile(os.path.join(argument_value,ff_file)) == False: - continue - if len(ff_file) > 3 \ - and ( ff_file[-4:].lower() == ".cpp" \ - or ff_file[-4:].lower() == ".hpp" \ - or ff_file[-4:].lower() == ".c++" \ - or ff_file[-2:].lower() == ".c" \ - or ff_file[-4:].lower() == ".h++" \ - or ff_file[-2:].lower() == ".h" \ - or ff_file[-3:].lower() == ".hh" \ - or ff_file[-3:].lower() == ".cc" \ - or ff_file[-3:].lower() == ".py" \ - or ff_file[-4:].lower() == ".lua" \ - or ff_file[-3:].lower() == ".md"): - real_list.append(os.path.join(argument_value,ff_file)) - # sort list to have all time the same order. - real_list.sort() - # TODO: Add filter if needed. - for ff_file in real_list: - debug.info("-----------------------------------------------") - tmp_count_error = module.annalyse(ff_file) - summary.append([ff_file, tmp_count_error]) - number_of_error += tmp_count_error - actionDone = True - -# if no action done : we do "all" ... -if actionDone == False: - usage() - exit(-1) - -if number_of_error != 0: - debug.info("Detected " + str(number_of_error) + " ERROR(s) on " + str(len(summary)) + " files") - for elem in summary: - if elem[1] != 0: - debug.info(elem[0] + "\r\t\t\t\t\t\t [ERROR] " + str(elem[1])) - else: - debug.info(elem[0] + "\r\t\t\t\t\t\t [ OK ]") - exit(-1); - -debug.info("[ OK ]") -exit(0); +import prude \ No newline at end of file diff --git a/common/.prude_lua b/common/.prude_lua new file mode 100644 index 0000000..8cfb164 --- /dev/null +++ b/common/.prude_lua @@ -0,0 +1,152 @@ +# This file is for prude parsing (must start with .prude_* or project file .prude) +# some possibiliries: +# - Check the compleate name with case sensitive [a-zA-Z0-9_] ==> to ignore it. format +ABC_def +# - not case-sensitive separate word camel-case and snake-case (set direct word) +# - with # simple comment +# - start with ! for global parameter ++LUA_NOREF ++LUA_REGISTRYINDEX ++LUA_GCCOLLECT +luaref +userdata ++lua_Alloc ++lua_atpanic ++lua_call ++lua_CFunction ++lua_checkstack ++lua_close ++lua_concat ++lua_cpcall ++lua_createtable ++lua_dump ++lua_equal ++lua_error ++lua_gc ++lua_getallocf ++lua_getfenv ++lua_getfield ++lua_getglobal ++lua_getmetatable ++lua_gettable ++lua_gettop ++lua_insert ++lua_Integer ++lua_isboolean ++lua_iscfunction ++lua_isfunction ++lua_islightuserdata ++lua_isnil ++lua_isnone ++lua_isnoneornil ++lua_isnumber ++lua_isstring ++lua_istable ++lua_isthread ++lua_isuserdata ++lua_lessthan ++lua_load ++lua_newstate ++lua_newtable ++lua_newthread ++lua_newuserdata ++lua_next ++lua_Number ++lua_objlen ++lua_pcall ++lua_pop ++lua_pushboolean ++lua_pushcclosure ++lua_pushcfunction ++lua_pushfstring ++lua_pushinteger ++lua_pushlightuserdata ++lua_pushliteral ++lua_pushlstring ++lua_pushnil ++lua_pushnumber ++lua_pushstring ++lua_pushthread ++lua_pushvalue ++lua_pushvfstring ++lua_rawequal ++lua_rawget ++lua_rawgeti ++lua_rawset ++lua_rawseti ++lua_Reader ++lua_register ++lua_remove ++lua_replace ++lua_resume ++lua_setallocf ++lua_setfenv ++lua_setfield ++lua_setglobal ++lua_setmetatable ++lua_settable ++lua_settop ++lua_State ++lua_status ++lua_toboolean ++lua_tocfunction ++lua_tointeger ++lua_tolstring ++lua_tonumber ++lua_topointer ++lua_tostring ++lua_tothread ++lua_touserdata ++lua_type ++lua_typename ++lua_Writer ++lua_xmove ++lua_yield ++luaL_addchar ++luaL_addlstring ++luaL_addsize ++luaL_addstring ++luaL_addvalue ++luaL_argcheck ++luaL_argerror ++luaL_Buffer ++luaL_buffinit ++luaL_callmeta ++luaL_checkany ++luaL_checkint ++luaL_checkinteger ++luaL_checklong ++luaL_checklstring ++luaL_checknumber ++luaL_checkoption ++luaL_checkstack ++luaL_checkstring ++luaL_checktype ++luaL_checkudata ++luaL_dofile ++luaL_dostring ++luaL_error ++luaL_getmetafield ++luaL_getmetatable ++luaL_gsub ++luaL_loadbuffer ++luaL_loadfile ++luaL_loadstring ++luaL_newmetatable ++luaL_newstate ++luaL_openlibs ++luaL_optint ++luaL_optinteger ++luaL_optlong ++luaL_optlstring ++luaL_optnumber ++luaL_optstring ++luaL_prepbuffer ++luaL_pushresult ++luaL_ref ++luaL_Reg ++luaL_register ++luaL_typename ++luaL_typerror ++luaL_unref ++luaL_where + diff --git a/prude/__init__.py b/prude/__init__.py index bd3f42f..61977b9 100755 --- a/prude/__init__.py +++ b/prude/__init__.py @@ -3,24 +3,162 @@ ## ## @author Edouard DUPIN ## -## @copyright 2012, Edouard DUPIN, all right reserved +## @copyright 2017, Edouard DUPIN, all right reserved ## ## @license APACHE v2.0 (see license file) ## import os import sys import fnmatch -# Local import -from . import target -from . import tools +import copy from . import debug -from . import module +from . import arg as arguments from . import env -is_init = False +from . import tools +from . import module -def init(): - global is_init; - if is_init == True: - return - +myArgs = arguments.doxyArg() +myArgs.add(arguments.ArgDefine("h", "help", desc="Display this help")) +myArgs.add_section("option", "Can be set one time in all case") +myArgs.add(arguments.ArgDefine("v", "verbose", list=[["0","None"],["1","error"],["2","warning"],["3","info"],["4","debug"],["5","verbose"],["6","extreme_verbose"]], desc="display makefile debug level (verbose) default =2")) +myArgs.add(arguments.ArgDefine("C", "color", desc="Display makefile output in color")) +myArgs.add(arguments.ArgDefine("r", "recursive", desc="Recursive check of the paths")) +myArgs.add_section("cible", "generate in order set") +localArgument = myArgs.parse() + +## Display the help of this makefile +def usage(full=False): + color = debug.get_color_set() + # generic argument displayed : + myArgs.display() + print(" ex: " + sys.argv[0] + " myFile1.cpp") + exit(0) + +def check_boolean(value): + if value == "" \ + or value == "1" \ + or value == "true" \ + or value == "True" \ + or value == True: + return True + return False + + +recursive = False; + +# preparse the argument to get the verbose element for debug mode +def parseGenericArg(argument, active): + debug.extreme_verbose("parse arg : " + argument.get_option_name() + " " + argument.get_arg() + " active=" + str(active)) + if argument.get_option_name() == "help": + if active==False: + usage() + return True + elif argument.get_option_name() == "recursive": + if active==False: + recursive = True; + return True + elif argument.get_option_name() == "verbose": + if active==True: + debug.set_level(int(argument.get_arg())) + return True + elif argument.get_option_name() == "color": + if active==True: + if check_boolean(argument.get_arg()) == True: + debug.enable_color() + else: + debug.disable_color() + return True + return False + +# parse default unique argument: +for argument in localArgument: + parseGenericArg(argument, True) + +actionDone = False; + +summary = [] + +def recursive_get(path): + out = [] + for root, directories, filenames in os.walk(path): + for filename in filenames: + #debug.info(os.path.join(root,filename)) + if len(filename) > 2 \ + and ( ff_file[-3:].lower() == ".d" \ + or ff_file[-3:].lower() == ".o"): + pass + else: + out.append(os.path.join(root,filename)) + for dir in directories: + tmp = recursive_get(os.path.join(root,dir)) + for elem in tmp: + out.append(elem) + return out + +# parse all argument +number_of_error = 0 +for argument in localArgument: + if parseGenericArg(argument, False) == True: + continue + else: + argument_value = argument.get_arg() + debug.debug("something request : '" + argument_value + "'") + if argument.get_option_name() != "": + debug.warning("Can not understand argument : '" + argument.get_option_name() + "'") + usage() + break; + if os.path.isfile(argument_value) == True: + # Single file: + tmp_count_error = module.annalyse(argument_value) + summary.append([argument_value, tmp_count_error]) + number_of_error += tmp_count_error + else: + # a full path + if recursive == True: + list_files = os.listdir(argument_value) + else: + list_files = recursive_get(argument_value) + real_list = [] + for ff_file in list_files: + if os.path.isfile(os.path.join(argument_value,ff_file)) == False: + continue + if len(ff_file) > 3 \ + and ( ff_file[-4:].lower() == ".cpp" \ + or ff_file[-4:].lower() == ".hpp" \ + or ff_file[-4:].lower() == ".c++" \ + or ff_file[-2:].lower() == ".c" \ + or ff_file[-4:].lower() == ".h++" \ + or ff_file[-2:].lower() == ".h" \ + or ff_file[-3:].lower() == ".hh" \ + or ff_file[-3:].lower() == ".cc" \ + or ff_file[-3:].lower() == ".py" \ + or ff_file[-4:].lower() == ".lua" \ + or ff_file[-3:].lower() == ".md"): + real_list.append(os.path.join(argument_value,ff_file)) + # sort list to have all time the same order. + real_list.sort() + # TODO: Add filter if needed. + for ff_file in real_list: + debug.info("-----------------------------------------------") + tmp_count_error = module.annalyse(ff_file) + summary.append([ff_file, tmp_count_error]) + number_of_error += tmp_count_error + actionDone = True + +# if no action done : we do "all" ... +if actionDone == False: + usage() + exit(-1) + +if number_of_error != 0: + debug.info("Detected " + str(number_of_error) + " ERROR(s) on " + str(len(summary)) + " files") + for elem in summary: + if elem[1] != 0: + debug.info(elem[0] + "\r\t\t\t\t\t\t [ERROR] " + str(elem[1])) + else: + debug.info(elem[0] + "\r\t\t\t\t\t\t [ OK ]") + exit(-1); + +debug.info("[ OK ]") +exit(0); diff --git a/prude/debug.py b/prude/debug.py index 4870497..22bd375 100644 --- a/prude/debug.py +++ b/prude/debug.py @@ -9,7 +9,6 @@ ## import os -import threading import re debug_level=3 @@ -23,9 +22,6 @@ color_blue = "" color_purple = "" color_cyan = "" - -debug_lock = threading.Lock() - def set_level(id): global debug_level debug_level = id @@ -72,82 +68,57 @@ def disable_color(): color_cyan = "" def extreme_verbose(input, force=False): - global debug_lock global debug_level if debug_level >= 6 \ or force == True: - debug_lock.acquire() print(color_blue + input + color_default) - debug_lock.release() def verbose(input, force=False): - global debug_lock global debug_level if debug_level >= 5 \ or force == True: - debug_lock.acquire() print(color_blue + input + color_default) - debug_lock.release() def debug(input, force=False): - global debug_lock global debug_level if debug_level >= 4 \ or force == True: - debug_lock.acquire() print(color_green + input + color_default) - debug_lock.release() def info(input, force=False): - global debug_lock global debug_level if debug_level >= 3 \ or force == True: - debug_lock.acquire() print(input + color_default) - debug_lock.release() def warning(input, force=False): - global debug_lock global debug_level if debug_level >= 2 \ or force == True: - debug_lock.acquire() print(color_purple + "[WARNING] " + input + color_default) - debug_lock.release() def todo(input, force=False): - global debug_lock global debug_level if debug_level >= 3 \ or force == True: - debug_lock.acquire() print(color_purple + "[TODO] " + input + color_default) - debug_lock.release() def error(input, force=False, crash=True): - global debug_lock global debug_level if debug_level >= 1 \ or force == True: - debug_lock.acquire() print(color_red + "[ERROR] " + input + color_default) - debug_lock.release() if crash == True: exit(-1) def print_element(type, lib, dir, name, force=False): - global debug_lock global debug_level if debug_level >= 3 \ or force == True: - debug_lock.acquire() print(color_cyan + type + color_default + " : " + color_yellow + lib + color_default + " " + dir + " " + color_blue + name + color_default) - debug_lock.release() def print_compilator(myString): global debug_color - global debug_lock if debug_color == True: myString = myString.replace('\\n', '\n') myString = myString.replace('\\t', '\t') @@ -157,10 +128,7 @@ def print_compilator(myString): myString = re.sub(r'([/\w_-]+\.\w+):', r'-COLORIN-\1-COLOROUT-:', myString) myString = myString.replace('-COLORIN-', color_yellow) myString = myString.replace('-COLOROUT-', color_default) - - debug_lock.acquire() print(myString) - debug_lock.release() def get_color_set() : global color_default diff --git a/prude/env.py b/prude/env.py index 4520fc2..23742a0 100644 --- a/prude/env.py +++ b/prude/env.py @@ -3,7 +3,7 @@ ## ## @author Edouard DUPIN ## -## @copyright 2012, Edouard DUPIN, all right reserved +## @copyright 2017, Edouard DUPIN, all right reserved ## ## @license APACHE v2.0 (see license file) ## @@ -12,22 +12,6 @@ from . import debug import os - - -force_mode=False - -def set_force_mode(val): - global force_mode - if val==1: - force_mode = 1 - else: - force_mode = 0 - -def get_force_mode(): - global force_mode - return force_mode - - system_base_name = "prude" def set_system_base_name(val): @@ -40,30 +24,6 @@ def get_system_base_name(): return system_base_name -prude_root_path = os.path.join(os.getcwd()) -if os.path.exists(os.path.join(prude_root_path, "." + get_system_base_name())) == True: - # all is good ... - pass -elif os.path.exists(os.path.join(prude_root_path, "..", "." + get_system_base_name())) == True: - prude_root_path = os.path.join(os.getcwd(), "..") -elif os.path.exists(os.path.join(prude_root_path, "..", "..", "." + get_system_base_name())) == True: - prude_root_path = os.path.join(os.getcwd(), "..", "..") -elif os.path.exists(os.path.join(prude_root_path, "..", "..", "..", "." + get_system_base_name())) == True: - prude_root_path = os.path.join(os.getcwd(), "..", "..", "..") -elif os.path.exists(os.path.join(prude_root_path, "..", "..", "..", "..", "." + get_system_base_name())) == True: - prude_root_path = os.path.join(os.getcwd(), "..", "..", "..", "..") -elif os.path.exists(os.path.join(prude_root_path, "..", "..", "..", "..", "..", "." + get_system_base_name())) == True: - prude_root_path = os.path.join(os.getcwd(), "..", "..", "..", "..", "..") -elif os.path.exists(os.path.join(prude_root_path, "..", "..", "..", "..", "..", "..", "." + get_system_base_name())) == True: - prude_root_path = os.path.join(os.getcwd(), "..", "..", "..", "..", "..", "..") -else: - #debug.error("the root path of " + get_system_base_name() + " must not be upper that 6 parent path") - pass -prude_path = os.path.join(prude_root_path, "." + get_system_base_name()) - -def get_local_config_file(): - return prude_path - def file_read_data(path): if not os.path.isfile(path): return "" @@ -72,15 +32,19 @@ def file_read_data(path): file.close() return data_file -def get_local_filter(): - global capital_letter_check - capital_letter_check = True - if os.path.exists(prude_root_path) == False: - return [] +def read_file_property(folder): # parse the global .prude file filter_list = [{"check-capital":True}, [], []] - if os.path.exists(get_local_config_file()) == True: - data = file_read_data(get_local_config_file()) + list_files = os.listdir(folder) + for ff_file in list_files: + if ( len(ff_file) >= 7 \ + and ff_file[:7] == ".prude_") \ + or ff_file == ".prude": + pass + else: + continue + debug.debug("Load config file:" + os.path.join(folder,ff_file)) + data = file_read_data(os.path.join(prude_root_path,ff_file)) for elem in data.split("\n"): if elem == "": continue @@ -100,30 +64,38 @@ def get_local_filter(): filter_list[1].append(elem[1:]) else: filter_list[2].append(elem) - - list_files = os.listdir(prude_root_path) - for ff_file in list_files: - if len(ff_file) <= 7 \ - or ff_file[:7] != ".prude_": - continue - debug.debug("Load config file:" + os.path.join(prude_root_path,ff_file)) - data = file_read_data(os.path.join(prude_root_path,ff_file)) - for elem in data.split("\n"): - if elem == "": - continue - if elem[0] == "#": - continue - if elem[0] == "!": - # specific control check - if elem == "!NO_CAPITAL_LETTER": - filter_list[0]["check-capital"] = False - else: - debug.error("unknows parameter: '" + elem + "'") - continue - if elem[0] == "+": - # check the full name: - filter_list[1].append(elem[1:]) - else: - filter_list[2].append(elem) debug.verbose("fulllist:" + str(filter_list)) return filter_list + + + +def get_local_filter(path_to_search): + path_to_search = os.path.join(os.getcwd(), path_to_search) + if os.path.exists(path_to_search) == False: + return [] + + # parse the global .prude file + filter_list = [{"check-capital":True}, [], []] + current_path = path_to_search + while current_path != "/": + list_files = os.listdir(current_path) + debug.debug("read path: " + current_path) + tmp_value = read_file_property(current_path) + + for key in tmp_value[0]: + filter_list[0][key] = tmp_value[0][key] + + for elem in tmp_value[1]: + if elem not in filter_list[1]: + filter_list[1].append(elem) + + for elem in tmp_value[2]: + if elem not in filter_list[2]: + filter_list[2].append(elem.lower()) + + if os.path.exists(os.path.join(current_path, ".prude")) == True: + debug.debug("fulllist:" + str(filter_list)) + return filter_list + current_path = os.path.dirname(current_path) + debug.debug("fulllist (root):" + str(filter_list)) + return filter_list diff --git a/prude/module.py b/prude/module.py index 0454616..d00c128 100644 --- a/prude/module.py +++ b/prude/module.py @@ -3,7 +3,7 @@ ## ## @author Edouard DUPIN ## -## @copyright 2012, Edouard DUPIN, all right reserved +## @copyright 2017, Edouard DUPIN, all right reserved ## ## @license APACHE v2.0 (see license file) ## @@ -103,24 +103,119 @@ tolerate_words = [ "ll", "xll", #libc funtions - "memcpy", "strncpy", "printf", "sprintf", "fopen", "malloc", "calloc", "kalloc", + "memcpy", "strncpy", "printf", "sprintf", "fopen", "malloc", "calloc", "kalloc", "realloc", "noinline", "ramtext", "constexpr", "typename", "inline", "memset", "getchar", "putchar", - "fread", "fwrite", "gets", "puts", + "fread", "fwrite", "gets", "puts", "memmove", "iterator", #pb with number parsing: "ull", ] -application_filter = None - previous_sugestion = {} +def add_word(current_word, line, line_id, start_word_pos): + #remove end char: - . -> + while True: + if len(current_word) > 1 \ + and current_word[-1] == ':' \ + and current_word[-2] != ':': + current_word = current_word[:-1] + continue + if len(current_word) > 1 \ + and current_word[-1] == '>' \ + and current_word[-2] == '-': + current_word = current_word[:-2] + continue + while len(current_word) > 0 \ + and current_word[-1] == '.': + current_word = current_word[:-1] + continue + while len(current_word) > 0 \ + and current_word[-1] == '-': + current_word = current_word[:-1] + continue + break + tmp = re.sub(r'0(x|X)[0-9a-fA-F]+(ull|ll)?', '', current_word) + if tmp != current_word: + is_a_number = True + else: + is_a_number = False + # check if not a current Type: + if current_word in generic_cpp_type: + return { + "line":line, + "line-id":line_id, + "pos":start_word_pos, + "word":current_word, + "word-list":[[0,current_word]], + "generic-type":True, + "in-namespace":False, + "number":is_a_number + } + # separate with camelCase and snake case: + under_word_list = [] + current_sub_word = "" + offset_in_word_count = 0 + offset_in_word = None + in_namespace = False + if len(current_word.split("::")) >= 2: + in_namespace = True + if len(current_word.split("->")) >= 2: + in_namespace = True + if len(current_word.split(".")) >= 2: + in_namespace = True + for elem_word in current_word: + offset_in_word_count += 1 + if elem_word in "abcdefghijklmnopqrstuvwxyz:": + current_sub_word += elem_word + if offset_in_word == None: + offset_in_word = offset_in_word_count - 1; + elif elem_word in "0123456789": + pass + else: + if current_sub_word != "": + if elem_word in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + and current_sub_word[-1] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": + pass + else: + while len(current_sub_word) > 0 \ + and current_sub_word[-1] == ":": + current_sub_word = current_sub_word[:-1] + if current_sub_word != "": + under_word_list.append([offset_in_word,current_sub_word]) + current_sub_word = "" + offset_in_word = None + if elem_word != "_": + if offset_in_word == None: + offset_in_word = offset_in_word_count - 1; + current_sub_word += elem_word + if current_sub_word != "": + while len(current_sub_word) > 0 \ + and current_sub_word[-1] == ":": + current_sub_word = current_sub_word[:-1] + if current_sub_word != "": + under_word_list.append([offset_in_word,current_sub_word]) + # add at minimal 1 word... + if len(under_word_list) == 0: + offset_in_word == 0 + under_word_list.append([offset_in_word,current_sub_word]) + return { + "line":line, + "line-id":line_id, + "pos":start_word_pos, + "word":current_word, + "word-list":under_word_list, + "generic-type":False, + "in-namespace":in_namespace, + "number":is_a_number + } + + + def annalyse(filename): - global application_filter debug.info("Annalyse: '" + filename + "'") data = tools.file_read_data(filename) - if application_filter == None: - application_filter = env.get_local_filter() + application_filter = env.get_local_filter(os.path.dirname(filename)) line_id = 0 number_of_error = 0 # Annalyse in separate files: @@ -131,7 +226,7 @@ def annalyse(filename): line, flags=re.DOTALL) # remove the hexa string ==> not able to parse it for now ... - line = re.sub(r'0(x|X)[0-9a-fA-F]+(ull|ll)?', '', line) + #line = re.sub(r'0(x|X)[0-9a-fA-F]+(ull|ll)?', '', line) line_id += 1 if len(line) == 0: continue; @@ -153,9 +248,33 @@ def annalyse(filename): and line[:2] == "#!": # remove include handle ==> this is for later ... continue + have_special_char = False for elem in line: position_in_line += 1 - if elem in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_:": + if elem in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_": + if current_word != "" \ + and current_word[-1] == '-': + word_list.append(add_word(current_word, line, line_id, start_word_pos)) + current_word = "" + start_word_pos = None + current_word += elem + if start_word_pos == None: + start_word_pos = position_in_line + # this is to get the last word of the line + if position_in_line != len(line): + continue + if elem == '>': + #Special multiple word element... + if current_word != "" \ + and current_word[-1] == '-': + current_word += elem + else: + continue + if position_in_line != len(line): + continue + if elem in ":.-": + #Special multiple word element... + have_special_char = True current_word += elem if start_word_pos == None: start_word_pos = position_in_line @@ -163,76 +282,13 @@ def annalyse(filename): if position_in_line != len(line): continue if current_word != "": - # check if not a current Type: - if current_word in generic_cpp_type: - word_list.append({ - "line":line, - "line-id":line_id, - "pos":start_word_pos, - "word":current_word, - "word-list":[[0,current_word]], - "generic-type":True, - "in-namespace":False - }) - else: - # separate with camelCase and snake case: - under_word_list = [] - current_sub_word = "" - offset_in_word_count = 0 - offset_in_word = None - in_namespace = False - if len(current_word.split("::")) >= 2: - in_namespace = True - for elem_word in current_word: - offset_in_word_count += 1 - if elem_word in "abcdefghijklmnopqrstuvwxyz:": - current_sub_word += elem_word - if offset_in_word == None: - offset_in_word = offset_in_word_count - 1; - elif elem_word in "0123456789": - pass - else: - if current_sub_word != "": - if elem_word in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ - and current_sub_word[-1] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": - pass - else: - while len(current_sub_word) > 0 \ - and current_sub_word[-1] == ":": - current_sub_word = current_sub_word[:-1] - if current_sub_word != "": - under_word_list.append([offset_in_word,current_sub_word]) - current_sub_word = "" - offset_in_word = None - if elem_word != "_": - if offset_in_word == None: - offset_in_word = offset_in_word_count - 1; - current_sub_word += elem_word - if current_sub_word != "": - while len(current_sub_word) > 0 \ - and current_sub_word[-1] == ":": - current_sub_word = current_sub_word[:-1] - if current_sub_word != "": - under_word_list.append([offset_in_word,current_sub_word]) - # add at minimal 1 word... - if len(under_word_list) == 0: - offset_in_word == 0 - under_word_list.append([offset_in_word,current_sub_word]) - word_list.append({ - "line":line, - "line-id":line_id, - "pos":start_word_pos, - "word":current_word, - "word-list":under_word_list, - "generic-type":False, - "in-namespace":in_namespace - }) + word_list.append(add_word(current_word, line, line_id, start_word_pos)) current_word = "" start_word_pos = None for elem in word_list: - debug.extreme_verbose(" " + str(elem["pos"]) + ":" + elem["word"]) + debug.debug(" " + str(elem["pos"]) + ":" + elem["word"]) if len(elem["word-list"]) > 1: for elem_sub in elem["word-list"]: debug.extreme_verbose(" " + str(elem_sub)) @@ -246,6 +302,9 @@ def annalyse(filename): if elem["in-namespace"] == True: # nothing to parse ==> parse at the definition... continue + if elem["number"] == True: + # nothing to parse ==> parse at the definition... + continue if elem["word"] in application_filter[1]: # nothing to parse ==> parse at the definition... debug.extreme_verbose("reject global names " + elem["word"]); diff --git a/prude/multiprocess.py b/prude/multiprocess.py deleted file mode 100644 index 564be79..0000000 --- a/prude/multiprocess.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -## -## @author Edouard DUPIN -## -## @copyright 2012, Edouard DUPIN, all right reserved -## -## @license APACHE v2.0 (see license file) -## - -import sys -import threading -import time -import sys -import os -import subprocess -import shlex -# Local import -from . import debug -from . import tools -from . import env - - - -def run_command(cmd_line, store_cmd_line="", store_output_file=""): - global error_occured - global exit_flag - global current_id_execution - global error_execution - # prepare command line: - args = shlex.split(cmd_line) - debug.verbose("cmd = " + str(args)) - try: - # create the subprocess - p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - except subprocess.CalledProcessError as e: - debug.error("subprocess.CalledProcessError : TODO ...") - except: - debug.error("Exception on : " + str(args)) - # launch the subprocess: - output, err = p.communicate() - if sys.version_info >= (3, 0): - output = output.decode("utf-8") - err = err.decode("utf-8") - # store error if needed: - tools.store_warning(store_output_file, output, err) - # Check error : - if p.returncode == 0: - debug.debug(env.print_pretty(cmd_line)) - if output != "": - debug.print_compilator(output) - if err != "": - debug.print_compilator(err) - else: - # if No ID : Not in a multiprocess mode ==> just stop here - debug.debug(env.print_pretty(cmd_line), force=True) - debug.print_compilator(output) - debug.print_compilator(err) - if p.returncode == 2: - debug.error("can not compile file ... [keyboard interrrupt]") - else: - debug.error("can not compile file ... ret : " + str(p.returncode)) - debug.verbose("done 3") - # write cmd line only after to prevent errors ... - tools.store_command(cmd_line, store_cmd_line) - diff --git a/prude/target.py b/prude/target.py deleted file mode 100644 index e69de29..0000000 diff --git a/prude/tools.py b/prude/tools.py index 48f5099..16325a5 100644 --- a/prude/tools.py +++ b/prude/tools.py @@ -9,49 +9,6 @@ ## import os -import shutil -import errno -import fnmatch -import stat -# Local import -from . import debug -from . import env - -def get_run_path(): - return os.getcwd() - -def get_current_path(file): - return os.path.dirname(os.path.realpath(file)) - -def create_directory_of_file(file): - path = os.path.dirname(file) - try: - os.stat(path) - except: - os.makedirs(path) - -def get_list_sub_path(path): - # TODO : os.listdir(path) - for dirname, dirnames, filenames in os.walk(path): - return dirnames - return [] - -def remove_path_and_sub_path(path): - if os.path.isdir(path): - debug.verbose("remove path : '" + path + "'") - shutil.rmtree(path) - -def remove_file(path): - if os.path.isfile(path): - os.remove(path) - elif os.path.islink(path): - os.remove(path) - -def file_size(path): - if not os.path.isfile(path): - return 0 - statinfo = os.stat(path) - return statinfo.st_size def file_read_data(path, binary=False): if not os.path.isfile(path): @@ -64,242 +21,4 @@ def file_read_data(path, binary=False): file.close() return data_file -def version_to_string(version): - version_ID = "" - for id in version: - if len(version_ID) != 0: - if type(id) == str: - version_ID += "-" - else: - version_ID += "." - version_ID += str(id) - return version_ID - -## -## @brief Write data in a specific path. -## @param[in] path Path of the data might be written. -## @param[in] data Data To write in the file. -## @param[in] only_if_new (default: False) Write data only if data is different. -## @return True Something has been copied -## @return False Nothing has been copied -## -def file_write_data(path, data, only_if_new=False): - if only_if_new == True: - old_data = file_read_data(path) - if old_data == data: - return False - #real write of data: - create_directory_of_file(path) - file = open(path, "w") - file.write(data) - file.close() - return True - -def list_to_str(list): - if type(list) == type(str()): - return list + " " - else: - result = "" - # mulyiple imput in the list ... - for elem in list: - result += list_to_str(elem) - return result - -def add_prefix(prefix,list): - if type(list) == type(None): - return "" - if type(list) == type(str()): - return prefix+list - else: - if len(list)==0: - return '' - else: - result=[] - for elem in list: - result.append(prefix+elem) - return result - -## -## @brief Clean a path from all un-needed element in a directory -## @param[in] path Path to clean -## @param[in] normal_list List of all files/path in the path -## @return True Something has been removed -## @return False Nothing has been removed -## -def clean_directory(path, normal_list): - has_file_removed = False - # get a list of all element in the path: - for root, dirnames, filenames in os.walk(path): - for file in filenames: - file_name = os.path.join(root, file) - if file_name not in normal_list: - debug.print_element("remove file ", os.path.relpath(file_name), "==>", "---") - os.remove(file_name) - has_file_removed = True - return has_file_removed - -def filter_extention(list_files, extentions, invert=False): - out = [] - for file in list_files: - in_list = False - for ext in extentions: - if file[-len(ext):] == ext: - in_list = True - if in_list == True \ - and invert == False: - out.append(file) - elif in_list == False \ - and invert == True: - out.append(file) - return out - - -def move_if_needed(src, dst): - if not os.path.isfile(src): - debug.error("request move if needed, but file does not exist: '" + str(src) + "' to '" + str(dst) + "'") - return - src_data = file_read_data(src) - if os.path.isfile(dst): - # file exist ==> must check ... - dst_data = file_read_data(dst) - if src_data == dst_data: - # nothing to do ... - return - file_write_data(dst, src_data) - remove_file(src) - -def store_command(cmd_line, file): - # write cmd line only after to prevent errors ... - if file == "" \ - or file == None: - return; - debug.verbose("create cmd file: " + file) - # Create directory: - create_directory_of_file(file) - # Store the command Line: - file2 = open(file, "w") - file2.write(cmd_line) - file2.flush() - file2.close() - -def store_warning(file, output, err): - # write warning line only after to prevent errors ... - if file == "" \ - or file == None: - return; - if env.get_warning_mode() == False: - debug.verbose("remove warning file: " + file) - # remove file if exist... - remove_file(file); - return; - debug.verbose("create warning file: " + file) - # Create directory: - create_directory_of_file(file) - # Store the command Line: - file2 = open(file, "w") - file2.write("===== output =====\n") - file2.write(output) - file2.write("\n\n") - file2.write("===== error =====\n") - file2.write(err) - file2.write("\n\n") - file2.flush() - file2.close() - - -## List tools: -def list_append_and_check(listout, newElement, order): - for element in listout: - if element==newElement: - return - listout.append(newElement) - if order == True: - if type(newElement) is not dict: - listout.sort() - -def list_append_to(out_list, in_list, order=False): - if type(in_list) == str: - list_append_and_check(out_list, in_list, order) - elif type(in_list) == list: - # mulyiple imput in the list ... - for elem in in_list: - list_append_and_check(out_list, elem, order) - elif type(in_list) == dict: - list_append_and_check(out_list, in_list, order) - else: - debug.warning("can not add in list other than {list/dict/str} : " + str(type(in_list))) - -def list_append_to_2(listout, module, list, order=False): - # sepcial cse of bool - if type(list) == bool: - listout[module] = list - return - # add list in the Map - if module not in listout: - listout[module] = [] - # add elements... - list_append_to(listout[module], list, order) - - - -## -## @brief The vertion number can be set in an external file to permit to have a singe position to change when create a vew version -## @param[in] path_module (string) Path of the module position -## @param[in] filename_or_version (string or list) Path of the version or the real version lint parameter -## @return (list) List of version number -## -def get_version_from_file_or_direct(path_module, filename_or_version): - # check case of iser set the version directly - if type(filename_or_version) == list: - return filename_or_version - # this use a version file - file_data = file_read_data(os.path.join(path_module, filename_or_version)) - if len(file_data) == 0: - debug.warning("not enought data in the file version size=0 " + path_module + " / " + filename_or_version) - return [0,0,0] - lines = file_data.split("\n") - if len(lines) != 1: - debug.warning("More thatn one line in the file version ==> bas case use mode: 'XX', XX.YYY', 'XX.Y.ZZZ' or 'XX.Y-dev' : " + path_module + " / " + filename_or_version) - return [0,0,0] - line = lines[0] - debug.debug("Parse line: '" + line + "'") - #check if we have "-dev" - dev_mode = False - if line[-4:] == "-dev": - dev_mode = True - line = line[:-4] - out = [] - list_elem = line.split('.') - for elem in list_elem: - out.append(int(elem)) - if dev_mode == True: - out.append("dev") - debug.debug(" ==> " + str(out)) - return out - -## -## @brief Get the list of the authors frim an input list or a file -## @param[in] path_module (string) Path of the module position -## @param[in] filename_or_version (string or list) Path of the author file or the real list of authors -## @return (list) List of authors -## -def get_maintainer_from_file_or_direct(path_module, filename_or_author): - # check case of iser set the version directly - if type(filename_or_author) == list: - return filename_or_author - # this use a version file - file_data = file_read_data(os.path.join(path_module, filename_or_author)) - if len(file_data) == 0: - debug.warning("not enought data in the file author size=0 " + path_module + " / " + filename_or_author) - return [] - # One user by line and # for comment line - out = [] - for elem in file_data.split('\n'): - if len(elem) == 0: - continue - if elem[0] == "#": - # comment ... - continue - out.append(elem) - return out diff --git a/test/the_test_cpp.cpp b/test/the_test_cpp.cpp new file mode 100644 index 0000000..0d6d7ac --- /dev/null +++ b/test/the_test_cpp.cpp @@ -0,0 +1,26 @@ +uint32_t hello +// Stipd comment +::global_name_space(); + +etk::nameFunction(); + +prout->call() + +prout.call() + +prout::call() + +call-0x1562 + +call. + +call- + +call-> + +call: + +bool: + +0x1524 0x5847894ull +