sogo/OpenChange/gen-property-selectors.py

267 lines
8.8 KiB
Python
Executable File

#!/usr/bin/python
include_dirs = [ "/usr/include" ]
output = "-"
import os
import sys
m_template = """/* %(filename)s (auto-generated) */
#include <objc/objc.h>
#include <stdint.h>
#import "%(h_filename)s"
const NSUInteger MAPIStorePropertyGettersCount = %(nbr_getters)d;
const NSUInteger MAPIStoreLastPropertyIdx = %(last_property)d;
const NSUInteger MAPIStoreSupportedPropertiesCount = %(nbr_supported_properties)d;
const enum MAPITAGS MAPIStoreSupportedProperties[] = {
%(supported_properties)s
};
static const uint16_t MAPIStorePropertyGettersIdx[] = {
%(getters_idx)s
};
static const SEL MAPIStorePropertyGetterSelectors[] = {
%(getters)s
};
#include "code-%(filename)s"
"""
h_template = """/* %(filename)s (auto-generated) */
#ifndef %(h_exclusion)s
#define %(h_exclusion)s 1
#import <Foundation/NSObjCRuntime.h>
#include <stdbool.h>
#include <talloc.h>
#include <util/time.h>
#include <gen_ndr/exchange.h>
extern const NSUInteger MAPIStorePropertyGettersCount;
extern const NSUInteger MAPIStoreLastPropertyIdx;
extern const NSUInteger MAPIStoreSupportedPropertiesCount;
extern const enum MAPITAGS MAPIStoreSupportedProperties[];
#import "MAPIStoreObject.h"
@interface MAPIStoreObject (MAPIStorePropertySelectors)
%(prototypes)s
@end
#include "code-%(filename)s"
#endif /* %(h_exclusion)s */
"""
# hack: some properties have multiple and incompatible types. Sometimes those
# props are not related at all...
bannedProps = set(["PidTagBodyHtml", "PidTagFavAutosubfolders",
"PidTagAttachDataObj", "PidTagAclTable", "PidTagAclData",
"PidTagRulesTable", "PidTagRulesData",
"PidTagDisableWinsock",
"PidTagHierarchyServer", "PidTagOfflineAddrbookEntryid",
"PidTagShorttermEntryidFromObject",
"PidTagNormalMessageSizeExtended",
"PidTagAssocMessageSizeExtended",
"PidTagMessageSizeExtended",
"PidTagOabContainerGuid",
"PidTagOfflineAddressBookMessageClass", "PidTagScriptData",
"PidTagOfflineAddressBookTruncatedProperties",
"PidTagOfflineAddressBookContainerGuid",
"PidTagOfflineAddressBookDistinguishedName",
"PidTagOfflineAddressBookShaHash",
"PidTagSenderTelephoneNumber",
"PidTagGatewayNeedsToRefresh",
"PidTagWlinkType", "PidTagWlinkFlags",
"PidTagWlinkGroupClsid", "PidTagWlinkGroupName",
"PidTagWlinkGroupHeaderID",
"PidTagScheduleInfoDelegatorWantsCopy",
"PidTagWlinkOrdinal",
"PidTagWlinkSection", "PidTagWlinkCalendarColor",
"PidTagWlinkAddressBookEID", "PidTagWlinkFolderType",
"PidTagScheduleInfoDelegateNames",
"PidTagScheduleInfoDelegateEntryIds",
"PidTagBusiness2TelephoneNumbers",
"PidTagHome2TelephoneNumbers",
"PidTagAttachDataObject",
"PidTagShorttermEntryIdFromObject",
])
def ParseExchangeH(names, lines):
state = 0
maxlines = len(lines)
x = 0
while x < maxlines and state != 3:
stripped = lines[x].strip()
if state == 0:
if stripped == "enum MAPITAGS":
state = 1
elif state == 1:
if stripped == "{":
state = 2
elif state == 2:
if stripped == "}":
state = 3
else:
ParseExchangeHDefinition(names, stripped)
x = x + 1
def ParseExchangeHDefinition(names, line):
stripped = line.strip()
eqIdx = stripped.find("=")
if eqIdx == -1:
raise Exception, "line does not contain a '='"
propName = stripped[0:eqIdx]
if not propName.endswith("_Error") and not propName.endswith("_string8") \
and propName not in bannedProps:
intIdx = stripped.find("(int", eqIdx)
valueIdx = stripped.find("0x", intIdx + 1)
endIdx = stripped.find(")", valueIdx)
value = int(stripped[valueIdx:endIdx], 16)
if value < 0x80000000:
names[propName] = value
def ParseMapistoreNameIDH(names, lines):
for line in lines:
stripped = line.strip()
if stripped.startswith("#define Pid"):
ParseMapistoreNameIDHDefinition(names, stripped)
def ParseMapistoreNameIDHDefinition(names, line):
stripped = line.strip()
pidIdx = stripped.find("Pid")
if pidIdx == -1:
raise Exception, "line does not contain a 'Pid'"
valueIdx = stripped.find("0x")
propName = stripped[pidIdx:valueIdx].strip()
if not propName.startswith("PidLidUnknown") and propName not in bannedProps:
value = int(stripped[valueIdx:], 16)
names[propName] = value
def FindHFile(filename):
found = None
for dirname in include_dirs:
full_filename = "%s/%s" % (dirname, filename)
if os.path.exists(full_filename):
found = full_filename
if found is None:
raise Exception, "'%s' not found in include dirs" % filename
return found
def ProcessHeaders(names, hdict):
for filename in hdict:
header_filename = FindHFile(filename)
header_file = open(header_filename, "r")
lines = header_file.readlines()
header_file.close()
hdict[filename](names, lines)
if __name__ == "__main__":
arg_count = len(sys.argv)
x = 0
while x < arg_count:
arg = sys.argv[x]
argname = None
if arg.startswith("-"):
argname = arg[1]
if len(arg) == 2:
argvalue = sys.argv[x + 1]
x = x + 1
else:
argvalue = arg[2:]
x = x + 1
if argname == "o":
output = argvalue
elif argname == "I":
include_dirs.append(argvalue)
names = {}
ProcessHeaders(names,
{"gen_ndr/exchange.h": ParseExchangeH,
"mapistore/mapistore_nameid.h": ParseMapistoreNameIDH})
getters = []
getters_idx = []
# setters = []
# preferred_types = []
prototypes = []
for x in xrange(0x10000):
getters_idx.append(" 0xffff")
# setters.append(" NULL")
prop_types = {}
# sanitization: only take unicode version of text properties
for name, prop_tag in names.iteritems():
prop_id = prop_tag >> 16
prop_type = prop_tag & 0xffff
if not prop_id in prop_types:
prop_types[prop_id] = []
prop_types[prop_id].append(prop_type)
if (prop_type & 0xfff) == 0x001e:
prop_tag = (prop_tag & 0xfffff000) | 0x001f
names[name] = prop_tag
#sanitization: report multiple types for the same keynames
for prop_id, xtypes in prop_types.iteritems():
cnt = len(xtypes)
if cnt > 1:
print "%d types available for prop id 0x%.4x: %s" % (cnt, prop_id, ", ".join(["%.4x" % x for x in xtypes]))
supported_properties = []
current_getter_idx = 0
highest_prop_idx = 0
for name, prop_tag in names.iteritems():
supported_properties.append(" 0x%.8x" % prop_tag);
prop_idx = (prop_tag & 0xffff0000) >> 16
getters_idx[prop_idx] = " 0x%.4x" % current_getter_idx
if prop_idx > highest_prop_idx:
highest_prop_idx = prop_idx
getters.append(" @selector (get%s:inMemCtx:)" % name)
# preferred_types.append(" 0x%.4x" % (prop_tag & 0xffff))
prototypes.append("- (int) get%s: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;" % name)
current_getter_idx = current_getter_idx + 1
# setters[prop_idx] = " @selector (set%s:)" % name
# prototypes.append("- (int) set%s: (void **) data;" % name)
# prototypes.append("")
filename = "%s.m" % output
h_filename = "%s.h" % output
outf = open(filename, "wb+")
outf.write(m_template % {"getters_idx": ",\n".join(getters_idx),
"getters": ",\n".join(getters),
"nbr_getters": len(getters),
"last_property": highest_prop_idx,
"nbr_supported_properties": len(supported_properties),
"supported_properties": ",\n".join(supported_properties),
"filename": filename,
"h_filename": h_filename})
outf.close()
outf = open(h_filename, "wb+")
exclusion = ""
for x in h_filename.upper():
if ord(x) < 65 or ord(x) > 90:
x = "_"
exclusion = exclusion + x
outf.write(h_template % {"prototypes": "\n".join(prototypes),
"h_exclusion": exclusion,
"filename": h_filename })
outf.close()