├── .gitignore
├── misc
└── node_structure.png
├── vsproj
├── RunTest.vcxproj.user
├── ObjcEncodingParser.vcxproj.user
├── RunTest.vcxproj.filters
├── ObjcEncodingParser.vcxproj.filters
├── ObjcEncodingParser.sln
├── RunTest.vcxproj
└── ObjcEncodingParser.vcxproj
├── ObjcEncodingParser.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── LICENSE
├── common.h
├── modifiers.def
├── README.md
├── run-test.c
├── Makefile
├── cursor.h
├── types.def
├── strings.h
├── parser.h
└── parser.c
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | xcuserdata
3 |
4 | /obj
5 | *.a
6 | *.o
--------------------------------------------------------------------------------
/misc/node_structure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unixzii/objc-encodingparser/HEAD/misc/node_structure.png
--------------------------------------------------------------------------------
/vsproj/RunTest.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/vsproj/ObjcEncodingParser.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/ObjcEncodingParser.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ObjcEncodingParser.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/vsproj/RunTest.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
6 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
7 |
8 |
9 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
10 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
11 |
12 |
13 |
14 |
15 | Headers
16 |
17 |
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Cyandev.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/vsproj/ObjcEncodingParser.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 |
14 |
15 | Sources
16 |
17 |
18 |
19 |
20 | Headers
21 |
22 |
23 | Headers
24 |
25 |
26 | Headers
27 |
28 |
29 | Headers
30 |
31 |
32 |
--------------------------------------------------------------------------------
/common.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Objective-C encoding parser library
3 | *
4 | * Copyright (c) 2022 Cyandev.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | #ifndef COMMON_H
26 | #define COMMON_H
27 |
28 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
29 | #define CONFIG_WIN32 1
30 | #endif
31 |
32 | #if defined(CONFIG_WIN32)
33 | #define ALWAYS_INLINE __inline
34 | #define NO_INLINE __declspec(noinline)
35 | #define UNUSED
36 | #else
37 | #define ALWAYS_INLINE inline __attribute__((always_inline))
38 | #define NO_INLINE __attribute__((noinline))
39 | #define UNUSED __attribute__((unused))
40 | #endif
41 |
42 | #ifndef MAX
43 | #define MAX(x, y) ((x) > (y) ? (x) : (y))
44 | #endif
45 |
46 | #ifndef ROUNDUP
47 | #define ROUNDUP(x, y) (((x) + (y) - 1) & -(y))
48 | #endif
49 |
50 | #endif /* COMMON_H */
51 |
--------------------------------------------------------------------------------
/modifiers.def:
--------------------------------------------------------------------------------
1 | /*
2 | * Objective-C encoding parser library
3 | *
4 | * Copyright (c) 2024 Cyandev.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | #ifndef __OBJC_MODIFIER
26 | #define __OBJC_MODIFIER(name, value, rep)
27 | #endif
28 |
29 | // name val rep
30 | __OBJC_MODIFIER(OBJC_MODIFIER_COMPLEX, (1 << 0), 'j')
31 | __OBJC_MODIFIER(OBJC_MODIFIER_ATOMIC, (1 << 2), 'A')
32 | __OBJC_MODIFIER(OBJC_MODIFIER_CONST, (1 << 3), 'r')
33 | __OBJC_MODIFIER(OBJC_MODIFIER_IN, (1 << 4), 'n')
34 | __OBJC_MODIFIER(OBJC_MODIFIER_INOUT, (1 << 5), 'N')
35 | __OBJC_MODIFIER(OBJC_MODIFIER_OUT, (1 << 6), 'o')
36 | __OBJC_MODIFIER(OBJC_MODIFIER_BYCOPY, (1 << 7), 'O')
37 | __OBJC_MODIFIER(OBJC_MODIFIER_BYREF, (1 << 8), 'R')
38 | __OBJC_MODIFIER(OBJC_MODIFIER_ONEWAY, (1 << 9), 'V')
39 | __OBJC_MODIFIER(OBJC_MODIFIER_GNUREGISTER, (1 << 10), '+')
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Objective-C Encoding Parser
2 |
3 | This library is a simple parser for Objective-C [type encoding](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html) with a focus on cross-platform.
4 |
5 | See [parser.h](./parser.h) for the provided APIs and [run-test.c](./run-test.c) to learn how this library works in action.
6 |
7 | ## Features
8 |
9 | * Simple and intuitive APIs, ready for use without reading any documents.
10 | * Zero-dependency and platform-agnostic, tested in macOS, Linux and Windows, easy to integrate with your various analysis facilities.
11 | * Full support of the type encoding syntax (including struct, union), and able to get the related information of the type (like name, size and alignment).
12 | * Error tolerance for ill-formed encoding strings, the library parses inputs in its best effort.
13 | * Built-in dump function to print the human-readable string describing the type.
14 |
15 | ## Building
16 |
17 | ### Make
18 |
19 | ```
20 | git clone https://github.com/unixzii/objc-encodingparser.git
21 | cd objc-encodingparser
22 | make
23 | ```
24 |
25 | This will generate both the static library `libocep.a` and a `run-test` program.
26 |
27 | ### Xcode / Visual Studio
28 |
29 | The project (solution) both contains two targets: `libocep` and `RunTest`. Once build is succeeded, you can retrieve the products from your IDE's build directory.
30 |
31 | ## Type Node Explained
32 |
33 | `ocep_type_node_t` is the core structure of this library, you parse an encoding string and get the result with that type. It's like an n-ary tree and each node has a parent pointer, a child pointer and a sibling pointer. An example is shown as the below figure:
34 |
35 | 
36 |
37 | You can use `ocep_type_node_traverse` function to visit all the children (include itself) of a given node in a DFS-fashion traverse.
38 |
39 | ## Limitations
40 |
41 | * Bit fields are currently not supported (since it's rare in Objective-C code), submit an issue if you see this important.
42 | * Type size is now calculated in the compact layout (eg. `"{?=c^vc}"` will get a size of 16 while actually it's 24).
43 |
44 | ## License
45 |
46 | This project is licensed under MIT license.
--------------------------------------------------------------------------------
/run-test.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Test runner for Objective-C encoding parser library
3 | *
4 | * Copyright (c) 2022 Cyandev.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | #include
26 | #include
27 |
28 | #include "parser.h"
29 |
30 | static void run_test(const char *test) {
31 | ocep_type_node_t root = ocep_parse_encoding(test);
32 | char *dump_str = ocep_type_node_dump(root);
33 | printf("--- %s ---\n%s\n\n", test, dump_str);
34 | free(dump_str);
35 | ocep_type_node_free(root);
36 | }
37 |
38 | int main(int argc, char **argv) {
39 | if (argc > 1) {
40 | // Run with the given input.
41 | run_test(argv[1]);
42 | return 0;
43 | }
44 |
45 | // Run with a suite of tests.
46 | run_test("@@:");
47 | run_test("v@:");
48 | run_test("v@:{CGRect={CGPoint=dd}{CGSize=dd}}");
49 | run_test("{B={A=[5c]}i^v}");
50 | run_test("{?=c^vc"); // invalid encoding string on purpose
51 | run_test("{basic_string, std::allocator>={__compressed_pair::__rep, std::allocator>={__rep=(?={__long=*QQ}{__short=[23c]{?=C}}{__raw=[3Q]})}}}");
52 | run_test("v32@0:8Ar^^{CGRect}16^q24");
53 | return 0;
54 | }
55 |
--------------------------------------------------------------------------------
/vsproj/ObjcEncodingParser.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.32014.148
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ObjcEncodingParser", "ObjcEncodingParser.vcxproj", "{6500AAA2-E125-419D-ACF7-698EB4B6AD44}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RunTest", "RunTest.vcxproj", "{4613528E-93FA-41B1-AEBF-CB4E567914BA}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|x64 = Debug|x64
13 | Debug|x86 = Debug|x86
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {6500AAA2-E125-419D-ACF7-698EB4B6AD44}.Debug|x64.ActiveCfg = Debug|x64
19 | {6500AAA2-E125-419D-ACF7-698EB4B6AD44}.Debug|x64.Build.0 = Debug|x64
20 | {6500AAA2-E125-419D-ACF7-698EB4B6AD44}.Debug|x86.ActiveCfg = Debug|Win32
21 | {6500AAA2-E125-419D-ACF7-698EB4B6AD44}.Debug|x86.Build.0 = Debug|Win32
22 | {6500AAA2-E125-419D-ACF7-698EB4B6AD44}.Release|x64.ActiveCfg = Release|x64
23 | {6500AAA2-E125-419D-ACF7-698EB4B6AD44}.Release|x64.Build.0 = Release|x64
24 | {6500AAA2-E125-419D-ACF7-698EB4B6AD44}.Release|x86.ActiveCfg = Release|Win32
25 | {6500AAA2-E125-419D-ACF7-698EB4B6AD44}.Release|x86.Build.0 = Release|Win32
26 | {4613528E-93FA-41B1-AEBF-CB4E567914BA}.Debug|x64.ActiveCfg = Debug|x64
27 | {4613528E-93FA-41B1-AEBF-CB4E567914BA}.Debug|x64.Build.0 = Debug|x64
28 | {4613528E-93FA-41B1-AEBF-CB4E567914BA}.Debug|x86.ActiveCfg = Debug|Win32
29 | {4613528E-93FA-41B1-AEBF-CB4E567914BA}.Debug|x86.Build.0 = Debug|Win32
30 | {4613528E-93FA-41B1-AEBF-CB4E567914BA}.Release|x64.ActiveCfg = Release|x64
31 | {4613528E-93FA-41B1-AEBF-CB4E567914BA}.Release|x64.Build.0 = Release|x64
32 | {4613528E-93FA-41B1-AEBF-CB4E567914BA}.Release|x86.ActiveCfg = Release|Win32
33 | {4613528E-93FA-41B1-AEBF-CB4E567914BA}.Release|x86.Build.0 = Release|Win32
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | GlobalSection(ExtensibilityGlobals) = postSolution
39 | SolutionGuid = {F9F3E6F7-8263-4068-A459-2A4A18DA7AC1}
40 | EndGlobalSection
41 | EndGlobal
42 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # Objective-C encoding parser library
3 | #
4 | # Copyright (c) 2022 Cyandev.
5 | #
6 | # Permission is hereby granted, free of charge, to any person obtaining a copy
7 | # of this software and associated documentation files (the "Software"), to deal
8 | # in the Software without restriction, including without limitation the rights
9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | # copies of the Software, and to permit persons to whom the Software is
11 | # furnished to do so, subject to the following conditions:
12 | #
13 | # The above copyright notice and this permission notice shall be included in all
14 | # copies or substantial portions of the Software.
15 | #
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | # SOFTWARE.
23 |
24 | ifeq ($(OS),Windows_NT)
25 | CONFIG_WIN32=y
26 | else
27 | ifeq ($(shell uname -s),Darwin)
28 | CONFIG_DARWIN=y
29 | else
30 | CONFIG_POSIX=y
31 | endif
32 | endif
33 |
34 | OBJDIR=obj
35 |
36 | ifdef CONFIG_DARWIN
37 | CC=clang
38 | CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
39 | CFLAGS += -Wextra
40 | CFLAGS += -Wno-sign-compare
41 | CFLAGS += -Wno-missing-field-initializers
42 | CFLAGS += -Wundef -Wuninitialized
43 | CFLAGS += -Wunused -Wno-unused-parameter
44 | CFLAGS += -Wwrite-strings
45 | CFLAGS += -Wchar-subscripts -funsigned-char
46 |
47 | AR=ar
48 | else ifdef CONFIG_POSIX
49 | CC=gcc
50 | CFLAGS=-g -Wall
51 |
52 | AR=ar
53 | endif
54 |
55 | PROGS=run-test
56 | LIBS=libocep.a
57 |
58 | LIB_OBJS=$(OBJDIR)/parser.o
59 |
60 | all: $(LIBS) $(PROGS)
61 |
62 | run-test: $(OBJDIR)/run-test.o libocep.a
63 | $(CC) $(CFLAGS) -o $@ $(filter-out libocep.a,$^) -L. -locep
64 |
65 | libocep.a: $(LIB_OBJS)
66 | $(AR) -rcs $@ $^
67 |
68 | $(OBJDIR)/%.o: %.c | $(OBJDIR)
69 | $(CC) $(CFLAGS) -c $< -o $@
70 |
71 | $(OBJDIR):
72 | mkdir -p $@
73 |
74 | clean:
75 | rm -rf $(OBJDIR)
76 | rm -rf $(PROGS)
77 |
78 | -include $(wildcard $(OBJDIR)/*.d)
79 |
--------------------------------------------------------------------------------
/cursor.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Objective-C encoding parser library
3 | *
4 | * Copyright (c) 2022 Cyandev.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | #ifndef CURSOR_H
26 | #define CURSOR_H
27 |
28 | #include
29 | #include
30 | #include
31 |
32 | #include "common.h"
33 |
34 | struct ocep_cursor {
35 | size_t len;
36 | size_t idx;
37 | char str[1];
38 | };
39 |
40 | typedef struct ocep_cursor *ocep_cursor_t;
41 |
42 | static ocep_cursor_t ocep_cursor_new(const char *str) {
43 | size_t len = strlen(str);
44 | size_t size = sizeof(struct ocep_cursor) + len;
45 |
46 | ocep_cursor_t cursor = (ocep_cursor_t) malloc(size);
47 | if (!cursor) {
48 | return NULL;
49 | }
50 |
51 | cursor->len = len;
52 | cursor->idx = 0;
53 | memcpy(cursor->str, str, len);
54 |
55 | return cursor;
56 | }
57 |
58 | static ALWAYS_INLINE void ocep_cursor_free(ocep_cursor_t cursor) {
59 | free(cursor);
60 | }
61 |
62 |
63 | static ALWAYS_INLINE int ocep_cursor_is_eof(ocep_cursor_t cursor) {
64 | return cursor->idx >= cursor->len;
65 | }
66 |
67 | static char ocep_cursor_peek(ocep_cursor_t cursor) {
68 | if (ocep_cursor_is_eof(cursor)) {
69 | return '\0';
70 | }
71 | return cursor->str[cursor->idx];
72 | }
73 |
74 | static char ocep_cursor_step(ocep_cursor_t cursor) {
75 | if (ocep_cursor_is_eof(cursor)) {
76 | return '\0';
77 | }
78 | char tok = ocep_cursor_peek(cursor);
79 | ++cursor->idx;
80 | return tok;
81 | }
82 |
83 | #endif /* CURSOR_H */
84 |
--------------------------------------------------------------------------------
/types.def:
--------------------------------------------------------------------------------
1 | /*
2 | * Objective-C encoding parser library
3 | *
4 | * Copyright (c) 2022 Cyandev.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | #ifndef __OBJC_TYPE
26 | #define __OBJC_TYPE(name, value, rep, size, simple)
27 | #endif
28 |
29 | // name val rep size simple
30 | __OBJC_TYPE(OBJC_TYPE_CHAR, 1, 'c', 1, 1)
31 | __OBJC_TYPE(OBJC_TYPE_INT, 2, 'i', 4, 1)
32 | __OBJC_TYPE(OBJC_TYPE_SHORT, 3, 's', 2, 1)
33 | __OBJC_TYPE(OBJC_TYPE_LONG, 4, 'l', 8, 1)
34 | __OBJC_TYPE(OBJC_TYPE_LONG_LONG, 5, 'q', 8, 1)
35 | __OBJC_TYPE(OBJC_TYPE_UNSIGNED_CHAR, 6, 'C', 1, 1)
36 | __OBJC_TYPE(OBJC_TYPE_UNSIGNED_INT, 7, 'I', 4, 1)
37 | __OBJC_TYPE(OBJC_TYPE_UNSIGNED_SHORT, 8, 'S', 2, 1)
38 | __OBJC_TYPE(OBJC_TYPE_UNSIGNED_LONG, 9, 'L', 8, 1)
39 | __OBJC_TYPE(OBJC_TYPE_UNSIGNED_LONG_LONG, 10, 'Q', 8, 1)
40 | __OBJC_TYPE(OBJC_TYPE_FLOAT, 11, 'f', 4, 1)
41 | __OBJC_TYPE(OBJC_TYPE_DOUBLE, 12, 'd', 8, 1)
42 | __OBJC_TYPE(OBJC_TYPE_BOOL, 13, 'B', 1, 1)
43 | __OBJC_TYPE(OBJC_TYPE_VOID, 14, 'v', 0, 1)
44 | __OBJC_TYPE(OBJC_TYPE_STRING, 15, '*', 8, 1)
45 | __OBJC_TYPE(OBJC_TYPE_OBJECT, 16, '@', 8, 1)
46 | __OBJC_TYPE(OBJC_TYPE_CLASS, 17, '#', 8, 1)
47 | __OBJC_TYPE(OBJC_TYPE_SEL, 18, ':', 8, 1)
48 | #ifndef __NO_COMPLEX_OBJC_TYPES
49 | __OBJC_TYPE(OBJC_TYPE_ARRAY, 19, '[', 8, 0)
50 | __OBJC_TYPE(OBJC_TYPE_STRUCT, 20, '{', 0, 0)
51 | __OBJC_TYPE(OBJC_TYPE_UNION, 21, '(', 0, 0)
52 | __OBJC_TYPE(OBJC_TYPE_BIT_FIELD, 22, 'b', 0, 0)
53 | __OBJC_TYPE(OBJC_TYPE_POINTER, 23, '^', 8, 0)
54 | #endif
55 | __OBJC_TYPE(OBJC_TYPE_UNKNOWN, 64, '?', 8, 1)
56 |
--------------------------------------------------------------------------------
/strings.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Objective-C encoding parser library
3 | *
4 | * Copyright (c) 2022 Cyandev.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | #ifndef STRINGS_H
26 | #define STRINGS_H
27 |
28 | #include
29 | #include
30 |
31 | #include "common.h"
32 |
33 | typedef struct _strbuf {
34 | char *str;
35 | size_t len;
36 | size_t cap;
37 | } strbuf;
38 |
39 | static strbuf strbuf_alloc(const char *str, size_t extra_bytes) {
40 | size_t len = 0;
41 | if (str) {
42 | len = strlen(str);
43 | }
44 | size_t cap = len + extra_bytes + 1;
45 |
46 | strbuf buf;
47 | buf.str = (char *) calloc(cap, 1);
48 | buf.len = len;
49 | buf.cap = cap;
50 |
51 | if (str) {
52 | #if defined(CONFIG_WIN32)
53 | strcpy_s(buf.str, buf.cap, str);
54 | #else
55 | strcpy(buf.str, str);
56 | #endif
57 | }
58 |
59 | return buf;
60 | }
61 |
62 | static char *strbuf_take(strbuf *buf) {
63 | char *str = buf->str;
64 | buf->str = NULL;
65 | buf->len = 0;
66 | buf->cap = 0;
67 | return str;
68 | }
69 |
70 | static UNUSED void strbuf_free(strbuf *buf) {
71 | char *str = strbuf_take(buf);
72 | if (str) {
73 | free(str);
74 | }
75 | }
76 |
77 | static void strbuf_append(strbuf *buf, const char *str) {
78 | size_t str_len = strlen(str);
79 |
80 | if (buf->len + str_len <= buf->cap - 1) {
81 | #if defined(CONFIG_WIN32)
82 | strcat_s(buf->str, buf->cap, str);
83 | #else
84 | strcat(buf->str, str);
85 | #endif
86 | buf->len += str_len;
87 | return;
88 | }
89 |
90 | char *old_str = buf->str;
91 | size_t new_cap = buf->cap + str_len + 1;
92 | char *new_str = (char *) calloc(new_cap, 1);
93 | if (old_str) {
94 | #if defined(CONFIG_WIN32)
95 | strcpy_s(new_str, new_cap, old_str);
96 | #else
97 | strcpy(new_str, old_str);
98 | #endif
99 | free(old_str);
100 | }
101 | #if defined(CONFIG_WIN32)
102 | strcat_s(new_str, new_cap, str);
103 | #else
104 | strcat(new_str, str);
105 | #endif
106 |
107 | buf->str = new_str;
108 | buf->len += str_len;
109 | buf->cap = new_cap;
110 | }
111 |
112 | static void strbuf_append_repeat(strbuf *buf, char ch, int count) {
113 | char str[2] = { ch, 0 };
114 | while (count--) {
115 | strbuf_append(buf, str);
116 | }
117 | }
118 |
119 | #endif /* STRINGS_H */
120 |
--------------------------------------------------------------------------------
/parser.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Objective-C encoding parser library
3 | *
4 | * Copyright (c) 2022 Cyandev.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | #ifndef PARSER_H
26 | #define PARSER_H
27 |
28 | #include
29 |
30 | #ifdef __cplusplus
31 | extern "C" {
32 | #endif
33 |
34 | enum {
35 | #define __OBJC_TYPE(name, value, _0, _1, _2) name = value,
36 | #include "types.def"
37 | #undef __OBJC_TYPE
38 | };
39 |
40 | enum {
41 | #define __OBJC_MODIFIER(name, value, _0) name = value,
42 | #include "modifiers.def"
43 | #undef __OBJC_MODIFIER
44 | };
45 |
46 | typedef struct ocep_type_node *ocep_type_node_t;
47 |
48 | struct ocep_type_node {
49 | /* Objective-C Type, see `types.def` for enum values.
50 | Return 0 for root nodes. */
51 | int type;
52 |
53 | /* Objective-C type modifiers, see `modifiers.def` for
54 | enum values. */
55 | int modifiers;
56 |
57 | /* Number of child types (for array, struct and union types).
58 | Note that there will only be one node in the child list
59 | for array type. */
60 | int child_num;
61 | /* Size of the value of this type. */
62 | int size;
63 | /* Alignment of this type. */
64 | int alignment;
65 |
66 | /* Struct name. Only exists for struct types. */
67 | const char *name;
68 |
69 | /* Parent node that holds this node. */
70 | ocep_type_node_t parent;
71 | /* First child node, NULL if the type contains no children. */
72 | ocep_type_node_t first_child;
73 | /* Next sibling node, NULL if this is the last node of the
74 | child list. */
75 | ocep_type_node_t next_sibling;
76 | };
77 |
78 | /* Parses the given encoding string and returns the type node.
79 | The caller must call `ocep_type_node_free` to free the memory
80 | when it has done with it. */
81 | ocep_type_node_t ocep_parse_encoding(const char *encoding);
82 |
83 | /* Deallocates the node object. */
84 | void ocep_type_node_free(ocep_type_node_t node);
85 |
86 | /* Recursively visits the given node, and invokes the given
87 | callback with each child node visited. */
88 | void ocep_type_node_traverse(ocep_type_node_t node, void *userdata,
89 | void (*cb)(ocep_type_node_t cur, int num, int depth, void *userdata));
90 |
91 | /* Dumps the given node to human-readable string. The caller
92 | must free the result string when it has done with it. */
93 | char *ocep_type_node_dump(ocep_type_node_t node);
94 |
95 | #ifdef __cplusplus
96 | } /* extern "C" { */
97 | #endif
98 |
99 | #endif /* PARSER_H */
100 |
--------------------------------------------------------------------------------
/vsproj/RunTest.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {4613528e-93fa-41b1-aebf-cb4e567914ba}
25 | RunTest
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v143
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v143
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v143
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 | true
81 |
82 |
83 | false
84 |
85 |
86 |
87 | Level3
88 | true
89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
90 | true
91 |
92 |
93 | Console
94 | true
95 |
96 |
97 |
98 |
99 | Level3
100 | true
101 | true
102 | true
103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
104 | true
105 |
106 |
107 | Console
108 | true
109 | true
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 | true
117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
118 | true
119 |
120 |
121 | Console
122 | true
123 |
124 |
125 |
126 |
127 | Level3
128 | true
129 | true
130 | true
131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
132 | true
133 |
134 |
135 | Console
136 | true
137 | true
138 | true
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | {6500aaa2-e125-419d-acf7-698eb4b6ad44}
147 |
148 |
149 |
150 |
151 |
152 |
--------------------------------------------------------------------------------
/vsproj/ObjcEncodingParser.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {6500aaa2-e125-419d-acf7-698eb4b6ad44}
25 | ObjcEncodingParser
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v143
39 | true
40 | Unicode
41 |
42 |
43 | StaticLibrary
44 | true
45 | v143
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v143
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 | true
81 |
82 |
83 | false
84 |
85 |
86 |
87 | Level3
88 | true
89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
90 | true
91 |
92 |
93 | Console
94 | true
95 |
96 |
97 |
98 |
99 | Level3
100 | true
101 | true
102 | true
103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
104 | true
105 |
106 |
107 | Console
108 | true
109 | true
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 | true
117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
118 | true
119 |
120 |
121 | Console
122 | true
123 |
124 |
125 |
126 |
127 | Level3
128 | true
129 | true
130 | true
131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
132 | true
133 |
134 |
135 | Console
136 | true
137 | true
138 | true
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/parser.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Objective-C encoding parser library
3 | *
4 | * Copyright (c) 2022 Cyandev.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | #include
26 | #include
27 |
28 | #include "parser.h"
29 | #include "cursor.h"
30 | #include "strings.h"
31 | #include "common.h"
32 |
33 | static ocep_type_node_t ocep_type_node_new(void) {
34 | ocep_type_node_t node = (ocep_type_node_t) malloc(sizeof(struct ocep_type_node));
35 | node->type = OBJC_TYPE_UNKNOWN;
36 | node->modifiers = 0;
37 | node->child_num = 0;
38 | node->size = 0;
39 | node->alignment = 0;
40 | node->name = NULL;
41 | node->parent = NULL;
42 | node->first_child = NULL;
43 | node->next_sibling = NULL;
44 | return node;
45 | }
46 |
47 | static void ocep_type_node_free_internal(ocep_type_node_t node) {
48 | if (node->name) {
49 | free((void *) node->name);
50 | }
51 | free(node);
52 | }
53 |
54 | static NO_INLINE int _parse_number(ocep_cursor_t cursor) {
55 | int num = 0;
56 | char tok;
57 | while (!ocep_cursor_is_eof(cursor)) {
58 | tok = ocep_cursor_peek(cursor);
59 | if (tok < '0' || tok > '9') {
60 | return num;
61 | }
62 | num = num * 10 + (tok - '0');
63 | ocep_cursor_step(cursor);
64 | }
65 | return num;
66 | }
67 |
68 | static ALWAYS_INLINE void _skip_digits(ocep_cursor_t cursor) {
69 | (void) _parse_number(cursor);
70 | }
71 |
72 | static ocep_type_node_t _parse_one_element(ocep_cursor_t cursor, ocep_type_node_t parent);
73 |
74 | static void _parse_struct_or_union(int type, ocep_cursor_t cursor, ocep_type_node_t node) {
75 | // Structs are represented as "{name=??}", the cursor has moved pass '{'
76 | // when this function is called.
77 |
78 | char close_tok;
79 | if (type == OBJC_TYPE_STRUCT) {
80 | close_tok = '}';
81 | } else {
82 | close_tok = ')';
83 | }
84 |
85 | // Collect struct name.
86 | strbuf name_buf = strbuf_alloc("", 8);
87 | while (!ocep_cursor_is_eof(cursor)) {
88 | char tok_str[2] = { 0, 0 };
89 | tok_str[0] = ocep_cursor_peek(cursor);
90 | if (tok_str[0] == close_tok) {
91 | break;
92 | }
93 | ocep_cursor_step(cursor);
94 | if (tok_str[0] == '=') {
95 | break;
96 | }
97 | strbuf_append(&name_buf, tok_str);
98 | }
99 |
100 | // Parse child nodes.
101 | ocep_type_node_t last_child = NULL;
102 | while (!ocep_cursor_is_eof(cursor)) {
103 | char tok = ocep_cursor_peek(cursor);
104 | if (tok == close_tok) {
105 | ocep_cursor_step(cursor);
106 | break;
107 | }
108 |
109 | ocep_type_node_t child = _parse_one_element(cursor, node);
110 | if (last_child) {
111 | last_child->next_sibling = child;
112 | } else {
113 | node->first_child = child;
114 | }
115 | last_child = child;
116 |
117 | node->alignment = MAX(node->alignment, child->alignment);
118 | if (type == OBJC_TYPE_STRUCT) {
119 | // FIXME: current naive algorithm assumes the compact layout.
120 | node->size += child->size;
121 | } else {
122 | node->size = MAX(node->size, child->size);
123 | }
124 | ++node->child_num;
125 | }
126 |
127 | if (type == OBJC_TYPE_STRUCT) {
128 | node->size = ROUNDUP(node->size, node->alignment);
129 | }
130 |
131 | node->type = type;
132 | node->name = strbuf_take(&name_buf);
133 | }
134 |
135 | static void _parse_array(ocep_cursor_t cursor, ocep_type_node_t node) {
136 | int count = _parse_number(cursor);
137 |
138 | ocep_type_node_t child = _parse_one_element(cursor, node);
139 | node->first_child = child;
140 | node->type = OBJC_TYPE_ARRAY;
141 | node->child_num = count;
142 | node->size = child->size * count;
143 | node->alignment = child->alignment;
144 |
145 | char tok = ocep_cursor_peek(cursor);
146 | if (tok == ']') {
147 | ocep_cursor_step(cursor);
148 | }
149 | }
150 |
151 | static void _parse_pointer(ocep_cursor_t cursor, ocep_type_node_t node) {
152 | ocep_type_node_t child = _parse_one_element(cursor, node);
153 | node->first_child = child;
154 | node->type = OBJC_TYPE_POINTER;
155 | node->child_num = 1;
156 | node->size = 8;
157 | node->alignment = 8;
158 | }
159 |
160 | static ocep_type_node_t _parse_one_element(ocep_cursor_t cursor, ocep_type_node_t parent) {
161 | ocep_type_node_t node = ocep_type_node_new();
162 | node->parent = parent;
163 |
164 | while (1) {
165 | int not_modifier = 0;
166 | char tok = ocep_cursor_peek(cursor);
167 | switch (tok) {
168 | #define __OBJC_MODIFIER(_0, val, rep) \
169 | case rep: \
170 | node->modifiers |= val; \
171 | break;
172 | #include "modifiers.def"
173 | #undef __OBJC_MODIFIER
174 | default:
175 | not_modifier = 1;
176 | break;
177 | }
178 | if (not_modifier) {
179 | break;
180 | } else {
181 | ocep_cursor_step(cursor);
182 | }
183 | }
184 |
185 | char tok = ocep_cursor_step(cursor);
186 | switch (tok) {
187 | #define __NO_COMPLEX_OBJC_TYPES
188 | #define __OBJC_TYPE(_0, val, rep, siz, _1) \
189 | case rep: \
190 | node->type = val; \
191 | node->size = siz; \
192 | node->alignment = siz; \
193 | break;
194 | #include "types.def"
195 | #undef __OBJC_TYPE
196 | #undef __NO_COMPLEX_OBJC_TYPES
197 | case '{':
198 | _parse_struct_or_union(OBJC_TYPE_STRUCT, cursor, node);
199 | break;
200 | case '(':
201 | _parse_struct_or_union(OBJC_TYPE_UNION, cursor, node);
202 | break;
203 | case '[':
204 | _parse_array(cursor, node);
205 | break;
206 | case '^':
207 | _parse_pointer(cursor, node);
208 | break;
209 | }
210 |
211 | // Skip the frame sizes and offsets, if any.
212 | _skip_digits(cursor);
213 |
214 | return node;
215 | }
216 |
217 | ocep_type_node_t ocep_parse_encoding(const char *encoding) {
218 | ocep_cursor_t cursor = ocep_cursor_new(encoding);
219 |
220 | // Allocate the root node.
221 | ocep_type_node_t root = ocep_type_node_new();
222 | root->type = 0;
223 |
224 | // Consume all tokens and generate subnodes.
225 | ocep_type_node_t last_elem = NULL;
226 | while (!ocep_cursor_is_eof(cursor)) {
227 | ocep_type_node_t elem = _parse_one_element(cursor, root);
228 | if (last_elem) {
229 | last_elem->next_sibling = elem;
230 | } else {
231 | root->first_child = elem;
232 | }
233 | last_elem = elem;
234 | ++root->child_num;
235 | }
236 |
237 | ocep_cursor_free(cursor);
238 | return root;
239 | }
240 |
241 | void ocep_type_node_free(ocep_type_node_t node) {
242 | if (node->parent) {
243 | abort(); // Child nodes must not be freed via `ocep_type_node_free`.
244 | return;
245 | }
246 |
247 | // Non-recursive free with node links.
248 | ocep_type_node_t cur = node;
249 | while (cur) {
250 | ocep_type_node_t to_free = NULL;
251 | if (cur->first_child) {
252 | ocep_type_node_t next = cur->first_child;
253 | cur->first_child = NULL;
254 | cur = next;
255 | } else if (cur->next_sibling) {
256 | to_free = cur;
257 | cur = cur->next_sibling;
258 | } else {
259 | to_free = cur;
260 | cur = cur->parent;
261 | }
262 |
263 | if (to_free)
264 | ocep_type_node_free_internal(to_free);
265 | }
266 | }
267 |
268 | static void ocep_type_node_traverse_internal(ocep_type_node_t node, void *userdata,
269 | int *num, int depth,
270 | void (*cb)(ocep_type_node_t cur, int num, int depth, void *userdata)) {
271 | normal:
272 | cb(node, *num, depth, userdata);
273 | ++*num;
274 |
275 | // Visit children.
276 | ocep_type_node_t first_child = node->first_child;
277 | if (first_child) {
278 | ocep_type_node_traverse_internal(first_child, userdata, num, depth + 1, cb);
279 | }
280 |
281 | // Then visit rest siblings.
282 | ocep_type_node_t next_sibling = node->next_sibling;
283 | if (next_sibling) {
284 | node = next_sibling;
285 | goto normal; // Force tail-recursion.
286 | }
287 | }
288 |
289 | void ocep_type_node_traverse(ocep_type_node_t node, void *userdata,
290 | void (*cb)(ocep_type_node_t cur, int num, int depth, void *userdata)) {
291 | int num = 0;
292 | ocep_type_node_traverse_internal(node, userdata, &num, 0, cb);
293 | }
294 |
295 | struct __ocep_type_node_dump_state {
296 | strbuf str;
297 | };
298 |
299 | // Outlined common routine for switch cases in `ocep_type_node_dump_visitor`.
300 | static NO_INLINE void ocep_type_node_dump_outlined_1(strbuf *str_buf,
301 | int depth, const char *type, char encoding) {
302 | strbuf_append_repeat(str_buf, ' ', depth * 4);
303 | strbuf_append(str_buf, "type: ");
304 | strbuf_append(str_buf, type);
305 | strbuf_append(str_buf, "\n");
306 |
307 | strbuf_append_repeat(str_buf, ' ', depth * 4);
308 | strbuf_append(str_buf, "encoding: ");
309 | char encoding_str[2] = { encoding, 0 };
310 | strbuf_append(str_buf, encoding_str);
311 | strbuf_append(str_buf, "\n");
312 | }
313 |
314 | static NO_INLINE void ocep_type_node_dump_outlined_2(strbuf *str_buf,
315 | int depth, const char *label, int value) {
316 | strbuf_append_repeat(str_buf, ' ', depth * 4);
317 | strbuf_append(str_buf, label);
318 | char value_str[32];
319 | #if defined(CONFIG_WIN32)
320 | sprintf_s(value_str, sizeof(value_str), "%d", value);
321 | #else
322 | sprintf(value_str, "%d", value);
323 | #endif
324 | strbuf_append(str_buf, value_str);
325 | strbuf_append(str_buf, "\n");
326 | }
327 |
328 | static NO_INLINE void ocep_type_node_dump_outlined_3(strbuf *str_buf, const char *modifier) {
329 | if (str_buf->str[str_buf->len - 1] != ' ') {
330 | strbuf_append(str_buf, ", ");
331 | }
332 | strbuf_append(str_buf, modifier);
333 | }
334 |
335 | static void ocep_type_node_dump_visitor(ocep_type_node_t node, int num, int depth, void *userdata) {
336 | if (node->type == 0) {
337 | return;
338 | }
339 |
340 | --depth; // Root node is skipped.
341 |
342 | struct __ocep_type_node_dump_state* state;
343 | state = (struct __ocep_type_node_dump_state*) userdata;
344 |
345 | strbuf *str_buf = &state->str;
346 |
347 | // Draw a separator line.
348 | if (num > 1) {
349 | strbuf_append_repeat(str_buf, ' ', depth * 4);
350 | strbuf_append_repeat(str_buf, '-', 30);
351 | strbuf_append(str_buf, "\n");
352 | }
353 |
354 | switch (node->type) {
355 | #define __OBJC_TYPE(name, val, rep, _0, _1) \
356 | case val: \
357 | ocep_type_node_dump_outlined_1(str_buf, depth, #name, rep); \
358 | break;
359 | #include "types.def"
360 | #undef __OBJC_TYPE
361 | }
362 |
363 | if (node->modifiers) {
364 | strbuf_append_repeat(str_buf, ' ', depth * 4);
365 | strbuf_append(str_buf, "modifiers: ");
366 | #define __OBJC_MODIFIER(name, val, _0) \
367 | if (node->modifiers & val) { \
368 | ocep_type_node_dump_outlined_3(str_buf, #name); \
369 | }
370 | #include "modifiers.def"
371 | #undef __OBJC_MODIFIER
372 | strbuf_append(str_buf, "\n");
373 | }
374 |
375 | ocep_type_node_dump_outlined_2(str_buf, depth, "size: ", node->size);
376 | ocep_type_node_dump_outlined_2(str_buf, depth, "alignment: ", node->alignment);
377 | if (node->child_num > 1) {
378 | ocep_type_node_dump_outlined_2(str_buf, depth, "child num: ", node->child_num);
379 | }
380 |
381 | const char *name = node->name;
382 | if (name) {
383 | strbuf_append_repeat(str_buf, ' ', depth * 4);
384 | strbuf_append(str_buf, "name: ");
385 | strbuf_append(str_buf, name);
386 | strbuf_append(str_buf, "\n");
387 | }
388 | }
389 |
390 | char *ocep_type_node_dump(ocep_type_node_t node) {
391 | struct __ocep_type_node_dump_state state;
392 | state.str = strbuf_alloc("", 128);
393 | ocep_type_node_traverse(node, &state, &ocep_type_node_dump_visitor);
394 | return strbuf_take(&state.str);
395 | }
396 |
--------------------------------------------------------------------------------
/ObjcEncodingParser.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 55;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | FA8450CE2811C642007162A3 /* parser.c in Sources */ = {isa = PBXBuildFile; fileRef = FA5D07F52810636F00ED9CA4 /* parser.c */; };
11 | FA8450D02811C647007162A3 /* liblibocep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA8450CA2811C639007162A3 /* liblibocep.a */; };
12 | FA8450D32811C64E007162A3 /* run-test.c in Sources */ = {isa = PBXBuildFile; fileRef = FA5D07F02810636F00ED9CA4 /* run-test.c */; };
13 | /* End PBXBuildFile section */
14 |
15 | /* Begin PBXContainerItemProxy section */
16 | FA8450D12811C64B007162A3 /* PBXContainerItemProxy */ = {
17 | isa = PBXContainerItemProxy;
18 | containerPortal = FAF1B151280F2A8500ABBA15 /* Project object */;
19 | proxyType = 1;
20 | remoteGlobalIDString = FA8450C92811C639007162A3;
21 | remoteInfo = libocep;
22 | };
23 | /* End PBXContainerItemProxy section */
24 |
25 | /* Begin PBXCopyFilesBuildPhase section */
26 | FA8450BD2811C615007162A3 /* CopyFiles */ = {
27 | isa = PBXCopyFilesBuildPhase;
28 | buildActionMask = 2147483647;
29 | dstPath = /usr/share/man/man1/;
30 | dstSubfolderSpec = 0;
31 | files = (
32 | );
33 | runOnlyForDeploymentPostprocessing = 1;
34 | };
35 | /* End PBXCopyFilesBuildPhase section */
36 |
37 | /* Begin PBXFileReference section */
38 | ED7091602C84405B0056D465 /* modifiers.def */ = {isa = PBXFileReference; lastKnownFileType = text; path = modifiers.def; sourceTree = ""; };
39 | FA5D07EF2810636F00ED9CA4 /* strings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = strings.h; sourceTree = ""; };
40 | FA5D07F02810636F00ED9CA4 /* run-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "run-test.c"; sourceTree = ""; };
41 | FA5D07F12810636F00ED9CA4 /* types.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = types.def; sourceTree = ""; };
42 | FA5D07F22810636F00ED9CA4 /* cursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cursor.h; sourceTree = ""; };
43 | FA5D07F32810636F00ED9CA4 /* parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = ""; };
44 | FA5D07F42810636F00ED9CA4 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; };
45 | FA5D07F52810636F00ED9CA4 /* parser.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parser.c; sourceTree = ""; };
46 | FA8450BF2811C615007162A3 /* RunTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = RunTest; sourceTree = BUILT_PRODUCTS_DIR; };
47 | FA8450CA2811C639007162A3 /* liblibocep.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = liblibocep.a; sourceTree = BUILT_PRODUCTS_DIR; };
48 | /* End PBXFileReference section */
49 |
50 | /* Begin PBXFrameworksBuildPhase section */
51 | FA8450BC2811C615007162A3 /* Frameworks */ = {
52 | isa = PBXFrameworksBuildPhase;
53 | buildActionMask = 2147483647;
54 | files = (
55 | FA8450D02811C647007162A3 /* liblibocep.a in Frameworks */,
56 | );
57 | runOnlyForDeploymentPostprocessing = 0;
58 | };
59 | FA8450C82811C639007162A3 /* Frameworks */ = {
60 | isa = PBXFrameworksBuildPhase;
61 | buildActionMask = 2147483647;
62 | files = (
63 | );
64 | runOnlyForDeploymentPostprocessing = 0;
65 | };
66 | /* End PBXFrameworksBuildPhase section */
67 |
68 | /* Begin PBXGroup section */
69 | FA8450CF2811C647007162A3 /* Frameworks */ = {
70 | isa = PBXGroup;
71 | children = (
72 | );
73 | name = Frameworks;
74 | sourceTree = "";
75 | };
76 | FAF1B150280F2A8500ABBA15 = {
77 | isa = PBXGroup;
78 | children = (
79 | FA5D07F42810636F00ED9CA4 /* common.h */,
80 | FA5D07F22810636F00ED9CA4 /* cursor.h */,
81 | FA5D07F52810636F00ED9CA4 /* parser.c */,
82 | FA5D07F32810636F00ED9CA4 /* parser.h */,
83 | FA5D07F02810636F00ED9CA4 /* run-test.c */,
84 | FA5D07EF2810636F00ED9CA4 /* strings.h */,
85 | FA5D07F12810636F00ED9CA4 /* types.def */,
86 | ED7091602C84405B0056D465 /* modifiers.def */,
87 | FAF1B15A280F2A8500ABBA15 /* Products */,
88 | FA8450CF2811C647007162A3 /* Frameworks */,
89 | );
90 | sourceTree = "";
91 | };
92 | FAF1B15A280F2A8500ABBA15 /* Products */ = {
93 | isa = PBXGroup;
94 | children = (
95 | FA8450BF2811C615007162A3 /* RunTest */,
96 | FA8450CA2811C639007162A3 /* liblibocep.a */,
97 | );
98 | name = Products;
99 | sourceTree = "";
100 | };
101 | /* End PBXGroup section */
102 |
103 | /* Begin PBXHeadersBuildPhase section */
104 | FA8450C62811C639007162A3 /* Headers */ = {
105 | isa = PBXHeadersBuildPhase;
106 | buildActionMask = 2147483647;
107 | files = (
108 | );
109 | runOnlyForDeploymentPostprocessing = 0;
110 | };
111 | /* End PBXHeadersBuildPhase section */
112 |
113 | /* Begin PBXNativeTarget section */
114 | FA8450BE2811C615007162A3 /* RunTest */ = {
115 | isa = PBXNativeTarget;
116 | buildConfigurationList = FA8450C52811C615007162A3 /* Build configuration list for PBXNativeTarget "RunTest" */;
117 | buildPhases = (
118 | FA8450BB2811C615007162A3 /* Sources */,
119 | FA8450BC2811C615007162A3 /* Frameworks */,
120 | FA8450BD2811C615007162A3 /* CopyFiles */,
121 | );
122 | buildRules = (
123 | );
124 | dependencies = (
125 | FA8450D22811C64B007162A3 /* PBXTargetDependency */,
126 | );
127 | name = RunTest;
128 | productName = RunTest;
129 | productReference = FA8450BF2811C615007162A3 /* RunTest */;
130 | productType = "com.apple.product-type.tool";
131 | };
132 | FA8450C92811C639007162A3 /* libocep */ = {
133 | isa = PBXNativeTarget;
134 | buildConfigurationList = FA8450CB2811C639007162A3 /* Build configuration list for PBXNativeTarget "libocep" */;
135 | buildPhases = (
136 | FA8450C62811C639007162A3 /* Headers */,
137 | FA8450C72811C639007162A3 /* Sources */,
138 | FA8450C82811C639007162A3 /* Frameworks */,
139 | );
140 | buildRules = (
141 | );
142 | dependencies = (
143 | );
144 | name = libocep;
145 | productName = libocep;
146 | productReference = FA8450CA2811C639007162A3 /* liblibocep.a */;
147 | productType = "com.apple.product-type.library.static";
148 | };
149 | /* End PBXNativeTarget section */
150 |
151 | /* Begin PBXProject section */
152 | FAF1B151280F2A8500ABBA15 /* Project object */ = {
153 | isa = PBXProject;
154 | attributes = {
155 | BuildIndependentTargetsInParallel = 1;
156 | LastUpgradeCheck = 1330;
157 | TargetAttributes = {
158 | FA8450BE2811C615007162A3 = {
159 | CreatedOnToolsVersion = 13.3;
160 | };
161 | FA8450C92811C639007162A3 = {
162 | CreatedOnToolsVersion = 13.3;
163 | };
164 | };
165 | };
166 | buildConfigurationList = FAF1B154280F2A8500ABBA15 /* Build configuration list for PBXProject "ObjcEncodingParser" */;
167 | compatibilityVersion = "Xcode 13.0";
168 | developmentRegion = en;
169 | hasScannedForEncodings = 0;
170 | knownRegions = (
171 | en,
172 | Base,
173 | );
174 | mainGroup = FAF1B150280F2A8500ABBA15;
175 | productRefGroup = FAF1B15A280F2A8500ABBA15 /* Products */;
176 | projectDirPath = "";
177 | projectRoot = "";
178 | targets = (
179 | FA8450BE2811C615007162A3 /* RunTest */,
180 | FA8450C92811C639007162A3 /* libocep */,
181 | );
182 | };
183 | /* End PBXProject section */
184 |
185 | /* Begin PBXSourcesBuildPhase section */
186 | FA8450BB2811C615007162A3 /* Sources */ = {
187 | isa = PBXSourcesBuildPhase;
188 | buildActionMask = 2147483647;
189 | files = (
190 | FA8450D32811C64E007162A3 /* run-test.c in Sources */,
191 | );
192 | runOnlyForDeploymentPostprocessing = 0;
193 | };
194 | FA8450C72811C639007162A3 /* Sources */ = {
195 | isa = PBXSourcesBuildPhase;
196 | buildActionMask = 2147483647;
197 | files = (
198 | FA8450CE2811C642007162A3 /* parser.c in Sources */,
199 | );
200 | runOnlyForDeploymentPostprocessing = 0;
201 | };
202 | /* End PBXSourcesBuildPhase section */
203 |
204 | /* Begin PBXTargetDependency section */
205 | FA8450D22811C64B007162A3 /* PBXTargetDependency */ = {
206 | isa = PBXTargetDependency;
207 | target = FA8450C92811C639007162A3 /* libocep */;
208 | targetProxy = FA8450D12811C64B007162A3 /* PBXContainerItemProxy */;
209 | };
210 | /* End PBXTargetDependency section */
211 |
212 | /* Begin XCBuildConfiguration section */
213 | FA8450C32811C615007162A3 /* Debug */ = {
214 | isa = XCBuildConfiguration;
215 | buildSettings = {
216 | CODE_SIGN_STYLE = Automatic;
217 | PRODUCT_NAME = "$(TARGET_NAME)";
218 | };
219 | name = Debug;
220 | };
221 | FA8450C42811C615007162A3 /* Release */ = {
222 | isa = XCBuildConfiguration;
223 | buildSettings = {
224 | CODE_SIGN_STYLE = Automatic;
225 | PRODUCT_NAME = "$(TARGET_NAME)";
226 | };
227 | name = Release;
228 | };
229 | FA8450CC2811C639007162A3 /* Debug */ = {
230 | isa = XCBuildConfiguration;
231 | buildSettings = {
232 | ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
233 | CODE_SIGN_STYLE = Automatic;
234 | EXECUTABLE_PREFIX = lib;
235 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
236 | PRODUCT_NAME = "$(TARGET_NAME)";
237 | SDKROOT = macosx;
238 | SKIP_INSTALL = YES;
239 | SUPPORTED_PLATFORMS = "watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
240 | SUPPORTS_MACCATALYST = YES;
241 | TVOS_DEPLOYMENT_TARGET = 11.0;
242 | WATCHOS_DEPLOYMENT_TARGET = 4.0;
243 | };
244 | name = Debug;
245 | };
246 | FA8450CD2811C639007162A3 /* Release */ = {
247 | isa = XCBuildConfiguration;
248 | buildSettings = {
249 | ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
250 | CODE_SIGN_STYLE = Automatic;
251 | EXECUTABLE_PREFIX = lib;
252 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
253 | PRODUCT_NAME = "$(TARGET_NAME)";
254 | SDKROOT = macosx;
255 | SKIP_INSTALL = YES;
256 | SUPPORTED_PLATFORMS = "watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
257 | SUPPORTS_MACCATALYST = YES;
258 | TVOS_DEPLOYMENT_TARGET = 11.0;
259 | WATCHOS_DEPLOYMENT_TARGET = 4.0;
260 | };
261 | name = Release;
262 | };
263 | FAF1B15E280F2A8500ABBA15 /* Debug */ = {
264 | isa = XCBuildConfiguration;
265 | buildSettings = {
266 | ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
267 | ALWAYS_SEARCH_USER_PATHS = NO;
268 | CLANG_ANALYZER_NONNULL = YES;
269 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
270 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
271 | CLANG_ENABLE_MODULES = YES;
272 | CLANG_ENABLE_OBJC_ARC = YES;
273 | CLANG_ENABLE_OBJC_WEAK = YES;
274 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
275 | CLANG_WARN_BOOL_CONVERSION = YES;
276 | CLANG_WARN_COMMA = YES;
277 | CLANG_WARN_CONSTANT_CONVERSION = YES;
278 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
279 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
280 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
281 | CLANG_WARN_EMPTY_BODY = YES;
282 | CLANG_WARN_ENUM_CONVERSION = YES;
283 | CLANG_WARN_INFINITE_RECURSION = YES;
284 | CLANG_WARN_INT_CONVERSION = YES;
285 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
286 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
287 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
288 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
289 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
290 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
291 | CLANG_WARN_STRICT_PROTOTYPES = YES;
292 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
293 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
294 | CLANG_WARN_UNREACHABLE_CODE = YES;
295 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
296 | COPY_PHASE_STRIP = NO;
297 | DEBUG_INFORMATION_FORMAT = dwarf;
298 | ENABLE_STRICT_OBJC_MSGSEND = YES;
299 | ENABLE_TESTABILITY = YES;
300 | GCC_C_LANGUAGE_STANDARD = gnu11;
301 | GCC_DYNAMIC_NO_PIC = NO;
302 | GCC_NO_COMMON_BLOCKS = YES;
303 | GCC_OPTIMIZATION_LEVEL = 0;
304 | GCC_PREPROCESSOR_DEFINITIONS = (
305 | "DEBUG=1",
306 | "$(inherited)",
307 | );
308 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
309 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
310 | GCC_WARN_UNDECLARED_SELECTOR = YES;
311 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
312 | GCC_WARN_UNUSED_FUNCTION = YES;
313 | GCC_WARN_UNUSED_VARIABLE = YES;
314 | MACOSX_DEPLOYMENT_TARGET = 10.13;
315 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
316 | MTL_FAST_MATH = YES;
317 | ONLY_ACTIVE_ARCH = YES;
318 | SDKROOT = macosx;
319 | SUPPORTED_PLATFORMS = "watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
320 | SUPPORTS_MACCATALYST = YES;
321 | };
322 | name = Debug;
323 | };
324 | FAF1B15F280F2A8500ABBA15 /* Release */ = {
325 | isa = XCBuildConfiguration;
326 | buildSettings = {
327 | ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
328 | ALWAYS_SEARCH_USER_PATHS = NO;
329 | CLANG_ANALYZER_NONNULL = YES;
330 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
331 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
332 | CLANG_ENABLE_MODULES = YES;
333 | CLANG_ENABLE_OBJC_ARC = YES;
334 | CLANG_ENABLE_OBJC_WEAK = YES;
335 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
336 | CLANG_WARN_BOOL_CONVERSION = YES;
337 | CLANG_WARN_COMMA = YES;
338 | CLANG_WARN_CONSTANT_CONVERSION = YES;
339 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
340 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
341 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
342 | CLANG_WARN_EMPTY_BODY = YES;
343 | CLANG_WARN_ENUM_CONVERSION = YES;
344 | CLANG_WARN_INFINITE_RECURSION = YES;
345 | CLANG_WARN_INT_CONVERSION = YES;
346 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
347 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
348 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
349 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
350 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
351 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
352 | CLANG_WARN_STRICT_PROTOTYPES = YES;
353 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
354 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
355 | CLANG_WARN_UNREACHABLE_CODE = YES;
356 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
357 | COPY_PHASE_STRIP = NO;
358 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
359 | ENABLE_NS_ASSERTIONS = NO;
360 | ENABLE_STRICT_OBJC_MSGSEND = YES;
361 | GCC_C_LANGUAGE_STANDARD = gnu11;
362 | GCC_NO_COMMON_BLOCKS = YES;
363 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
364 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
365 | GCC_WARN_UNDECLARED_SELECTOR = YES;
366 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
367 | GCC_WARN_UNUSED_FUNCTION = YES;
368 | GCC_WARN_UNUSED_VARIABLE = YES;
369 | MACOSX_DEPLOYMENT_TARGET = 10.13;
370 | MTL_ENABLE_DEBUG_INFO = NO;
371 | MTL_FAST_MATH = YES;
372 | SDKROOT = macosx;
373 | SUPPORTED_PLATFORMS = "watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
374 | SUPPORTS_MACCATALYST = YES;
375 | };
376 | name = Release;
377 | };
378 | /* End XCBuildConfiguration section */
379 |
380 | /* Begin XCConfigurationList section */
381 | FA8450C52811C615007162A3 /* Build configuration list for PBXNativeTarget "RunTest" */ = {
382 | isa = XCConfigurationList;
383 | buildConfigurations = (
384 | FA8450C32811C615007162A3 /* Debug */,
385 | FA8450C42811C615007162A3 /* Release */,
386 | );
387 | defaultConfigurationIsVisible = 0;
388 | defaultConfigurationName = Release;
389 | };
390 | FA8450CB2811C639007162A3 /* Build configuration list for PBXNativeTarget "libocep" */ = {
391 | isa = XCConfigurationList;
392 | buildConfigurations = (
393 | FA8450CC2811C639007162A3 /* Debug */,
394 | FA8450CD2811C639007162A3 /* Release */,
395 | );
396 | defaultConfigurationIsVisible = 0;
397 | defaultConfigurationName = Release;
398 | };
399 | FAF1B154280F2A8500ABBA15 /* Build configuration list for PBXProject "ObjcEncodingParser" */ = {
400 | isa = XCConfigurationList;
401 | buildConfigurations = (
402 | FAF1B15E280F2A8500ABBA15 /* Debug */,
403 | FAF1B15F280F2A8500ABBA15 /* Release */,
404 | );
405 | defaultConfigurationIsVisible = 0;
406 | defaultConfigurationName = Release;
407 | };
408 | /* End XCConfigurationList section */
409 | };
410 | rootObject = FAF1B151280F2A8500ABBA15 /* Project object */;
411 | }
412 |
--------------------------------------------------------------------------------