1# Scan an Apple header file, generating a Python file of generator calls.
2
3import sys
4from bgenlocations import TOOLBOXDIR, BGENDIR
5sys.path.append(BGENDIR)
6from scantools import Scanner_OSX
7
8LONG = "CoreFoundation"
9SHORT = "cf"
10OBJECTS = ("CFTypeRef",
11                "CFArrayRef", "CFMutableArrayRef",
12                "CFDataRef", "CFMutableDataRef",
13                "CFDictionaryRef", "CFMutableDictionaryRef",
14                "CFStringRef", "CFMutableStringRef",
15                "CFURLRef",
16##              "CFPropertyListRef",
17                )
18# ADD object typenames here
19
20def main():
21    input = [
22            "CFBase.h",
23            "CFArray.h",
24##              "CFBag.h",
25##              "CFBundle.h",
26##              "CFCharacterSet.h",
27            "CFData.h",
28##              "CFDate.h",
29            "CFDictionary.h",
30##              "CFNumber.h",
31##              "CFPlugIn.h",
32            "CFPreferences.h",
33            "CFPropertyList.h",
34##              "CFSet.h",
35            "CFString.h",
36##              "CFStringEncodingExt.h",
37##              "CFTimeZone.h",
38            "CFURL.h",
39            ]
40    output = SHORT + "gen.py"
41    defsoutput = TOOLBOXDIR + LONG + ".py"
42    scanner = MyScanner(input, output, defsoutput)
43    scanner.scan()
44    scanner.gentypetest(SHORT+"typetest.py")
45    scanner.close()
46    print "=== Testing definitions output code ==="
47    execfile(defsoutput, {}, {})
48    print "=== Done scanning and generating, now importing the generated code... ==="
49    exec "import " + SHORT + "support"
50    print "=== Done.  It's up to you to compile it now! ==="
51
52class MyScanner(Scanner_OSX):
53
54    def destination(self, type, name, arglist):
55        classname = "Function"
56        listname = "functions"
57        if arglist and name[:13] != 'CFPreferences':
58            t, n, m = arglist[0]
59            if t in OBJECTS and m == "InMode":
60                classname = "Method"
61                listname = t + "_methods"
62            # Special case for the silly first AllocatorRef argument
63            if t == 'CFAllocatorRef' and m == 'InMode' and len(arglist) > 1:
64                t, n, m = arglist[1]
65                if t in OBJECTS and m == "InMode":
66                    classname = "MethodSkipArg1"
67                    listname = t + "_methods"
68        return classname, listname
69
70    def writeinitialdefs(self):
71        self.defsfile.write("def FOUR_CHAR_CODE(x): return x\n")
72
73    def makeblacklistnames(self):
74        return [
75                # Memory allocator functions
76                "CFAllocatorGetDefault",
77                "CFAllocatorSetDefault",
78                "CFAllocatorAllocate",
79                "CFAllocatorReallocate",
80                "CFAllocatorDeallocate",
81                "CFGetAllocator",
82                # Array functions we skip for now.
83                "CFArrayGetValueAtIndex",
84                # Data pointer functions. Skip for now.
85                "CFDataGetBytePtr",
86                "CFDataGetMutableBytePtr",
87                "CFDataGetBytes",   # XXXX Should support this one
88                # String functions
89                "CFStringGetPascalString", # Use the C-string methods.
90                "CFStringGetPascalStringPtr", # TBD automatically
91                "CFStringGetCStringPtr",
92                "CFStringGetCharactersPtr",
93                "CFStringGetCString",
94                "CFStringGetCharacters",
95                "CFURLCreateStringWithFileSystemPath", # Gone in later releases
96                "CFStringCreateMutableWithExternalCharactersNoCopy", # Not a clue...
97                "CFStringSetExternalCharactersNoCopy",
98                "CFStringGetCharacterAtIndex", # No format for single unichars yet.
99                "kCFStringEncodingInvalidId", # incompatible constant declaration
100                "CFPropertyListCreateFromXMLData", # Manually generated
101                ]
102
103    def makegreylist(self):
104        return []
105
106    def makeblacklisttypes(self):
107        return [
108                "CFComparatorFunction", # Callback function pointer
109                "CFAllocatorContext", # Not interested in providing our own allocator
110                "void_ptr_ptr",  # Tricky. This is the initializer for arrays...
111                "void_ptr", # Ditto for various array lookup methods
112                "CFArrayApplierFunction", # Callback function pointer
113                "CFDictionaryApplierFunction", # Callback function pointer
114                "va_list", # For printf-to-a-cfstring. Use Python.
115                "const_CFStringEncoding_ptr", # To be done, I guess
116                ]
117
118    def makerepairinstructions(self):
119        return [
120                # Buffers in CF seem to be passed as UInt8 * normally.
121                ([("UInt8_ptr", "*", "InMode"), ("CFIndex", "*", "InMode")],
122                 [("UcharInBuffer", "*", "*")]),
123
124                ([("UniChar_ptr", "*", "InMode"), ("CFIndex", "*", "InMode")],
125                 [("UnicodeInBuffer", "*", "*")]),
126
127                # Some functions return a const char *. Don't worry, we won't modify it.
128                ([("const_char_ptr", "*", "ReturnMode")],
129                 [("return_stringptr", "*", "*")]),
130
131                # base URLs are optional (pass None for NULL)
132                ([("CFURLRef", "baseURL", "InMode")],
133                 [("OptionalCFURLRef", "*", "*")]),
134
135                # We handle CFPropertyListRef objects as plain CFTypeRef
136                ([("CFPropertyListRef", "*", "*")],
137                 [("CFTypeRef", "*", "*")]),
138                ]
139
140if __name__ == "__main__":
141    main()
142