Example #1
0
    def setup(self):

        self.parser = CParser(process_all=False)
Example #2
0
 def setup(self):
     path = os.path.join(os.path.dirname(__file__), 'test.pyclibcache')
     parser = CParser(['ctypes_test.h'])
     parser.write_cache(path)
     self.library = CLibrary(_ctypes_test.__file__, ['ctypes_test.h'],
                             cache=path)
Example #3
0
class TestPreprocessing(object):
    """Test preprocessing.

    """

    h_dir = os.path.join(H_DIRECTORY, "macros")

    def setup(self):

        self.parser = CParser(process_all=False)

    def test_values(self):

        path = os.path.join(self.h_dir, "macro_values.h")
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)

        macros = self.parser.defs["macros"]
        values = self.parser.defs["values"]

        assert "M" in macros and macros["M"] == ""
        assert "N" in macros and macros["N"] == "n" and values["N"] is None

        # Decimal integer
        assert "MACRO_D1" in macros and macros["MACRO_D1"] == "1" and values["MACRO_D1"] == 1
        assert "MACRO_D2" in macros and macros["MACRO_D2"] == "-2U" and values["MACRO_D2"] == -2
        assert "MACRO_D3" in macros and macros["MACRO_D3"] == "+ 3UL" and values["MACRO_D3"] == 3

        # Bit shifted decimal integer
        assert "MACRO_SD1" in macros and macros["MACRO_SD1"] == "(1 << 1)" and values["MACRO_SD1"] == 2
        assert "MACRO_SD2" in macros and macros["MACRO_SD2"] == "(2U << 2)" and values["MACRO_SD2"] == 8
        assert "MACRO_SD3" in macros and macros["MACRO_SD3"] == "(3UL << 3)" and values["MACRO_SD3"] == 24

        # Hexadecimal integer
        assert "MACRO_H1" in macros and macros["MACRO_H1"] == "+0x000000" and values["MACRO_H1"] == 0
        assert "MACRO_H2" in macros and macros["MACRO_H2"] == "- 0x000001U" and values["MACRO_H2"] == -1
        assert "MACRO_H3" in macros and macros["MACRO_H3"] == "0X000002UL" and values["MACRO_H3"] == 2

        # Bit shifted hexadecimal integer
        assert "MACRO_SH1" in macros and macros["MACRO_SH1"] == "(0x000000 << 1)" and values["MACRO_SH1"] == 0
        assert "MACRO_SH2" in macros and macros["MACRO_SH2"] == "(0x000001U << 2)" and values["MACRO_SH2"] == 4
        assert "MACRO_H3" in macros and macros["MACRO_SH3"] == "(0X000002UL << 3)" and values["MACRO_SH3"] == 16

        # Floating point value
        assert "MACRO_F1" in macros and macros["MACRO_F1"] == "1.0" and values["MACRO_F1"] == 1.0
        assert "MACRO_F2" in macros and macros["MACRO_F2"] == "1.1e1" and values["MACRO_F2"] == 11.0
        assert "MACRO_F3" in macros and macros["MACRO_F3"] == "-1.1E-1" and values["MACRO_F3"] == -0.11

        # String macro
        assert "MACRO_S" in macros and macros["MACRO_S"] == '"test"' and values["MACRO_S"] == "test"

        # Nested macros
        assert "NESTED" in macros and macros["NESTED"] == "1" and values["NESTED"] == 1
        assert "NESTED2" in macros and macros["NESTED2"] == "1" and values["NESTED2"] == 1
        assert "MACRO_N" in macros and macros["MACRO_N"] == "1 + 2" and values["MACRO_N"] == 3

        # Muliline macro
        assert "MACRO_ML" in macros and values["MACRO_ML"] == 2

    def test_conditionals(self):

        path = os.path.join(self.h_dir, "macro_conditionals.h")
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)
        self.parser.parse_defs(path)

        macros = self.parser.defs["macros"]
        stream = self.parser.files[path]

        # Test if defined conditional
        assert "DEFINE_IF" in macros
        assert "  int DECLARE_IF;\n" in stream
        assert "NO_DEFINE_IF" not in macros
        assert "  int NO_DECLARE_IF;\n" not in stream

        # Test ifdef conditional
        assert "DEFINE_IFDEF" in macros
        assert "  int DECLARE_IFDEF;\n" in stream
        assert "NO_DEFINE_IFDEF" not in macros
        assert "  int NO_DECLARE_IFDEF;\n" not in stream

        # Test if !defined
        assert "DEFINE_IFN" in macros
        assert "  int DECLARE_IFN;\n" in stream
        assert "NO_DEFINE_IFN" not in macros
        assert "  int NO_DECLARE_IFN;\n" not in stream

        # Test ifndef
        assert "DEFINE_IFNDEF" in macros
        assert "  int DECLARE_IFNDEF;\n" in stream
        assert "NO_DEFINE_IFNDEF" not in macros
        assert "  int NO_DECLARE_IFNDEF;\n" not in stream

        # Test elif
        assert "DEFINE_ELIF" in macros
        assert "  int DECLARE_ELIF;\n" in stream
        assert "NO_DEFINE_ELIF" not in macros
        assert "  int NO_DECLARE_ELIF;\n" not in stream

        # Test else
        assert "DEFINE_ELSE" in macros
        assert "  int DECLARE_ELSE;\n" in stream
        assert "NO_DEFINE_ELSE" not in macros
        assert "  int NO_DECLARE_ELSE;\n" not in stream

        # Test nested
        assert "DEFINE_N1" in macros
        assert "  int DECLARE_N1;\n" in stream
        assert "NO_DEFINE_N2" not in macros
        assert "DEFINE_N2" not in macros

        assert "DEFINE_N3" in macros
        assert "NO_DEFINE_N3" not in macros
        assert "  int NO_DECLARE_N3;\n" not in stream

        # Test logical
        assert "DEFINE_LOG" in macros
        assert "  int DECLARE_LOG;\n" in stream
        assert "NO_DEFINE_LOG" not in macros
        assert "NO_DEFINE_LOG" not in macros

        # Test undef
        assert "DEFINE_UNDEF" in macros
        assert "UNDEF" not in macros

    def test_macro_function(self):

        path = os.path.join(self.h_dir, "macro_functions.h")
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)
        self.parser.parse_defs(path)

        values = self.parser.defs["values"]
        fnmacros = self.parser.defs["fnmacros"]
        stream = self.parser.files[path]

        # Test macro declaration.
        assert "CARRE" in fnmacros
        assert "int carre = 2*2;" in stream

        assert "int __declspec(dllexport) function2()" in stream
        assert "__declspec(dllexport) int function3()" in stream
        assert "__declspec(dllexport) int * function4()" in stream

        # Test defining a macro function as an alias for another one.
        assert "MAKEINTRESOURCEA" in fnmacros
        assert "MAKEINTRESOURCEW" in fnmacros
        assert "MAKEINTRESOURCE" in fnmacros
        assert fnmacros["MAKEINTRESOURCE"] == fnmacros["MAKEINTRESOURCEA"]
        assert "int x = ((LPSTR)((ULONG_PTR)((WORD)(4))))"

        # Test using a macro value in a macro function call
        assert "BIT" in values and values["BIT"] == 1
        assert "((y) |= (0x01))" in stream

        # Test defining a macro function calling other macros (values and
        # functions)
        assert "SETBITS" in fnmacros
        assert "int z1, z2 = (((1) |= (0x01)), ((2) |= (0x01)));" in stream

        # Test defining a macro function calling nested macro functions
        assert "SETBIT_AUTO" in fnmacros
        assert "int z3 = ((((3) |= (0x01)), ((3) |= (0x01))));" in stream

    def test_pragmas(self):

        path = os.path.join(self.h_dir, "pragmas.h")
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)
        self.parser.parse_defs(path)

        stream = self.parser.files[path]
        packings = self.parser.pack_list[path]

        # Check all pragmas instructions have been removed.
        assert stream.strip() == ""

        assert packings[1][1] is None
        assert packings[2][1] == 4
        assert packings[3][1] == 16
        assert packings[4][1] is None
        assert packings[5][1] is None
        assert packings[6][1] == 4
        assert packings[7][1] == 16
        assert packings[8][1] is None
Example #4
0
class TestParsing(object):
    """Test parsing.

    """

    h_dir = H_DIRECTORY

    def setup(self):

        self.parser = CParser(process_all=False)

    def test_variables(self):

        path = os.path.join(self.h_dir, "variables.h")
        self.parser.load_file(path)
        self.parser.process_all()

        variables = self.parser.defs["variables"]

        # Integers
        assert "short1" in variables and variables["short1"] == (1, Type("signed short"))
        assert "short_int" in variables and variables["short_int"] == (1, Type("short int"))
        assert "short_un" in variables and variables["short_un"] == (1, Type("unsigned short"))
        assert "short_int_un" in variables and variables["short_int_un"] == (1, Type("unsigned short int"))
        assert "int1" in variables and variables["int1"] == (1, Type("int"))
        assert "un" in variables and variables["un"] == (1, Type("unsigned"))
        assert "int_un" in variables and variables["int_un"] == (1, Type("unsigned int"))
        assert "long1" in variables and variables["long1"] == (1, Type("long"))
        assert "long_int" in variables and variables["long_int"] == (1, Type("long int"))
        assert "long_un" in variables and variables["long_un"] == (1, Type("unsigned long"))
        assert "long_int_un" in variables and variables["long_int_un"] == (1, Type("unsigned long int"))
        if sys.platform == "win32":
            assert "int64" in variables and variables["int64"] == (1, Type("__int64"))
            assert "int64_un" in variables and variables["int64_un"] == (1, Type("unsigned __int64"))
        assert "long_long" in variables and variables["long_long"] == (1, Type("long long"))
        assert "long_long_int" in variables and variables["long_long_int"] == (1, Type("long long int"))
        assert "long_long_un" in variables and variables["long_long_un"] == (1, Type("unsigned long long"))
        assert "long_long_int_un" in variables and variables["long_long_int_un"] == (
            1,
            Type("unsigned long " "long int"),
        )

        # Floating point number
        assert "fl" in variables and variables["fl"] == (1.0, Type("float"))
        assert "db" in variables and variables["db"] == (0.1, Type("double"))
        assert "dbl" in variables and variables["dbl"] == (-10.0, Type("long double"))

        # Const and static modif
        assert "int_const" in variables and variables["int_const"] == (4, Type("int", type_quals=(("const",),)))
        assert "int_stat" in variables and variables["int_stat"] == (4, Type("int"))
        assert "int_con_stat" in variables and variables["int_con_stat"] == (4, Type("int", type_quals=(("const",),)))
        assert "int_extern" in variables and variables["int_extern"] == (4, Type("int"))

        # String
        assert "str1" in variables and variables["str1"] == ("normal string", Type("char", "*"))
        assert "str2" in variables and variables["str2"] == ("string with macro: INT", Type("char", "*", "*"))
        assert "str3" in variables and variables["str3"] == (
            "string with comment: /*comment inside string*/",
            Type("char", "*", type_quals=(("const",), ("const",))),
        )
        assert "str4" in variables and variables["str4"] == (
            "string with define #define MACRO5 macro5_in_string ",
            Type("char", "*"),
        )
        assert "str5" in variables and variables["str5"] == ('string with "escaped quotes" ', Type("char", "*"))

        # Test complex evaluation
        assert "x1" in variables and variables["x1"] == (1.0, Type("float"))

        # Test type casting handling.
        assert "x2" in variables and variables["x2"] == (88342528, Type("int"))

        # Test array handling
        assert "array" in variables and variables["array"] == ([1, 3141500.0], Type("float", [2]))
        assert "intJunk" in variables and variables["intJunk"] == (
            None,
            Type("int", "*", "*", "*", [4], type_quals=(("const",), ("const",), (), (), ())),
        )

        # test type qualifiers
        assert variables.get("typeQualedIntPtrPtr") == (
            None,
            Type("int", "*", "*", type_quals=(("const",), ("volatile",), ())),
        )
        assert variables.get("typeQualedIntPtr") == (None, Type("int", "*", type_quals=(("const", "volatile"), ())))

        # test type definition precedence
        assert variables.get("prec_ptr_of_arr") == (None, Type("int", [1], "*"))
        assert variables.get("prec_arr_of_ptr") == (None, Type("int", "*", [1]))
        assert variables.get("prec_arr_of_ptr2") == (None, Type("int", "*", [1]))

    # No structure, no unions, no enum
    def test_typedef(self):

        path = os.path.join(self.h_dir, "typedefs.h")
        self.parser.load_file(path)
        self.parser.process_all()

        types = self.parser.defs["types"]
        variables = self.parser.defs["variables"]

        # Test defining types from base types.
        assert "typeChar" in types and types["typeChar"] == Type("char", "*", "*")
        assert "typeInt" in types and types["typeInt"] == Type("int")
        assert "typeIntPtr" in types and types["typeIntPtr"] == Type("int", "*")
        assert "typeIntArr" in types and types["typeIntArr"] == Type("int", [10])
        assert "typeIntDArr" in types and types["typeIntDArr"] == Type("int", [5], [6])
        assert "typeTypeInt" in types and types["typeTypeInt"] == Type("typeInt")
        assert not self.parser.is_fund_type("typeTypeInt")
        assert self.parser.eval_type(["typeTypeInt"]) == Type("int")
        assert "ULONG" in types and types["ULONG"] == Type("unsigned long")

        # Test annotated types
        assert "voidpc" in types and types["voidpc"] == Type("void", "*", type_quals=(("const",), ()))
        assert "charf" in types and types["charf"] == Type("char", type_quals=(("far",),))

        # Test using custom type.
        assert "ttip5" in variables and variables["ttip5"] == (None, Type("typeTypeInt", "*", [5]))

        # Handling undefined types
        assert "SomeOtherType" in types and types["SomeOtherType"] == Type("someType")
        assert "x" in variables and variables["x"] == (None, Type("undefined"))
        assert not self.parser.is_fund_type("SomeOtherType")
        with raises(Exception):
            self.parser.eval_type(Type("undefined"))

        # Testing recursive defs
        assert "recType1" in types
        assert "recType2" in types
        assert "recType3" in types
        with raises(Exception):
            self.parser.eval_type(Type("recType3"))

    def test_enums(self):

        path = os.path.join(self.h_dir, "enums.h")
        self.parser.load_file(path)
        self.parser.process_all()

        enums = self.parser.defs["enums"]
        types = self.parser.defs["types"]
        variables = self.parser.defs["variables"]
        print(self.parser.defs["values"])
        assert "enum_name" in enums and "enum enum_name" in types
        assert enums["enum_name"] == {"enum1": 129, "enum2": 6, "enum3": 7, "enum4": 8}
        assert types["enum enum_name"] == Type("enum", "enum_name")
        assert "enum_inst" in variables and variables["enum_inst"] == (None, Type("enum enum_name"))

        assert "anon_enum0" in enums
        assert "anon_enum1" in enums
        assert "no_name_enum_typeddef" in types

    def test_struct(self):

        path = os.path.join(self.h_dir, "structs.h")
        self.parser.load_file(path)
        self.parser.process_all()

        structs = self.parser.defs["structs"]
        types = self.parser.defs["types"]
        variables = self.parser.defs["variables"]

        # Test creating a structure using only base types.
        assert "struct_name" in structs and "struct struct_name" in types
        assert structs["struct_name"] == Struct(
            ("x", Type("int"), 1), ("y", Type("type_type_int"), None, 2), ("str", Type("char", [10]), None)
        )
        assert "struct_inst" in variables and variables["struct_inst"] == (None, Type("struct struct_name"))

        # Test creating a pointer type from a structure.
        assert "struct_name_ptr" in types and types["struct_name_ptr"] == Type("struct struct_name", "*")

        assert "struct_name2_ptr" in types and types["struct_name2_ptr"] == Type("struct anon_struct0", "*")

        # Test declaring a recursive structure.
        assert "recursive_struct" in structs and "struct recursive_struct" in types
        assert structs["recursive_struct"] == Struct(("next", Type("struct recursive_struct", "*"), None))

        # Test declaring near and far pointers.
        assert "tagWNDCLASSEXA" in structs
        assert "NPWNDCLASSEXA" in types and (
            types["NPWNDCLASSEXA"] == Type("struct tagWNDCLASSEXA", "*", type_quals=(("near",), ()))
        )

        # Test altering the packing of a structure.
        assert "struct_name_p" in structs and "struct struct_name_p" in types
        assert structs["struct_name_p"] == Struct(
            ("x", Type("int"), None),
            ("y", Type("type_type_int"), None),
            ("str", Type("char", [10]), "brace }  \0"),
            pack=16,
        )

    def test_unions(self):

        path = os.path.join(self.h_dir, "unions.h")
        self.parser.load_file(path)
        self.parser.process_all()

        unions = self.parser.defs["unions"]
        structs = self.parser.defs["structs"]
        types = self.parser.defs["types"]
        variables = self.parser.defs["variables"]

        # Test declaring an union.
        assert "union_name" in unions and "union union_name" in types
        assert unions["union_name"] == Union(("x", Type("int"), 1), ("y", Type("int"), None), pack=None)
        assert "union_name_ptr" in types and types["union_name_ptr"] == Type("union union_name", "*")

        # Test defining an unnamed union
        assert "no_name_union_inst" in variables and variables["no_name_union_inst"] == (
            None,
            Type("union anon_union0"),
        )

        # Test defining a structure using an unnamed union internally.
        assert "tagRID_DEVICE_INFO" in structs and structs["tagRID_DEVICE_INFO"] == Struct(
            ("cbSize", Type("DWORD"), None), ("dwType", Type("DWORD"), None), (None, Type("union anon_union1"), None)
        )

        assert "RID_DEVICE_INFO" in types and types["RID_DEVICE_INFO"] == Type("struct tagRID_DEVICE_INFO")
        assert "PRID_DEVICE_INFO" in types and types["PRID_DEVICE_INFO"] == Type("struct tagRID_DEVICE_INFO", "*")
        assert "LPRID_DEVICE_INFO" in types and (types["LPRID_DEVICE_INFO"] == Type("struct tagRID_DEVICE_INFO", "*"))

    def test_functions(self):

        path = os.path.join(self.h_dir, "functions.h")
        self.parser.load_file(path)
        self.parser.process_all()

        functions = self.parser.defs["functions"]
        variables = self.parser.defs["variables"]

        assert functions.get("f") == Type(Type("void"), ((None, Type("int"), None), (None, Type("int"), None)))
        assert functions["g"] == Type(
            Type("int"), (("ch", Type("char", "*"), None), ("str", Type("char", "*", "*"), None))
        )
        assert variables.get("fnPtr") == (
            None,
            Type("int", ((None, Type("char"), None), (None, Type("float"), None)), "*"),
        )
        assert functions.get("function1") == Type(Type("int", "__stdcall", type_quals=((), None)), ())

        assert functions.get("function2") == Type(Type("int"), ())

        assert "externFunc" in functions

        ptyp = Type("int", "*", "*", type_quals=(("volatile",), ("const",), ()))
        assert functions.get("typeQualedFunc") == Type(Type("int"), ((None, ptyp, None),))
Example #5
0
    def setup(self):

        self.parser = CParser(process_all=False)
Example #6
0
class TestFileHandling(object):
    """Test parser basic file operations.

    """

    h_dir = os.path.join(H_DIRECTORY, "file_handling")

    def setup(self):

        self.parser = CParser(process_all=False)

    def test_init(self):
        parser = CParser(os.path.join(self.h_dir, "replace.h"))
        assert parser.files is not None

    def test_find_file(self):

        saved_headers = pyclibrary.utils.HEADER_DIRS
        try:
            pyclibrary.utils.add_header_locations([self.h_dir])
            assert self.h_dir in pyclibrary.utils.HEADER_DIRS
            assert self.parser.find_headers(["replace.h"]) == [os.path.join(self.h_dir, "replace.h")]
        finally:
            pyclibrary.utils.HEADER_DIRS = saved_headers

        abs_hdr_path = os.path.join(self.h_dir, "replace.h")
        assert self.parser.find_headers([abs_hdr_path]) == [abs_hdr_path]
        abs_hdr_path2 = os.path.join(self.h_dir, "c_comments.h")
        assert len(self.parser.find_headers([abs_hdr_path, abs_hdr_path2])) == 2

    def test_load_file(self):

        path = os.path.join(self.h_dir, "replace.h")
        assert self.parser.load_file(path)
        assert self.parser.files[path] is not None
        assert self.parser.file_order == [path]
        assert self.parser.init_opts["replace"]["replace.h"] is None
        assert self.parser.init_opts["files"] == ["replace.h"]

    def test_load_file_and_replace(self):

        path = os.path.join(self.h_dir, "replace.h")
        rep = {"{placeholder}": "1", "placeholder2": "2"}
        assert self.parser.load_file(path, rep)

        lines = self.parser.files[path].split("\n")
        assert lines[3] == "# define MACRO 1"
        assert lines[6] == "    # define MACRO2 2"

        lines[3] = "# define MACRO {placeholder}"
        lines[6] = "    # define MACRO2 placeholder2"
        with open(path) as f:
            compare_lines(lines, f.readlines())

        assert self.parser.file_order == [path]
        assert self.parser.init_opts["replace"]["replace.h"] == rep
        assert self.parser.init_opts["files"] == ["replace.h"]

    def test_load_non_existing_file(self):

        path = os.path.join(self.h_dir, "no.h")
        assert not self.parser.load_file(path)
        assert self.parser.files[path] is None

    def test_removing_c_comments(self):

        path = os.path.join(self.h_dir, "c_comments.h")
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        with open(os.path.join(self.h_dir, "c_comments_removed.h"), "rU") as f:
            compare_lines(self.parser.files[path].split("\n"), f.readlines())

    def test_removing_cpp_comments(self):

        path = os.path.join(self.h_dir, "cpp_comments.h")
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        with open(os.path.join(self.h_dir, "cpp_comments_removed.h"), "rU") as f:
            compare_lines(self.parser.files[path].split("\n"), f.readlines())
Example #7
0
class TestPreprocessing(object):
    """Test preprocessing.

    """
    h_dir = os.path.join(H_DIRECTORY, 'macros')

    def setup(self):

        self.parser = CParser(process_all=False)

    def test_values(self):

        path = os.path.join(self.h_dir, 'macro_values.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)

        macros = self.parser.defs['macros']
        values = self.parser.defs['values']

        assert 'M' in macros and macros['M'] == ''
        assert 'N' in macros and macros['N'] == 'n' and values['N'] is None

        # Decimal integer
        assert ('MACRO_D1' in macros and macros['MACRO_D1'] == '1'
                and values['MACRO_D1'] == 1)
        assert ('MACRO_D2' in macros and macros['MACRO_D2'] == '-2U'
                and values['MACRO_D2'] == -2)
        assert ('MACRO_D3' in macros and macros['MACRO_D3'] == '+ 3UL'
                and values['MACRO_D3'] == 3)

        # Bit shifted decimal integer
        assert ('MACRO_SD1' in macros and macros['MACRO_SD1'] == '(1 << 1)'
                and values['MACRO_SD1'] == 2)
        assert ('MACRO_SD2' in macros and macros['MACRO_SD2'] == '(2U << 2)'
                and values['MACRO_SD2'] == 8)
        assert ('MACRO_SD3' in macros and macros['MACRO_SD3'] == '(3UL << 3)'
                and values['MACRO_SD3'] == 24)

        # Hexadecimal integer
        assert ('MACRO_H1' in macros and macros['MACRO_H1'] == '+0x000000'
                and values['MACRO_H1'] == 0)
        assert ('MACRO_H2' in macros and macros['MACRO_H2'] == '- 0x000001U'
                and values['MACRO_H2'] == -1)
        assert ('MACRO_H3' in macros and macros['MACRO_H3'] == '0X000002UL'
                and values['MACRO_H3'] == 2)

        # Bit shifted hexadecimal integer
        assert ('MACRO_SH1' in macros
                and macros['MACRO_SH1'] == '(0x000000 << 1)'
                and values['MACRO_SH1'] == 0)
        assert ('MACRO_SH2' in macros
                and macros['MACRO_SH2'] == '(0x000001U << 2)'
                and values['MACRO_SH2'] == 4)
        assert ('MACRO_H3' in macros
                and macros['MACRO_SH3'] == '(0X000002UL << 3)'
                and values['MACRO_SH3'] == 16)

        # Floating point value
        assert ('MACRO_F1' in macros and macros['MACRO_F1'] == '1.0'
                and values['MACRO_F1'] == 1.0)
        assert ('MACRO_F2' in macros and macros['MACRO_F2'] == '1.1e1'
                and values['MACRO_F2'] == 11.)
        assert ('MACRO_F3' in macros and macros['MACRO_F3'] == '-1.1E-1'
                and values['MACRO_F3'] == -0.11)

        # String macro
        assert ('MACRO_S' in macros and macros['MACRO_S'] == '"test"'
                and values['MACRO_S'] == 'test')

        # Nested macros
        assert ('NESTED' in macros and macros['NESTED'] == '1'
                and values['NESTED'] == 1)
        assert ('NESTED2' in macros and macros['NESTED2'] == '1'
                and values['NESTED2'] == 1)
        assert ('MACRO_N' in macros and macros['MACRO_N'] == '1 + 2'
                and values['MACRO_N'] == 3)

        # Muliline macro
        assert 'MACRO_ML' in macros and values['MACRO_ML'] == 2

    def test_conditionals(self):

        path = os.path.join(self.h_dir, 'macro_conditionals.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)
        self.parser.parse_defs(path)

        macros = self.parser.defs['macros']
        stream = self.parser.files[path]

        # Test if defined conditional
        assert 'DEFINE_IF' in macros
        assert '  int DECLARE_IF;\n' in stream
        assert 'NO_DEFINE_IF' not in macros
        assert '  int NO_DECLARE_IF;\n' not in stream

        # Test ifdef conditional
        assert 'DEFINE_IFDEF' in macros
        assert '  int DECLARE_IFDEF;\n' in stream
        assert 'NO_DEFINE_IFDEF' not in macros
        assert '  int NO_DECLARE_IFDEF;\n' not in stream

        # Test if !defined
        assert 'DEFINE_IFN' in macros
        assert '  int DECLARE_IFN;\n' in stream
        assert 'NO_DEFINE_IFN' not in macros
        assert '  int NO_DECLARE_IFN;\n' not in stream

        # Test ifndef
        assert 'DEFINE_IFNDEF' in macros
        assert '  int DECLARE_IFNDEF;\n' in stream
        assert 'NO_DEFINE_IFNDEF' not in macros
        assert '  int NO_DECLARE_IFNDEF;\n' not in stream

        # Test elif
        assert 'DEFINE_ELIF' in macros
        assert '  int DECLARE_ELIF;\n' in stream
        assert 'NO_DEFINE_ELIF' not in macros
        assert '  int NO_DECLARE_ELIF;\n' not in stream

        # Test else
        assert 'DEFINE_ELSE' in macros
        assert '  int DECLARE_ELSE;\n' in stream
        assert 'NO_DEFINE_ELSE' not in macros
        assert '  int NO_DECLARE_ELSE;\n' not in stream

        # Test nested
        assert 'DEFINE_N1' in macros
        assert '  int DECLARE_N1;\n' in stream
        assert 'NO_DEFINE_N2' not in macros
        assert 'DEFINE_N2' not in macros

        assert 'DEFINE_N3' in macros
        assert 'NO_DEFINE_N3' not in macros
        assert '  int NO_DECLARE_N3;\n' not in stream

        # Test logical
        assert 'DEFINE_LOG' in macros
        assert '  int DECLARE_LOG;\n' in stream
        assert 'NO_DEFINE_LOG' not in macros
        assert 'NO_DEFINE_LOG' not in macros

        # Test undef
        assert 'DEFINE_UNDEF' in macros
        assert 'UNDEF' not in macros

    def test_macro_function(self):

        path = os.path.join(self.h_dir, 'macro_functions.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)
        self.parser.parse_defs(path)

        values = self.parser.defs['values']
        fnmacros = self.parser.defs['fnmacros']
        stream = self.parser.files[path]

        # Test macro declaration.
        assert 'CARRE' in fnmacros
        assert 'int carre = 2*2;' in stream

        assert 'int __declspec(dllexport) function2()' in stream
        assert '__declspec(dllexport) int function3()' in stream
        assert '__declspec(dllexport) int * function4()' in stream

        # Test defining a macro function as an alias for another one.
        assert 'MAKEINTRESOURCEA' in fnmacros
        assert 'MAKEINTRESOURCEW' in fnmacros
        assert 'MAKEINTRESOURCE' in fnmacros
        assert fnmacros['MAKEINTRESOURCE'] == fnmacros['MAKEINTRESOURCEA']
        assert 'int x = ((LPSTR)((ULONG_PTR)((WORD)(4))))'

        # Test using a macro value in a macro function call
        assert 'BIT' in values and values['BIT'] == 1
        assert '((y) |= (0x01))' in stream

        # Test defining a macro function calling other macros (values and
        # functions)
        assert 'SETBITS' in fnmacros
        assert 'int z1, z2 = (((1) |= (0x01)), ((2) |= (0x01)));' in stream

        # Test defining a macro function calling nested macro functions
        assert 'SETBIT_AUTO' in fnmacros
        assert 'int z3 = ((((3) |= (0x01)), ((3) |= (0x01))));' in stream

    def test_pragmas(self):

        path = os.path.join(self.h_dir, 'pragmas.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)
        self.parser.parse_defs(path)

        stream = self.parser.files[path]
        packings = self.parser.pack_list[path]

        # Check all pragmas instructions have been removed.
        assert stream.strip() == ''

        assert packings[1][1] is None
        assert packings[2][1] == 4
        assert packings[3][1] == 16
        assert packings[4][1] is None
        assert packings[5][1] is None
        assert packings[6][1] == 4
        assert packings[7][1] == 16
        assert packings[8][1] is None
Example #8
0
class TestParsing(object):
    """Test parsing.

    """

    h_dir = H_DIRECTORY

    def setup(self):

        self.parser = CParser(process_all=False)

    def test_variables(self):

        path = os.path.join(self.h_dir, 'variables.h')
        self.parser.load_file(path)
        self.parser.process_all()

        variables = self.parser.defs['variables']

        # Integers
        assert ('short1' in variables
                and variables['short1'] == (1, Type('signed short')))
        assert ('short_int' in variables
                and variables['short_int'] == (1, Type('short int')))
        assert ('short_un' in variables
                and variables['short_un'] == (1, Type('unsigned short')))
        assert ('short_int_un' in variables and variables['short_int_un']
                == (1, Type('unsigned short int')))
        assert ('int1' in variables and variables['int1'] == (1, Type('int')))
        assert ('un' in variables and variables['un'] == (1, Type('unsigned')))
        assert ('int_un' in variables
                and variables['int_un'] == (1, Type('unsigned int')))
        assert ('long1' in variables
                and variables['long1'] == (1, Type('long')))
        assert ('long_int' in variables
                and variables['long_int'] == (1, Type('long int')))
        assert ('long_un' in variables
                and variables['long_un'] == (1, Type('unsigned long')))
        assert ('long_int_un' in variables
                and variables['long_int_un'] == (1, Type('unsigned long int')))
        if sys.platform == 'win32':
            assert ('int64' in variables
                    and variables['int64'] == (1, Type('__int64')))
            assert ('int64_un' in variables
                    and variables['int64_un'] == (1, Type('unsigned __int64')))
        assert ('long_long' in variables
                and variables['long_long'] == (1, Type('long long')))
        assert ('long_long_int' in variables
                and variables['long_long_int'] == (1, Type('long long int')))
        assert ('long_long_un' in variables and variables['long_long_un']
                == (1, Type('unsigned long long')))
        assert ('long_long_int_un' in variables
                and variables['long_long_int_un']
                == (1, Type('unsigned long '
                            'long int')))

        # C99 integers
        for i in (8, 16, 32, 64):
            assert ('i%d' % i in variables
                    and variables['i%d' % i] == (1, Type('int%d_t' % i)))
            assert ('u%d' % i in variables
                    and variables['u%d' % i] == (1, Type('uint%d_t' % i)))

        # Floating point number
        assert ('fl' in variables and variables['fl'] == (1., Type('float')))
        assert ('db' in variables and variables['db'] == (0.1, Type('double')))
        assert ('dbl' in variables
                and variables['dbl'] == (-10., Type('long double')))

        # Const and static modif
        assert ('int_const' in variables and variables['int_const']
                == (4, Type('int', type_quals=(('const', ), ))))
        assert ('int_stat' in variables
                and variables['int_stat'] == (4, Type('int')))
        assert ('int_con_stat' in variables and variables['int_con_stat']
                == (4, Type('int', type_quals=(('const', ), ))))
        assert ('int_extern' in variables
                and variables['int_extern'] == (4, Type('int')))

        # String
        assert ('str1' in variables
                and variables['str1'] == ("normal string", Type('char', '*')))
        assert ('str2' in variables and variables['str2']
                == ("string with macro: INT", Type('char', '*', '*')))
        assert ('str3' in variables and variables['str3']
                == ("string with comment: /*comment inside string*/",
                    Type('char', '*', type_quals=(('const', ), ('const', )))))
        assert ('str4' in variables and variables['str4']
                == ("string with define #define MACRO5 macro5_in_string ",
                    Type('char', '*')))
        assert ('str5' in variables and variables['str5']
                == ("string with \"escaped quotes\" ", Type('char', '*')))

        # Test complex evaluation
        assert ('x1' in variables and variables['x1'] == (1., Type('float')))

        # Test type casting handling.
        assert ('x2' in variables
                and variables['x2'] == (88342528, Type('int')))

        # Test array handling
        assert ('array' in variables
                and variables['array'] == ([1, 3141500.0], Type('float', [2])))
        assert ('intJunk' in variables
                and variables['intJunk'] == (None,
                                             Type('int',
                                                  '*',
                                                  '*',
                                                  '*', [4],
                                                  type_quals=(('const', ),
                                                              ('const', ), (),
                                                              (), ()))))

        # test type qualifiers
        assert variables.get('typeQualedIntPtrPtr') == \
               (None, Type('int', '*', '*',
                           type_quals=(('const',), ('volatile',), ())) )
        assert variables.get('typeQualedIntPtr') == \
               (None, Type('int', '*', type_quals=(('const', 'volatile',), ())))

        # test type definition precedence
        assert variables.get('prec_ptr_of_arr') == \
               (None, Type('int', [1], '*'))
        assert variables.get('prec_arr_of_ptr') == \
               (None, Type('int', '*', [1]))
        assert variables.get('prec_arr_of_ptr2') == \
               (None, Type('int', '*', [1]))

    # No structure, no unions, no enum
    def test_typedef(self):

        path = os.path.join(self.h_dir, 'typedefs.h')
        self.parser.load_file(path)
        self.parser.process_all()

        types = self.parser.defs['types']
        variables = self.parser.defs['variables']

        # Test defining types from base types.
        assert ('typeChar' in types
                and types['typeChar'] == Type('char', '*', '*'))
        assert ('typeInt' in types and types['typeInt'] == Type('int'))
        assert ('typeIntPtr' in types
                and types['typeIntPtr'] == Type('int', '*'))
        assert ('typeIntArr' in types
                and types['typeIntArr'] == Type('int', [10]))
        assert ('typeIntDArr' in types
                and types['typeIntDArr'] == Type('int', [5], [6]))
        assert ('typeTypeInt' in types
                and types['typeTypeInt'] == Type('typeInt'))
        assert not self.parser.is_fund_type('typeTypeInt')
        assert self.parser.eval_type(['typeTypeInt']) == Type('int')
        assert ('ULONG' in types and types['ULONG'] == Type('unsigned long'))

        # Test annotated types
        assert ('voidpc' in types and types['voidpc'] == Type(
            'void', '*', type_quals=(('const', ), ())))
        assert ('charf' in types
                and types['charf'] == Type('char', type_quals=(('far', ), )))

        # Test using custom type.
        assert ('ttip5' in variables and variables['ttip5']
                == (None, Type('typeTypeInt', '*', [5])))

        # Handling undefined types
        assert ('SomeOtherType' in types
                and types['SomeOtherType'] == Type('someType'))
        assert ('x' in variables
                and variables['x'] == (None, Type('undefined')))
        assert not self.parser.is_fund_type('SomeOtherType')
        with raises(Exception):
            self.parser.eval_type(Type('undefined'))

        # Testing recursive defs
        assert 'recType1' in types
        assert 'recType2' in types
        assert 'recType3' in types
        with raises(Exception):
            self.parser.eval_type(Type('recType3'))

    def test_enums(self):

        path = os.path.join(self.h_dir, 'enums.h')
        self.parser.load_file(path)
        self.parser.process_all()

        enums = self.parser.defs['enums']
        types = self.parser.defs['types']
        variables = self.parser.defs['variables']
        print(self.parser.defs['values'])
        assert ('enum_name' in enums and 'enum enum_name' in types)
        assert enums['enum_name'] == {
            'enum1': 129,
            'enum2': 6,
            'enum3': 7,
            'enum4': 8
        }
        assert types['enum enum_name'] == Type(
            'enum',
            'enum_name',
        )
        assert ('enum_inst' in variables
                and variables['enum_inst'] == (None, Type('enum enum_name', )))

        assert 'anon_enum0' in enums
        assert 'anon_enum1' in enums
        assert 'no_name_enum_typeddef' in types

    def test_struct(self):

        path = os.path.join(self.h_dir, 'structs.h')
        self.parser.load_file(path)
        self.parser.process_all()

        structs = self.parser.defs['structs']
        types = self.parser.defs['types']
        variables = self.parser.defs['variables']

        # Test creating a structure using only base types.
        assert ('struct_name' in structs and 'struct struct_name' in types)
        assert structs['struct_name'] == \
               Struct(('x', Type('int'), 1),
                      ('y', Type('type_type_int'), None, 2),
                      ('str', Type('char', [10]), None))
        assert ('struct_inst' in variables and variables['struct_inst']
                == (None, Type('struct struct_name')))

        # Test creating a pointer type from a structure.
        assert ('struct_name_ptr' in types and types['struct_name_ptr']
                == Type('struct struct_name', '*'))

        assert ('struct_name2_ptr' in types and types['struct_name2_ptr']
                == Type('struct anon_struct0', '*'))

        # Test declaring a recursive structure.
        assert ('recursive_struct' in structs
                and 'struct recursive_struct' in types)
        assert structs['recursive_struct'] == \
               Struct(('next', Type('struct recursive_struct', '*'), None))

        # Test declaring near and far pointers.
        assert 'tagWNDCLASSEXA' in structs
        assert ('NPWNDCLASSEXA' in types and (types['NPWNDCLASSEXA'] == Type(
            'struct tagWNDCLASSEXA', '*', type_quals=(('near', ), ()))))

        # Test altering the packing of a structure.
        assert ('struct_name_p' in structs and 'struct struct_name_p' in types)
        assert structs['struct_name_p'] == \
               Struct(('x', Type('int'), None),
                      ('y', Type('type_type_int'), None),
                      ('str', Type('char', [10]), "brace }  \0"),
                      pack=16)

    def test_unions(self):

        path = os.path.join(self.h_dir, 'unions.h')
        self.parser.load_file(path)
        self.parser.process_all()

        unions = self.parser.defs['unions']
        structs = self.parser.defs['structs']
        types = self.parser.defs['types']
        variables = self.parser.defs['variables']

        # Test declaring an union.
        assert 'union_name' in unions and 'union union_name' in types
        assert unions['union_name'] == \
               Union(('x', Type('int'), 1),
                     ('y', Type('int'), None),
                     pack=None)
        assert ('union_name_ptr' in types
                and types['union_name_ptr'] == Type('union union_name', '*'))

        # Test defining an unnamed union
        assert ('no_name_union_inst' in variables
                and variables['no_name_union_inst']
                == (None, Type('union anon_union0')))

        # Test defining a structure using an unnamed union internally.
        assert ('tagRID_DEVICE_INFO' in structs and
                structs['tagRID_DEVICE_INFO'] == \
                Struct(('cbSize', Type('DWORD'), None),
                       ('dwType', Type('DWORD'), None),
                       (None, Type('union anon_union1'), None)))

        assert ('RID_DEVICE_INFO' in types and types['RID_DEVICE_INFO']
                == Type('struct tagRID_DEVICE_INFO'))
        assert ('PRID_DEVICE_INFO' in types
                and types['PRID_DEVICE_INFO'] == Type(
                    'struct tagRID_DEVICE_INFO', '*'))
        assert ('LPRID_DEVICE_INFO' in types
                and (types['LPRID_DEVICE_INFO'] == Type(
                    'struct tagRID_DEVICE_INFO', '*')))

    def test_functions(self):

        path = os.path.join(self.h_dir, 'functions.h')
        self.parser.load_file(path)
        self.parser.process_all()

        functions = self.parser.defs['functions']
        variables = self.parser.defs['variables']

        assert functions.get('f') == \
               Type(Type('void'), ( (None, Type('int'), None),
                                    (None, Type('int'), None) ))
        assert functions['g'] == \
               Type(Type('int'), ( ('ch', Type('char', '*'), None),
                                   ('str', Type('char', '*', '*'), None) ))
        assert variables.get('fnPtr') == \
               (None, Type('int',
                           ( (None, Type('char'), None),
                             (None, Type('float'), None) ),
                           '*'))
        assert functions.get('function1') == \
               Type(Type('int', '__stdcall', type_quals=((), None)), ())

        assert functions.get('function2') == Type(Type('int'), ())

        assert 'externFunc' in functions

        ptyp = Type('int',
                    '*',
                    '*',
                    type_quals=(('volatile', ), ('const', ), ()))
        assert functions.get('typeQualedFunc') == \
               Type(Type('int'), ((None, ptyp, None),))
Example #9
0
 def test_init(self):
     parser = CParser(os.path.join(self.h_dir, 'replace.h'))
     assert parser.files is not None
Example #10
0
class TestFileHandling(object):
    """Test parser basic file operations.

    """

    h_dir = os.path.join(H_DIRECTORY, 'file_handling')

    def setup(self):

        self.parser = CParser(process_all=False)

    def test_init(self):
        parser = CParser(os.path.join(self.h_dir, 'replace.h'))
        assert parser.files is not None

    def test_find_file(self):

        saved_headers = pyclibrary.utils.HEADER_DIRS
        try:
            pyclibrary.utils.add_header_locations([self.h_dir])
            assert self.h_dir in pyclibrary.utils.HEADER_DIRS
            assert self.parser.find_headers(['replace.h']) == \
                   [os.path.join(self.h_dir, 'replace.h')]
        finally:
            pyclibrary.utils.HEADER_DIRS = saved_headers

        abs_hdr_path = os.path.join(self.h_dir, 'replace.h')
        assert self.parser.find_headers([abs_hdr_path]) == [abs_hdr_path]
        abs_hdr_path2 = os.path.join(self.h_dir, 'c_comments.h')
        assert len(self.parser.find_headers([abs_hdr_path,
                                             abs_hdr_path2])) == 2

    def test_load_file(self):

        path = os.path.join(self.h_dir, 'replace.h')
        assert self.parser.load_file(path)
        assert self.parser.files[path] is not None
        assert self.parser.file_order == [path]
        assert self.parser.init_opts['replace']['replace.h'] is None
        assert self.parser.init_opts['files'] == ['replace.h']

    def test_load_file_and_replace(self):

        path = os.path.join(self.h_dir, 'replace.h')
        rep = {'{placeholder}': '1', 'placeholder2': '2'}
        assert self.parser.load_file(path, rep)

        lines = self.parser.files[path].split('\n')
        assert lines[3] == '# define MACRO 1'
        assert lines[6] == '    # define MACRO2 2'

        lines[3] = '# define MACRO {placeholder}'
        lines[6] = '    # define MACRO2 placeholder2'
        with open(path) as f:
            compare_lines(lines, f.readlines())

        assert self.parser.file_order == [path]
        assert self.parser.init_opts['replace']['replace.h'] == rep
        assert self.parser.init_opts['files'] == ['replace.h']

    def test_load_non_existing_file(self):

        path = os.path.join(self.h_dir, 'no.h')
        assert not self.parser.load_file(path)
        assert self.parser.files[path] is None

    def test_removing_c_comments(self):

        path = os.path.join(self.h_dir, 'c_comments.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        with open(os.path.join(self.h_dir, 'c_comments_removed.h'), 'rU') as f:
            compare_lines(self.parser.files[path].split('\n'), f.readlines())

    def test_removing_cpp_comments(self):

        path = os.path.join(self.h_dir, 'cpp_comments.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        with open(os.path.join(self.h_dir, 'cpp_comments_removed.h'),
                  'rU') as f:
            compare_lines(self.parser.files[path].split('\n'), f.readlines())
Example #11
0
class TestParsing(object):
    """Test parsing.

    """

    h_dir = H_DIRECTORY

    def setup(self):

        self.parser = CParser(process_all=False)

    def test_variables(self):

        path = os.path.join(self.h_dir, 'variables.h')
        self.parser.load_file(path)
        self.parser.process_all()

        variables = self.parser.defs['variables']

        # Integers
        assert ('short1' in variables and
                variables['short1'] == (1, Type('signed short')))
        assert ('short_int' in variables and
                variables['short_int'] == (1, Type('short int')))
        assert ('short_un' in variables and
                variables['short_un'] == (1, Type('unsigned short')))
        assert ('short_int_un' in variables and
                variables['short_int_un'] == (1, Type('unsigned short int')))
        assert ('int1' in variables and
                variables['int1'] == (1, Type('int')))
        assert ('un' in variables and
                variables['un'] == (1, Type('unsigned')))
        assert ('int_un' in variables and
                variables['int_un'] == (1, Type('unsigned int')))
        assert ('long1' in variables and
                variables['long1'] == (1, Type('long')))
        assert ('long_int' in variables and
                variables['long_int'] == (1, Type('long int')))
        assert ('long_un' in variables and
                variables['long_un'] == (1, Type('unsigned long')))
        assert ('long_int_un' in variables and
                variables['long_int_un'] == (1, Type('unsigned long int')))
        if sys.platform == 'win32':
            assert ('int64' in variables and
                    variables['int64'] == (1, Type('__int64')))
            assert ('int64_un' in variables and
                    variables['int64_un'] == (1, Type('unsigned __int64')))
        assert ('long_long' in variables and
                variables['long_long'] == (1, Type('long long')))
        assert ('long_long_int' in variables and
                variables['long_long_int'] == (1, Type('long long int')))
        assert ('long_long_un' in variables and
                variables['long_long_un'] == (1, Type('unsigned long long')))
        assert ('long_long_int_un' in variables and
                variables['long_long_int_un'] == (1, Type('unsigned long '
                                                          'long int')))

        # Floating point number
        assert ('fl' in variables and variables['fl'] ==
                (1., Type('float')))
        assert ('db' in variables and variables['db'] ==
                (0.1, Type('double')))
        assert ('dbl' in variables and
                variables['dbl'] == (-10., Type('long double')))

        # Const and static modif
        assert ('int_const' in variables and
                variables['int_const'] == (4, Type('int',
                                                   type_quals=(('const',),))))
        assert ('int_stat' in variables and
                variables['int_stat'] == (4, Type('int')))
        assert ('int_con_stat' in variables and
                variables['int_con_stat'] == (4, Type('int',
                                                      type_quals=(('const',),))))
        assert ('int_extern' in variables and
                variables['int_extern'] == (4, Type('int')))

        # String
        assert ('str1' in variables and
                variables['str1'] == ("normal string", Type('char', '*')))
        assert ('str2' in variables and
                variables['str2'] == ("string with macro: INT",
                                      Type('char', '*', '*')))
        assert ('str3' in variables and
                variables['str3'] == ("string with comment: /*comment inside string*/",
                                      Type('char', '*', type_quals=(('const',), ('const',)))))
        assert ('str4' in variables and
                variables['str4'] == ("string with define #define MACRO5 macro5_in_string ",
                                      Type('char', '*')))
        assert ('str5' in variables and
                variables['str5'] == ("string with \"escaped quotes\" ",
                                      Type('char', '*')))

        # Test complex evaluation
        assert ('x1' in variables and
                variables['x1'] == (1., Type('float')))

        # Test type casting handling.
        assert ('x2' in variables and
                variables['x2'] == (88342528, Type('int')))

        # Test array handling
        assert ('array' in variables and
                variables['array'] == ([1, 3141500.0], Type('float', [2])))
        assert ('intJunk' in variables and
                variables['intJunk'] == (
                    None,
                    Type('int', '*', '*', '*', [4],
                         type_quals=(('const',), ('const',), (), (), ())) ) )

        # test type qualifiers
        assert variables.get('typeQualedIntPtrPtr') == \
               (None, Type('int', '*', '*',
                           type_quals=(('const',), ('volatile',), ())) )
        assert variables.get('typeQualedIntPtr') == \
               (None, Type('int', '*', type_quals=(('const', 'volatile',), ())))

        # test type definition precedence
        assert variables.get('prec_ptr_of_arr') == \
               (None, Type('int', [1], '*'))
        assert variables.get('prec_arr_of_ptr') == \
               (None, Type('int', '*', [1]))
        assert variables.get('prec_arr_of_ptr2') == \
               (None, Type('int', '*', [1]))

    # No structure, no unions, no enum
    def test_typedef(self):

        path = os.path.join(self.h_dir, 'typedefs.h')
        self.parser.load_file(path)
        self.parser.process_all()

        types = self.parser.defs['types']
        variables = self.parser.defs['variables']

        # Test defining types from base types.
        assert ('typeChar' in types and types['typeChar'] ==
                Type('char', '*', '*'))
        assert ('typeInt' in types and types['typeInt'] ==
                Type('int'))
        assert ('typeIntPtr' in types and types['typeIntPtr'] ==
                Type('int', '*'))
        assert ('typeIntArr' in types and types['typeIntArr'] ==
                Type('int', [10]))
        assert ('typeIntDArr' in types and types['typeIntDArr'] ==
                Type('int', [5], [6]))
        assert ('typeTypeInt' in types and
                types['typeTypeInt'] == Type('typeInt'))
        assert not self.parser.is_fund_type('typeTypeInt')
        assert self.parser.eval_type(['typeTypeInt']) == Type('int')
        assert ('ULONG' in types and types['ULONG'] == Type('unsigned long'))

        # Test annotated types
        assert ('voidpc' in types and types['voidpc'] ==
                Type('void', '*', type_quals=(('const',), ())))
        assert ('charf' in types and types['charf'] ==
                Type('char', type_quals=(('far',),)))

        # Test using custom type.
        assert ('ttip5' in variables and
                variables['ttip5'] == (None, Type('typeTypeInt', '*', [5])))

        # Handling undefined types
        assert ('SomeOtherType' in types and
                types['SomeOtherType'] == Type('someType'))
        assert ('x' in variables and variables['x'] ==
                (None, Type('undefined')))
        assert not self.parser.is_fund_type('SomeOtherType')
        with raises(Exception):
            self.parser.eval_type(Type('undefined'))

        # Testing recursive defs
        assert 'recType1' in types
        assert 'recType2' in types
        assert 'recType3' in types
        with raises(Exception):
            self.parser.eval_type(Type('recType3'))

    def test_enums(self):

        path = os.path.join(self.h_dir, 'enums.h')
        self.parser.load_file(path)
        self.parser.process_all()

        enums = self.parser.defs['enums']
        types = self.parser.defs['types']
        variables = self.parser.defs['variables']
        print(self.parser.defs['values'])
        assert ('enum_name' in enums and 'enum enum_name' in types)
        assert enums['enum_name'] == {'enum1': 129, 'enum2': 6, 'enum3': 7,
                                      'enum4': 8}
        assert types['enum enum_name'] == Type('enum', 'enum_name',)
        assert ('enum_inst' in variables and
                variables['enum_inst'] == (None, Type('enum enum_name',)))

        assert 'anon_enum0' in enums
        assert 'anon_enum1' in enums
        assert 'no_name_enum_typeddef' in types

    def test_struct(self):

        path = os.path.join(self.h_dir, 'structs.h')
        self.parser.load_file(path)
        self.parser.process_all()

        structs = self.parser.defs['structs']
        types = self.parser.defs['types']
        variables = self.parser.defs['variables']

        # Test creating a structure using only base types.
        assert ('struct_name' in structs and 'struct struct_name' in types)
        assert structs['struct_name'] == \
               Struct(('x', Type('int'), 1),
                      ('y', Type('type_type_int'), None, 2),
                      ('str', Type('char', [10]), None))
        assert ('struct_inst' in variables and
                variables['struct_inst'] == (None, Type('struct struct_name')))

        # Test creating a pointer type from a structure.
        assert ('struct_name_ptr' in types and
                types['struct_name_ptr'] == Type('struct struct_name', '*'))

        assert ('struct_name2_ptr' in types and
                types['struct_name2_ptr'] == Type('struct anon_struct0', '*'))

        # Test declaring a recursive structure.
        assert ('recursive_struct' in structs and
                'struct recursive_struct' in types)
        assert structs['recursive_struct'] == \
               Struct(('next', Type('struct recursive_struct', '*'), None))

        # Test declaring near and far pointers.
        assert 'tagWNDCLASSEXA' in structs
        assert ('NPWNDCLASSEXA' in types and
                ( types['NPWNDCLASSEXA'] ==
                 Type('struct tagWNDCLASSEXA', '*', type_quals=(('near',), ()))))

        # Test altering the packing of a structure.
        assert ('struct_name_p' in structs and 'struct struct_name_p' in types)
        assert structs['struct_name_p'] == \
               Struct(('x', Type('int'), None),
                      ('y', Type('type_type_int'), None),
                      ('str', Type('char', [10]), "brace }  \0"),
                      pack=16)

    def test_unions(self):

        path = os.path.join(self.h_dir, 'unions.h')
        self.parser.load_file(path)
        self.parser.process_all()

        unions = self.parser.defs['unions']
        structs = self.parser.defs['structs']
        types = self.parser.defs['types']
        variables = self.parser.defs['variables']

        # Test declaring an union.
        assert 'union_name' in unions and 'union union_name' in types
        assert unions['union_name'] == \
               Union(('x', Type('int'), 1),
                     ('y', Type('int'), None),
                     pack=None)
        assert ('union_name_ptr' in types and
                types['union_name_ptr'] == Type('union union_name', '*'))

        # Test defining an unnamed union
        assert ('no_name_union_inst' in variables and
                variables['no_name_union_inst'] == (None,
                                                    Type('union anon_union0')))

        # Test defining a structure using an unnamed union internally.
        assert ('tagRID_DEVICE_INFO' in structs and
                structs['tagRID_DEVICE_INFO'] == \
                Struct(('cbSize', Type('DWORD'), None),
                       ('dwType', Type('DWORD'), None),
                       (None, Type('union anon_union1'), None)))

        assert ('RID_DEVICE_INFO' in types and
                types['RID_DEVICE_INFO'] == Type('struct tagRID_DEVICE_INFO'))
        assert ('PRID_DEVICE_INFO' in types and
                types['PRID_DEVICE_INFO'] ==
                    Type('struct tagRID_DEVICE_INFO', '*')
                )
        assert ('LPRID_DEVICE_INFO' in types and
                ( types['LPRID_DEVICE_INFO'] ==
                  Type('struct tagRID_DEVICE_INFO', '*')
                  )
                )

    def test_functions(self):

        path = os.path.join(self.h_dir, 'functions.h')
        self.parser.load_file(path)
        self.parser.process_all()

        functions = self.parser.defs['functions']
        variables = self.parser.defs['variables']

        assert functions.get('f') == \
               Type(Type('void'), ( (None, Type('int'), None),
                                    (None, Type('int'), None) ))
        assert functions['g'] == \
               Type(Type('int'), ( ('ch', Type('char', '*'), None),
                                   ('str', Type('char', '*', '*'), None) ))
        assert variables.get('fnPtr') == \
               (None, Type('int',
                           ( (None, Type('char'), None),
                             (None, Type('float'), None) ),
                           '*'))
        assert functions.get('function1') == \
               Type(Type('int', '__stdcall', type_quals=((), None)), ())

        assert functions.get('function2') == Type(Type('int'), ())

        assert 'externFunc' in functions

        ptyp = Type('int', '*', '*', type_quals=(('volatile',), ('const',), ()))
        assert functions.get('typeQualedFunc') == \
               Type(Type('int'), ((None, ptyp, None),))
Example #12
0
class TestPreprocessing(object):
    """Test preprocessing.

    """
    h_dir = os.path.join(H_DIRECTORY, 'macros')

    def setup(self):

        self.parser = CParser(process_all=False)

    def test_values(self):

        path = os.path.join(self.h_dir, 'macro_values.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)

        macros = self.parser.defs['macros']
        values = self.parser.defs['values']

        assert 'M' in macros and macros['M'] == ''
        assert 'N' in macros and macros['N'] == 'n' and values['N'] is None

        # Decimal integer
        assert ('MACRO_D1' in macros and macros['MACRO_D1'] == '1' and
                values['MACRO_D1'] == 1)
        assert ('MACRO_D2' in macros and macros['MACRO_D2'] == '-2U' and
                values['MACRO_D2'] == -2)
        assert ('MACRO_D3' in macros and macros['MACRO_D3'] == '+ 3UL' and
                values['MACRO_D3'] == 3)

        # Bit shifted decimal integer
        assert ('MACRO_SD1' in macros and
                macros['MACRO_SD1'] == '(1 << 1)' and
                values['MACRO_SD1'] == 2)
        assert ('MACRO_SD2' in macros and
                macros['MACRO_SD2'] == '(2U << 2)' and
                values['MACRO_SD2'] == 8)
        assert ('MACRO_SD3' in macros and
                macros['MACRO_SD3'] == '(3UL << 3)' and
                values['MACRO_SD3'] == 24)

        # Hexadecimal integer
        assert ('MACRO_H1' in macros and
                macros['MACRO_H1'] == '+0x000000' and
                values['MACRO_H1'] == 0)
        assert ('MACRO_H2' in macros and
                macros['MACRO_H2'] == '- 0x000001U' and
                values['MACRO_H2'] == -1)
        assert ('MACRO_H3' in macros and
                macros['MACRO_H3'] == '0X000002UL' and
                values['MACRO_H3'] == 2)

        # Bit shifted hexadecimal integer
        assert ('MACRO_SH1' in macros and
                macros['MACRO_SH1'] == '(0x000000 << 1)' and
                values['MACRO_SH1'] == 0)
        assert ('MACRO_SH2' in macros and
                macros['MACRO_SH2'] == '(0x000001U << 2)' and
                values['MACRO_SH2'] == 4)
        assert ('MACRO_H3' in macros and
                macros['MACRO_SH3'] == '(0X000002UL << 3)' and
                values['MACRO_SH3'] == 16)

        # Floating point value
        assert ('MACRO_F1' in macros and
                macros['MACRO_F1'] == '1.0' and
                values['MACRO_F1'] == 1.0)
        assert ('MACRO_F2' in macros and
                macros['MACRO_F2'] == '1.1e1' and
                values['MACRO_F2'] == 11.)
        assert ('MACRO_F3' in macros and
                macros['MACRO_F3'] == '-1.1E-1' and
                values['MACRO_F3'] == -0.11)

        # String macro
        assert ('MACRO_S' in macros and macros['MACRO_S'] == '"test"' and
                values['MACRO_S'] == 'test')

        # Nested macros
        assert ('NESTED' in macros and macros['NESTED'] == '1' and
                values['NESTED'] == 1)
        assert ('NESTED2' in macros and macros['NESTED2'] == '1' and
                values['NESTED2'] == 1)
        assert ('MACRO_N' in macros and macros['MACRO_N'] == '1 + 2' and
                values['MACRO_N'] == 3)

        # Muliline macro
        assert 'MACRO_ML' in macros and values['MACRO_ML'] == 2

    def test_conditionals(self):

        path = os.path.join(self.h_dir, 'macro_conditionals.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)
        self.parser.parse_defs(path)

        macros = self.parser.defs['macros']
        stream = self.parser.files[path]

        # Test if defined conditional
        assert 'DEFINE_IF' in macros
        assert '  int DECLARE_IF;\n' in stream
        assert 'NO_DEFINE_IF' not in macros
        assert '  int NO_DECLARE_IF;\n' not in stream

        # Test ifdef conditional
        assert 'DEFINE_IFDEF' in macros
        assert '  int DECLARE_IFDEF;\n' in stream
        assert 'NO_DEFINE_IFDEF' not in macros
        assert '  int NO_DECLARE_IFDEF;\n' not in stream

        # Test if !defined
        assert 'DEFINE_IFN' in macros
        assert '  int DECLARE_IFN;\n' in stream
        assert 'NO_DEFINE_IFN' not in macros
        assert '  int NO_DECLARE_IFN;\n' not in stream

        # Test ifndef
        assert 'DEFINE_IFNDEF' in macros
        assert '  int DECLARE_IFNDEF;\n' in stream
        assert 'NO_DEFINE_IFNDEF' not in macros
        assert '  int NO_DECLARE_IFNDEF;\n' not in stream

        # Test elif
        assert 'DEFINE_ELIF' in macros
        assert '  int DECLARE_ELIF;\n' in stream
        assert 'NO_DEFINE_ELIF' not in macros
        assert '  int NO_DECLARE_ELIF;\n' not in stream

        # Test else
        assert 'DEFINE_ELSE' in macros
        assert '  int DECLARE_ELSE;\n' in stream
        assert 'NO_DEFINE_ELSE' not in macros
        assert '  int NO_DECLARE_ELSE;\n' not in stream

        # Test nested
        assert 'DEFINE_N1' in macros
        assert '  int DECLARE_N1;\n' in stream
        assert 'NO_DEFINE_N2' not in macros
        assert 'DEFINE_N2' not in macros

        assert 'DEFINE_N3' in macros
        assert 'NO_DEFINE_N3' not in macros
        assert '  int NO_DECLARE_N3;\n' not in stream

        # Test logical
        assert 'DEFINE_LOG' in macros
        assert '  int DECLARE_LOG;\n' in stream
        assert 'NO_DEFINE_LOG' not in macros
        assert 'NO_DEFINE_LOG' not in macros

        # Test undef
        assert 'DEFINE_UNDEF' in macros
        assert 'UNDEF' not in macros

    def test_macro_function(self):

        path = os.path.join(self.h_dir, 'macro_functions.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)
        self.parser.parse_defs(path)

        values = self.parser.defs['values']
        fnmacros = self.parser.defs['fnmacros']
        stream = self.parser.files[path]

        # Test macro declaration.
        assert 'CARRE' in fnmacros
        assert 'int carre = 2*2;' in stream

        assert 'int __declspec(dllexport) function2()' in stream
        assert '__declspec(dllexport) int function3()' in stream

        # Test defining a macro function as an alias for another one.
        assert 'MAKEINTRESOURCEA' in fnmacros
        assert 'MAKEINTRESOURCEW' in fnmacros
        assert 'MAKEINTRESOURCE' in fnmacros
        assert fnmacros['MAKEINTRESOURCE'] == fnmacros['MAKEINTRESOURCEA']
        assert 'int x = ((LPSTR)((ULONG_PTR)((WORD)(4))))'

        # Test using a macro value in a macro function call
        assert 'BIT' in values and values['BIT'] == 1
        assert '((y) |= (0x01))' in stream

        # Test defining a macro function calling other macros (values and
        # functions)
        assert 'SETBITS' in fnmacros
        assert 'int z1, z2 = (((1) |= (0x01)), ((2) |= (0x01)));' in stream

        # Test defining a macro function calling nested macro functions
        assert 'SETBIT_AUTO' in fnmacros
        assert 'int z3 = ((((3) |= (0x01)), ((3) |= (0x01))));' in stream

    def test_pragmas(self):

        path = os.path.join(self.h_dir, 'pragmas.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        self.parser.preprocess(path)
        self.parser.parse_defs(path)

        stream = self.parser.files[path]
        packings = self.parser.pack_list[path]

        # Check all pragmas instructions have been removed.
        assert stream.strip() == ''

        assert packings[1][1] is None
        assert packings[2][1] == 4
        assert packings[3][1] == 16
        assert packings[4][1] is None
        assert packings[5][1] is None
        assert packings[6][1] == 4
        assert packings[7][1] == 16
        assert packings[8][1] is None
Example #13
0
class TestFileHandling(object):
    """Test parser basic file operations.

    """

    h_dir = os.path.join(H_DIRECTORY, 'file_handling')

    def setup(self):

        self.parser = CParser(process_all=False)

    def test_init(self):
        parser = CParser(os.path.join(self.h_dir, 'replace.h'))
        assert parser.files is not None

    def test_find_file(self):

        saved_headers = pyclibrary.utils.HEADER_DIRS
        try:
            pyclibrary.utils.add_header_locations([self.h_dir])
            assert self.h_dir in pyclibrary.utils.HEADER_DIRS
            assert self.parser.find_headers(['replace.h']) == \
                   [os.path.join(self.h_dir, 'replace.h')]
        finally:
            pyclibrary.utils.HEADER_DIRS = saved_headers

        abs_hdr_path = os.path.join(self.h_dir, 'replace.h')
        assert self.parser.find_headers([abs_hdr_path]) == [abs_hdr_path]
        abs_hdr_path2 = os.path.join(self.h_dir, 'c_comments.h')
        assert len(self.parser.find_headers([abs_hdr_path, abs_hdr_path2])) == 2


    def test_load_file(self):

        path = os.path.join(self.h_dir, 'replace.h')
        assert self.parser.load_file(path)
        assert self.parser.files[path] is not None
        assert self.parser.file_order == [path]
        assert self.parser.init_opts['replace']['replace.h'] is None
        assert self.parser.init_opts['files'] == ['replace.h']

    def test_load_file_and_replace(self):

        path = os.path.join(self.h_dir, 'replace.h')
        rep = {'{placeholder}': '1', 'placeholder2': '2'}
        assert self.parser.load_file(path, rep)

        lines = self.parser.files[path].split('\n')
        assert lines[3] == '# define MACRO 1'
        assert lines[6] == '    # define MACRO2 2'

        lines[3] = '# define MACRO {placeholder}'
        lines[6] = '    # define MACRO2 placeholder2'
        with open(path) as f:
            compare_lines(lines, f.readlines())

        assert self.parser.file_order == [path]
        assert self.parser.init_opts['replace']['replace.h'] == rep
        assert self.parser.init_opts['files'] == ['replace.h']

    def test_load_non_existing_file(self):

        path = os.path.join(self.h_dir, 'no.h')
        assert not self.parser.load_file(path)
        assert self.parser.files[path] is None

    def test_removing_c_comments(self):

        path = os.path.join(self.h_dir, 'c_comments.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        with open(os.path.join(self.h_dir, 'c_comments_removed.h'), 'rU') as f:
            compare_lines(self.parser.files[path].split('\n'), f.readlines())

    def test_removing_cpp_comments(self):

        path = os.path.join(self.h_dir, 'cpp_comments.h')
        self.parser.load_file(path)
        self.parser.remove_comments(path)
        with open(os.path.join(self.h_dir,
                               'cpp_comments_removed.h'), 'rU') as f:
            compare_lines(self.parser.files[path].split('\n'), f.readlines())