summaryrefslogtreecommitdiff
path: root/packages/cocoaint
diff options
context:
space:
mode:
authorjosef <josef@3ad0048d-3df7-0310-abae-a5850022a9f2>2009-12-20 14:29:12 +0000
committerjosef <josef@3ad0048d-3df7-0310-abae-a5850022a9f2>2009-12-20 14:29:12 +0000
commit8eb51c6f5876ee07498fc639edebcb014d6e52fc (patch)
tree6ce1e4d6ad7776fe1d873c2ba35bc094baa2e53b /packages/cocoaint
parent93688fcbcbaae3f7c445e3981454b3658f69ebca (diff)
downloadfpc-8eb51c6f5876ee07498fc639edebcb014d6e52fc.tar.gz
* Added missing UndefinedClasses.inc to /uikit
* Changed the PHP variable which was causing the parser to not produce iphone headers * Added /utils/iphone directory which is the last safe version of the parser. This is because future versions of the parser will likely break the iphone parsing ability before it can be fully restored. git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@14454 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/cocoaint')
-rwxr-xr-xpackages/cocoaint/src/uikit/UndefinedClasses.inc13
-rw-r--r--packages/cocoaint/utils/iphone/iPhone Parser.txt1
-rw-r--r--packages/cocoaint/utils/iphone/objp_parser.php560
-rwxr-xr-xpackages/cocoaint/utils/iphone/parser.php283
-rw-r--r--packages/cocoaint/utils/iphone/pascocoa_parser.php4163
-rwxr-xr-xpackages/cocoaint/utils/parser.php3
6 files changed, 5021 insertions, 2 deletions
diff --git a/packages/cocoaint/src/uikit/UndefinedClasses.inc b/packages/cocoaint/src/uikit/UndefinedClasses.inc
new file mode 100755
index 0000000000..195bcd1b4a
--- /dev/null
+++ b/packages/cocoaint/src/uikit/UndefinedClasses.inc
@@ -0,0 +1,13 @@
+
+{ Private instance variables from UITextField.h }
+UITextFieldBorderView = id;
+UITextFieldBackgroundView = id;
+UITextFieldLabel = id;
+UITextFieldAtomBackgroundView = id;
+
+{ Private instance variables from UITextView.h }
+WebFrame = id;
+WebCoreFrameBridge = id;
+DOMHTMLElement = id;
+UIDelayedAction = id;
+UIWebDocumentView = id; \ No newline at end of file
diff --git a/packages/cocoaint/utils/iphone/iPhone Parser.txt b/packages/cocoaint/utils/iphone/iPhone Parser.txt
new file mode 100644
index 0000000000..ac5d06521a
--- /dev/null
+++ b/packages/cocoaint/utils/iphone/iPhone Parser.txt
@@ -0,0 +1 @@
+This is the latest version of the iphone parser archived here so that future changes (to the Objective Pascal syntax) don't affect the iphone parsing ability. \ No newline at end of file
diff --git a/packages/cocoaint/utils/iphone/objp_parser.php b/packages/cocoaint/utils/iphone/objp_parser.php
new file mode 100644
index 0000000000..8c8ef15cd9
--- /dev/null
+++ b/packages/cocoaint/utils/iphone/objp_parser.php
@@ -0,0 +1,560 @@
+<?php
+
+class TObjPParser extends TPasCocoaParser {
+
+ var $objc_id = "id"; // Default type for generic objects
+ var $objc_id_real = "id"; // The real type of generic objects (id)
+ var $sel_string = "SEL";
+ var $trailing_underscore = true;
+ var $print_header_references = false;
+
+ // ignore these classes when testing for ivar size
+ var $ignore_class_ivar_comparison = array( "NSNibOutletConnector", "NSNibConnector", "NSNibControlConnector", "NSPredicateEditorRowTemplate", "NSSegmentedCell",
+ "NSSimpleHorizontalTypesetter", "NSInvocation", "NSPointerFunctions", "NSConstantString");
+
+ var $reserved_keywords = array( "const", "object", "string", "array", "var", "set", "interface", "classname", "unit",
+ "self", "type", "raise", "property", "to", "for", "with", "function", "procedure", "result",
+ "pointer", "create", "new", "dispose", "label", "packed", "record", "char", "class", "implementation",
+
+ // identifiers from NSObject
+ "zone",
+ );
+
+ var $replace_types = array( "void"=>"Pointer", "BOOL"=>"Boolean", "long"=>"clong", "int"=>"cint",
+ "unsigned long"=>"culong", "unsigned short"=>"cushort", "void *"=>"Pointer", "unsigned int"=>"cuint",
+ "Class"=>"Pobjc_class", "uint"=>"cuint",
+ "uint8_t"=>"byte", "signed int"=>"cint", "const char"=>"char", "const void"=>"Pointer",
+ "const uint8_t"=>"byte", "unsigned"=>"cuint", "int32_t"=>"longint", "float"=>"single",
+ "unsigned long long"=>"culonglong", "int64_t"=>"clonglong", "uint32_t"=>"cardinal", "uint16_t"=>"word",
+ "unsigned char"=>"char", "short"=>"cshort", "double"=>"double", "long long"=>"clonglong",
+
+ // ??? new in instance var parser: (add to main section eventually)
+ "signed char"=>"char", "uint64_t"=>"qword",
+
+ // work-arounds - the type replacement needs regex to handle with spaces I guess
+ "void*"=>"Pointer",
+
+ // macros
+ "IBAction"=>"void", "IBOutlet"=>"",
+
+ // special pointers
+ "const id *"=>"NSObjectArrayOfObjectsPtr", "Protocol *"=>"Protocol", "NSObject *"=>"NSObject",
+ "const char *"=>"PChar", "const void *"=>"Pointer", "unsigned char *"=>"Pointer", "char *"=>"PChar",
+ "unsigned *"=>"Pointer", "unichar *"=>"PWideChar", "const unichar *"=>"PWideChar",
+ );
+
+ // These methods require that the last parameter append a trailing underscore (if $trailing_underscore is on)
+ var $trailing_underscore_methods = array("- (void)copy:(id)sender;", "- (void)setNeedsDisplay:(BOOL)flag;");
+
+ // We use direct Cocoa classes now always
+ var $toll_free_bridge = array();
+
+ var $ignore_methods = array("observationInfo");
+
+ // Converts an Objective-c method name to Pascal
+ function ConvertObjcMethodName ($method) {
+ $params = explode(":", $method);
+ $name = "";
+
+ if (count($params) > 1) {
+ foreach ($params as $value) {
+ if (eregi("([a-zA-Z0-9]+)$", $value, $captures)) $name .= $captures[1]."_";
+ }
+ } else {
+ if (eregi("([a-zA-Z0-9]+)(;)*$", $params[0], $captures)) $name .= $captures[1]."_";
+ }
+
+ // clean it up
+ if ($this->trailing_underscore) {
+ if (!in_array($method, $this->trailing_underscore_methods)) $name = trim($name, "_");
+ }
+
+ $name = $this->ReplaceObjcType($name);
+
+ return $name;
+ }
+
+ // We use direct objc classes now so we don't need to replace them with references like in PasCocoa
+ function ReplaceNSTypesWithRef ($string) {
+ return $string;
+ }
+
+ // Converts an Objective-C method to Pascal format
+ function ConvertObjcMethodToPascal ($class, $source, $parts, $protected_keywords, $has_params) {
+
+ // remove deprecated macros from method source
+ $source = eregi_replace("[[:space:]]*DEPRECATED_IN_MAC_OS_X_VERSION_[0-9]+_[0-9]+_AND_LATER", "", $source);
+
+ // replace "hinted" params comment with hinted type
+ if ($this->replace_hinted_params) {
+
+ // param string
+ if (eregi("(/\*[[:space:]]*(.*)[[:space:]]*\*/)", $parts[4], $captures)) {
+ // ??? change the parameter to the hinted type
+ //$parts[4] = eregi_replace("(/\*.*\*/)", $captures[2], $parts[4]);
+ //$parts[4] = trim($parts[4], " ");
+ }
+
+ // return type
+ if (eregi("(/\*[[:space:]]*(.*)[[:space:]]*\*/)", $parts[2], $captures)) $parts[2] = $captures[2];
+
+ //print_r($parts);
+
+ } else { // remmove comments from params and return type
+ $parts[4] = eregi_replace("(/\*.*\*/)", "", $parts[4]);
+ $parts[4] = trim($parts[4], " ");
+
+ $parts[2] = eregi_replace("(/\*.*\*/)", "", $parts[2]);
+ $parts[2] = trim($parts[2], " ");
+ }
+
+ $return_type_clean = $parts[2];
+
+ // perform preformatting before attempting to protect keywords
+ $parts[2] = $this->FormatObjcType($parts[2], $modifiers);
+ $parts[4] = $this->FormatObjcParams($parts[4]);
+
+ // protect keywords in the parameter and return type
+ if (count($protected_keywords) > 0) {
+ foreach ($protected_keywords as $keyword) {
+ $parts[4] = istr_replace_word($keyword, $keyword."_", $parts[4]);
+ $parts[2] = istr_replace_word($keyword, $keyword."_", $parts[2]);
+ }
+ }
+
+ if ($has_params) {
+ $name = $this->ConvertObjcMethodName($source);
+
+ // merge default protected keywords for the class/category
+ if ($this->default_protected["*"]) $protected_keywords = array_merge($this->default_protected["*"], $protected_keywords);
+ if ($this->default_protected[$class]) $protected_keywords = array_merge($this->default_protected[$class], $protected_keywords);
+
+ $param_array = $this->ConvertObjcParamsToPascal($parts[4], $protected_keywords, $variable_arguments);
+ $params = "(".$param_array["string"].")";
+ $params_with_modifiers = "(".$param_array["string_with_modifiers"].")";
+ } else {
+ $params = "";
+ $params_with_modifiers = "";
+ $name = $parts[3];
+ $param_array = null;
+ $variable_arguments = false;
+ }
+
+ // protect method name from keywords
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+
+ // replace objc type
+ $return_type = $this->ConvertReturnType($return_type_clean);
+
+ $virtual = "";
+ $class_prefix = "";
+
+ // determine the type based on return value
+ if (ereg($this->regex_procedure_type, $return_type_clean)) {
+ $kind = "procedure";
+ } else {
+ $kind = "function";
+ }
+
+ // determine if this is a class method
+ if ($parts[1] == "+") {
+ $class_prefix = "class ";
+
+ // These methods probably return the an allocated instance of the class, a typical convenience method.
+ // ??? Ack! $class may be the category or protocol name
+ //if ($return_type == $this->objc_id) $return_type = $class;
+ }
+
+ // Replace SEL with the string equivalent
+ if ($this->register_selectors) {
+ $params_with_modifiers = str_replace_word("SEL", $this->sel_string, $params_with_modifiers);
+ }
+
+ // make method templates
+ if ($kind != "function") {
+ if ($variable_arguments) $modifier .= " varargs;";
+
+ $method = "$class_prefix$kind $name$params_with_modifiers;$modifier$virtual";
+ $method_template = "[KIND] [PREFIX]$name"."[PARAMS];$modifier";
+ } else {
+ if ($variable_arguments) $return_type = "$return_type; varargs";
+
+ $method = $class_prefix."function $name$params_with_modifiers: $return_type;$modifier$virtual";
+ $method_template = "[KIND] [PREFIX]$name"."[PARAMS]: [RETURN];$modifier";
+ $method_template_function = "function [PREFIX]$name"."[PARAMS]: [RETURN];$modifier";
+ }
+
+ $method_template_procedure = "procedure [PREFIX]$name"."[PARAMS];$modifier";
+ $method_template_function = "function [PREFIX]$name"."[PARAMS]: [RETURN];$modifier";
+
+ // ??? DEBUGGING
+ //print("$method\n");
+
+ // build structure
+ $struct["def"] = $method;
+ $struct["template"] = $method_template;
+ $struct["template_function"] = $method_template_function;
+ $struct["template_procedure"] = $method_template_procedure;
+ $struct["objc_method"] = $this->CopyObjcMethodName($source);
+ $struct["class_prefix"] = $class_prefix;
+ //$struct["def_objc"] = eregi("(.*);", $source, $captures[1]);
+ if ($return_type == "void") $return_type = "";
+ $struct["return"] = $return_type;
+
+ if (in_array($return_type, $this->cocoa_classes)) $struct["returns_wrapper"] = true;
+ $struct["param_string_clean"] = trim($params, "()");
+ $struct["param_string_clean_with_modifiers"] = trim($params_with_modifiers, "()");
+ $struct["param_string"] = $params;
+ $struct["param_string_with_modifiers"] = $params_with_modifiers;
+ $struct["param_array"] = $param_array["pairs"];
+ $struct["param_list"] = $param_array["list"];
+ $struct["class"] = $class;
+ $struct["name"] = $name;
+ $struct["kind"] = $kind;
+
+ if ($struct["param_array"] != null) $struct["has_params"] = true;
+
+ // FPC bug work around
+ if (strlen($name) > $this->maximum_method_length) {
+ $struct["can_override"] = false;
+ print(" # WARNING: method $name can't override because the name is too long\n");
+ $this->warning_count ++;
+ }
+
+ return $struct;
+ }
+
+ function InsertPatches ($header) {
+ $path = "$this->root/patches/".$header["name_clean"].".patch";
+ if ($handle = @fopen($path, "r")) {
+ $text = ReadTextFile($path);
+ $this->PrintOutput(0, $text);
+ fclose($handle);
+ }
+ }
+
+ function HeaderContainsPatch ($header) {
+ if ($handle = @fopen("$this->root/patches/".$header["name_clean"].".patch", "r")) {
+ fclose($handle);
+ return true;
+ }
+ }
+
+ // Prints all classes from the header in Objective-P FPC format
+ function PrintHeader ($header) {
+ global $version;
+
+ $this->output = fopen($header["path"], "w+");
+
+ $this->PrintOutput(0, "{ Parsed from ".ucfirst($header["framework"]).".framework ".$header["name"]." }");
+
+ $date = date("D M j G:i:s T Y");
+ $this->PrintOutput(0, "{ Version $version - $date }");
+ $this->PrintOutput(0, "");
+
+ $macro = strtoupper(substr($header["name"], 0, (strripos($header["name"], "."))));
+
+ /*
+ if ($header["classes"]) {
+ $this->PrintOutput(0, "{\$ifdef HEADER}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_H}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_H}");
+ $this->PrintOutput(0, "type");
+
+ foreach ($header["classes"] as $class) {
+
+ // Make a pointer to each class
+ $this->PrintOutput(1, $class["name"]."Pointer = Pointer;");
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+ }
+ */
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef TYPES}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_T}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_T}");
+ $this->PrintTypes($header);
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef RECORDS}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_R}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_R}");
+
+ // Records from types
+ $this->PrintRecords($header);
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef FUNCTIONS}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_F}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_F}");
+ $this->PrintFunctions($header);
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef EXTERNAL_SYMBOLS}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_S}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_S}");
+ $this->PrintExternalSymbols($header);
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+
+ // insert user patches
+ if ($this->HeaderContainsPatch($header)) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef USER_PATCHES}");
+ //$this->PrintOutput(0, "{\$ifndef $macro"."_PAS_PATCH}");
+ //$this->PrintOutput(0, "{\$define $macro"."_PAS_PATCH}");
+ $this->InsertPatches($header);
+ $this->PrintOutput(0, "");
+ //$this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+ }
+
+ if (($header["classes"]) || ($header["protocols"])) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef FORWARD}");
+
+ if ($header["protocols"]) {
+ foreach ($header["protocols"] as $protocol) $this->PrintOutput(1, $protocol["name"]."$this->protocol_suffix = objcprotocol;");
+ }
+
+ if ($header["classes"]) {
+ foreach ($header["classes"] as $class) {
+ $this->PrintOutput(1, $class["name"]." = objcclass;");
+ $this->PrintOutput(1, $class["name"]."Pointer = ^".$class["name"].";");
+ }
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ }
+
+ if ($header["classes"]) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef CLASSES}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_C}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_C}");
+
+ foreach ($header["classes"] as $class) {
+ //if (in_array($class["name"], $this->cocoa_classes))
+ $this->PrintClass($class);
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+ }
+
+
+ if ($header["protocols"]) {
+ $this->PrintOutput(0, "{\$ifdef PROTOCOLS}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_P}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_P}");
+
+
+ foreach ($header["protocols"] as $protocol) {
+ $this->PrintOutput(1, "");
+ $this->PrintOutput(0, "{ ".$protocol["name"]." Protocol }");
+ $this->PrintOutput(1, $protocol["name"]."$this->protocol_suffix = objcprotocol");
+
+ // print methods
+ if ($protocol["methods"]) {
+ foreach ($protocol["methods"] as $name => $method) {
+ $this->PrintOutput(2, $method["def"]." message '".$method["objc_method"]."';");
+ }
+ }
+
+ $this->PrintOutput(1, "end; external name '".$protocol["name"]."';");
+ }
+
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+ }
+ }
+
+ function PrintClass ($class) {
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ ".$class["name"]." }");
+ //print_r($class["methods"]);
+
+ // print super class or protocol which the class conforms to
+ if ($class["conforms"]) {
+ $this->PrintOutput(1, $class["name"]." = objcclass(".$class["super"].", ".$class["conforms"].")");
+ } elseif ($class["super"]) {
+ $this->PrintOutput(1, $class["name"]." = objcclass(".$class["super"].")");
+ }
+
+ // print instance variables
+ if ($class["ivars"]) {
+ $this->PrintOutput(1, "private");
+ foreach ($class["ivars"] as $ivar) {
+ $this->PrintOutput(2, $ivar);
+ }
+ }
+
+ // print alloc method for the class
+ $this->PrintOutput(2, "");
+ $this->PrintOutput(1, "public");
+ $this->PrintOutput(2, "class function alloc: ".$class["name"]."; message 'alloc';");
+
+ // print class-level methods
+ if ($class["methods"]) {
+ $this->PrintOutput(0, "");
+ foreach ($class["methods"] as $method) {
+ $this->PrintOutput(2, $method["def"]." message '".$method["objc_method"]."';");
+ }
+ }
+
+ // print category-level methods
+ if (count($class["categories"]) > 0) {
+ foreach ($class["categories"] as $name => $category) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(2, "{ Category: $name }");
+
+ if ($category["methods"]) {
+ foreach ($category["methods"] as $method) {
+ $this->PrintOutput(2, $method["def"]." message '".$method["objc_method"]."';");
+ }
+ }
+ }
+ }
+
+ $this->PrintOutput(1, "end; external;");
+ }
+
+ function PrintDelegateReference ($valid_categories) {
+ global $version;
+
+ $date = date("D M j G:i:s T Y");
+ $this->PrintOutput(0, "{ Version $version - $date }");
+ $this->PrintOutput(0, "");
+
+ ksort($this->delegate_methods);
+
+ $this->PrintOutput(0, "unit $this->master_delegate_file;");
+ $this->PrintOutput(0, "interface");
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Copy and paste these delegate methods into your real classes. }");
+
+
+ // implemented methods
+ foreach ($this->delegate_methods as $category => $selectors) {
+ if (in_array($category, $this->ignore_categories)) continue;
+
+ // make sure the category is valid
+ $valid = false;
+ foreach ($valid_categories as $pattern) {
+ if (eregi($pattern, $category)) {
+ $valid = true;
+ break;
+ }
+ }
+ if (!$valid) continue;
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "type");
+ $this->PrintOutput(1, "$category = objccategory (NSObject)");
+ //$this->PrintOutput(1, "public");
+
+ foreach ($selectors as $selector) {
+
+ // FPC long name bug work-around
+ if (strlen($selector["name_pascal"]) > $this->maximum_method_length) continue;
+
+ if ($selector["kind"] == "procedure") {
+ $this->PrintOutput(2, $selector["kind"]." ".$selector["name_pascal"].$selector["param_string"].";"." message '".$selector["name"]."';");
+ } else {
+ $this->PrintOutput(2, $selector["kind"]." ".$selector["name_pascal"].$selector["param_string"].": ".$selector["method"]["return"].";"." message '".$selector["name"]."';");
+ }
+ }
+
+ $this->PrintOutput(1, "end;");
+ }
+
+ }
+
+ function PrintIvarSizeComparison ($path) {
+ $count = 0;
+ $block = true;
+ $block_count = 1;
+ $limit = 2000;
+
+ $handle = fopen($path, "w+");
+ if (!$handle) die("Bad path to size comparison output program!");
+
+ fwrite($handle, "{\$mode objfpc}\n");
+ fwrite($handle, "{\$modeswitch objectivec1}\n");
+
+ fwrite($handle, "program IvarSize;\n");
+ fwrite($handle, "uses\n");
+ fwrite($handle, " objp,objcrtl,objcrtlmacosx;\n");
+
+ // print derived classes
+ foreach ($this->cocoa_classes as $class) {
+ if (in_array($class, $this->ignore_class_ivar_comparison)) continue;
+ if ($previous == $class) continue;
+
+ fwrite($handle, "type\n");
+ fwrite($handle, " TDerived$class = objcclass ($class)\n");
+ fwrite($handle, " extrabyte: byte;\n");
+ fwrite($handle, "end;\n");
+
+ $previous = $class;
+ }
+
+ // print procedures
+ foreach ($this->cocoa_classes as $class) {
+ if (in_array($class, $this->ignore_class_ivar_comparison)) continue;
+ if ($previous == $class) continue;
+
+ if ($count == 0) {
+ fwrite($handle, "\n");
+ fwrite($handle, "procedure PrintGlue$block_count;\n");
+ fwrite($handle, "begin\n");
+
+ $block_count ++;
+ }
+
+ $count ++;
+
+ fwrite($handle, " if class_getInstanceSize(TDerived$class) <> (class_getInstanceSize($class)+1) then\n");
+ fwrite($handle, " writeln('size of $class is wrong: ',class_getInstanceSize(TDerived$class),' <> ',class_getInstanceSize($class)+1);\n");
+
+ if ($count == $limit) {
+ fwrite($handle, "end;\n");
+ $count = 0;
+ }
+
+ $previous = $class;
+ }
+
+ if ($count < $limit) {
+ fwrite($handle, "end;\n");
+ $block_count --;
+ }
+
+ fwrite($handle, "begin\n");
+ for ($i=1; $i < $block_count + 1; $i++) {
+ fwrite($handle, " PrintGlue$i;\n");
+ }
+ fwrite($handle, "end.\n");
+ }
+
+}
+?>
diff --git a/packages/cocoaint/utils/iphone/parser.php b/packages/cocoaint/utils/iphone/parser.php
new file mode 100755
index 0000000000..b7418bbbd6
--- /dev/null
+++ b/packages/cocoaint/utils/iphone/parser.php
@@ -0,0 +1,283 @@
+<?php
+
+$version = "FrameworkParser: 1.3. PasCocoa 0.3, Objective-P 0.4";
+
+require("pascocoa_parser.php");
+require("objp_parser.php");
+
+/**
+ * Cocoa framework parser for PasCocoa
+ *
+ * @author Ryan Joseph
+ **/
+
+// These files have duplicates in AppKit and Foundation so we ignore the foundation versions and everything is merged into AppKit
+$duplicate_headers = array("foundation/NSAttributedString.inc", "foundation/NSAffineTransform.inc");
+
+// Print only these files
+$only_files = null;
+
+$options = array();
+
+function HandleCommandLineOptions ($argv) {
+ global $options;
+ global $root_path;
+ global $ignore_headers;
+ global $only_files;
+
+ // defaults
+ $options["framework_path"] = "/System/Library/Frameworks";
+
+ foreach ($argv as $option) {
+ $pair = explode("=", $option);
+ $key = trim($pair[0], "-");
+ $value = $pair[1];
+
+ switch ($key) {
+
+ case 'root':
+ $root_path = trim($value, "\"");
+ break;
+
+ case 'header':
+ $where = explode("/", trim($value, "\""));
+ $options[$key]["framework"] = ucfirst($where[0]);
+ $options[$key]["name"] = $where[1];
+ break;
+
+ case 'framework_path':
+ $options["framework_path"] = trim($value, "\"");
+ break;
+
+ case 'all':
+ $options[$key] = true;
+ break;
+
+ case 'objp':
+ $options[$key] = true;
+ break;
+
+ case 'encodings':
+ $options[$key] = true;
+ break;
+
+ case 'delegates':
+ $options[$key] = true;
+ break;
+
+ case 'noprint':
+ $options[$key] = true;
+ break;
+
+ case 'show':
+ $options[$key] = true;
+ break;
+
+ case 'reference':
+ $options[$key] = true;
+ break;
+
+ case 'iphone':
+ $options[$key] = true;
+ break;
+
+ case 'cocoa':
+ $options[$key] = true;
+ break;
+
+ case 'webkit':
+ $options[$key] = true;
+ break;
+
+ case 'ignore':
+ $ignore_headers = explode(",", trim($value, "\""));
+ break;
+
+ case 'only':
+ $only_files = explode(",", trim($value, "\""));
+ break;
+
+ case 'frameworks':
+ $options[$key] = explode(",", trim($value, "\""));
+ break;
+
+ default:
+ //print("unknown switch $key\n");
+ break;
+ }
+ }
+}
+
+// ??? TESTING
+$testing = false;
+
+if ($testing) {
+ $GLOBALS["argv"][] = "-webkit";
+ $GLOBALS["argv"][] = "-root=/Developer/ObjectivePascal";
+ $GLOBALS["argv"][] = "-delegates";
+ //$GLOBALS["argv"][] = "-reference";
+ //$GLOBALS["argv"][] = "-all";
+ $GLOBALS["argv"][] = "-noprint";
+ //$GLOBALS["argv"][] = "-show";
+ //$GLOBALS["argv"][] = "-only=\"UIWindow.h\"";
+ //$GLOBALS["argv"][] = "-frameworks=\"appkit,foundation\"";
+
+ //$GLOBALS["argv"][] = "-framework_path=\"/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/System/Library/Frameworks\"";
+ //$GLOBALS["argv"][] = "-header=\"uikit/UIView.h\"";
+
+ //$GLOBALS["argv"][] = "-framework_path=\"/System/Library/Frameworks\"";
+ //$GLOBALS["argv"][] = "-header=\"webkit/DOMDocument.h\"";
+
+ //$GLOBALS["argv"][] = "-framework_path=\"/System/Library/Frameworks\"";
+ //$GLOBALS["argv"][] = "-header=\"foundation/NSBundle.h\"";
+ //$GLOBALS["argv"][] = "-header=\"appkit/NSBundle.h\"";
+
+ $GLOBALS["argv"][] = "-ignore=\"NSGeometry.h,NSRange.h\"";
+ $GLOBALS["argv"][] = "-objp";
+
+ // Objective-P
+ /* Notes for master compile (-all):
+
+ • CocoaAll.pas:
+
+ Compiling /Developer/ObjectivePascal/CocoaAll.pas
+ 1) NSWorkspace.inc(35,46) Error: Duplicate identifier "NSWorkspaceLaunchAllowingClassicStartup"
+ 2) NSClassDescription.inc(60,55) Error: Duplicate identifier "description"
+ 3) NSScriptObjectSpecifiers.inc(194,44) Error: Duplicate identifier "classDescription"
+ 4) NSScriptSuiteRegistry.inc(75,40) Error: Duplicate identifier "classDescription"
+ 5) NSControl.inc(136,15) Error: Mismatch between number of declared parameters and number of colons in message string.
+ 6) NSWorkspace.inc(135,189) Error: Duplicate identifier "description"
+ 7) NSMenuItemCell.inc(64,9) Error: Duplicate identifier "reserved"
+ 8) NSRuleEditor.inc(127,15) Error: Mismatch between number of declared parameters and number of colons in message string.
+ 9) NSObjCRuntime.inc(79,24) Fatal: Syntax error, "identifier" expected but ":" found
+ Fatal: Compilation aborted
+
+ 1) NSWorkspace.h has a duplicate NSWorkspaceLaunchAllowingClassicStartup constant
+ 2) NSObjcRuntime.h contains a bad external function:
+ function __attribute__(: (format(__NSString__; : 1; : 2))): void NSLog(NSStringRef *format, ...); cdecl; external name '__attribute__';
+ procedure NSLog(fmt:NSString); cdecl; varargs; external;
+ 3) NSMenuItemCell.h has a duplicate (case sensitive name not allowed in Pascal) field that must be changed by hand.
+ 4) These methods have problems in the params. This is a Objc convention where an absent type is always "id"
+ - (void)performClick:sender;
+ - (void)setDelegate:delegate;
+ NSControl.inc(136,15) Error: Mismatch between number of declared parameters and number of colons in message string.
+ NSRuleEditor.inc(124,15) Error: Mismatch between number of declared parameters and number of colons in message string.
+ 5) NSInteger types are wrong in NSObjcRuntime (should be long)
+ NSInteger = clong;
+ NSUInteger = culong;
+ NSNotFound = high(NSInteger);
+ 6) Many description and classDescription identifiers are not protected in name space and cause errors
+
+ • iPhoneAll.pas
+ 1) UIAccelerometer: FPC bug causes methods with a single character message to fail. Remove the 3 methods affected
+ UIAccelerometer.inc(67,49) Error: Illegal expression after message directive
+ 2) There's no way to know that UITextInputTraits is actually UITextInputTraitsProtocol due to name changes for Pascal syntax
+ UITextField.inc(91,32) Error: Identifier not found "UITextInputTraits"
+
+ • WebKit.pas
+ 1) Extra duplicate type in DOMObject.inc
+ DOMObjectInternal = Pointer;
+ DOMObjectInternal = DOMObjectInternal;
+
+ 2) DOMDocument has method with reserved keyword name "implementation"
+ function implementation: DOMImplementation; message 'implementation';
+
+ 3) DOMEvent has method with reserved keyword name "type"
+ function type: NSString; message 'type';
+
+ * reserved keywords are not protected in method names. This is messing up WebKit parsing badly
+
+ - General notes:
+ 1) NSObject.h is parsed for the merged category methods that should be inserted manually into the real root class
+ 2) NSRange.h was ignored because it contains custom code and can be maintained by hand very easily
+ 3) NSGeometry.h was ignored because it contains many parsing errors and custom code, do this by hand for now.
+ 4) All instance variables are placed into "private" for now. There are a very small number of classes that have public ivar's.
+ */
+
+ //$GLOBALS["argv"][] = "-show";
+}
+
+if (count($GLOBALS["argv"]) == 1) {
+ print("Cocoa Framework Parser ($version) usage:\n");
+ print("php parser.php [switches]\n\n");
+ print("switches:\n\n");
+ print(" -all print all headers (.h) from AppKit/Foundation frameworks\n");
+ print(" -header=\"foundation/NSObject.h\" prints a single header from system frameworks\n");
+ print(" -root sets the root path of the pascocoa directory\n");
+ print(" -framework_path sets the root path of the frameworks directory (defaults to /System/Library/Frameworks)\n");
+ print(" -show prints output to screen instead of file\n");
+ print(" -ignore=\"NSObject.h,NSArray.h\" ignores the list of headers during parsing (-all only, no spaces)\n");
+ print(" -only=\"NSObject.h,NSArray.h\" only prints these files (-all only, no spaces)\n");
+ print(" -noprint parses but does not print (-all only)\n");
+ print(" -encodings prints Pascal type encoding glue for GenerateTypeEncodings.p (-all only)\n");
+ print(" -delegates prints NSDelegateController.inc to foundation (-all only)\n");
+ print(" -objp prints classes in FPC Objective-P dialect\n");
+ print(" -iphone one-time parse for iPhone headers\n");
+ print(" -cocoa one-time parse for Cocoa (AppKit/Foundation) headers\n");
+ print(" -frameworks=\"appkit,foundation\" list of supported frameworks to parse\n");
+ print("\n\n");
+}
+
+// get the command line options
+if (count($GLOBALS["argv"]) > 1) {
+ HandleCommandLineOptions($GLOBALS["argv"]);
+ //print_r($options);
+}
+
+// Make the output directory
+if ($options["out"]) {
+ @mkdir($root_path, 0777);
+ @mkdir($root_path."/foundation", 0777);
+ @mkdir($root_path."/appkit", 0777);
+// @mkdir($root_path."/webkit", 0777);
+ @mkdir($root_path."/uikit", 0777);
+// @mkdir($root_path."/reference", 0777);
+}
+
+// setup -iphone options
+if ($options["iphone"]) {
+ $options["all"] = true;
+ $options["objp"] = true;
+ $options["frameworks"] = array("uikit");
+}
+
+// setup -cocoa options
+if ($options["cocoa"]) {
+ $options["all"] = true;
+ $options["objp"] = true;
+ $options["frameworks"] = array("appkit","foundation");
+ $ignore_headers = array("NSGeometry.h","NSRange.h");
+}
+
+if ($options["webkit"]) {
+ $options["all"] = true;
+ $options["objp"] = true;
+ $options["frameworks"] = array("webkit");
+}
+
+// create the parser instance
+if ($options["objp"]) {
+ $parser = new TObjPParser ($root_path, "", $options["frameworks"], $options["show"]);
+} else {
+ $parser = new TPasCocoaParser ($root_path, "", $options["frameworks"], $options["show"]);
+}
+
+// Process single headers
+if ($options["header"] && !$options["all"]) {
+ $path = $options["framework_path"]."/".$options["header"]["framework"].".framework/Headers/".$options["header"]["name"];
+ print("* Processing $path...\n");
+ $parser->ProcessFile($path, true);
+}
+
+//$parser->PrintIvarSizeComparison("/Users/ryanjoseph/Desktop/objp/IvarSize.p");
+//exit;
+
+// Process all headers
+if ($options["all"]) {
+ $parser->ParseCocoaFrameworks($ignore_headers, null);
+ if (!$options["noprint"]) $parser->PrintAllHeaders("", $duplicate_headers, $only_files, $options["reference"]);
+ if ($options["delegates"]) $parser->ParseDelegateClasses();
+ if ($options["encodings"]) $parser->PrintTypeEncodingGlue();
+}
+
+?> \ No newline at end of file
diff --git a/packages/cocoaint/utils/iphone/pascocoa_parser.php b/packages/cocoaint/utils/iphone/pascocoa_parser.php
new file mode 100644
index 0000000000..cb1b9bd87d
--- /dev/null
+++ b/packages/cocoaint/utils/iphone/pascocoa_parser.php
@@ -0,0 +1,4163 @@
+<?php
+function ReadTextFile ($path) {
+ if ($handle = fopen($path, "r")) {
+ return fread($handle, 400 * 1024);
+ fclose($handle);
+ }
+}
+
+function str_replace_word ($needle, $replacement, $haystack) {
+ $pattern = "/\b$needle\b/";
+ $haystack = preg_replace($pattern, $replacement, $haystack);
+ return $haystack;
+}
+
+function istr_replace_word ($needle, $replacement, $haystack) {
+ $pattern = "/\b$needle\b/i";
+ $haystack = preg_replace($pattern, $replacement, $haystack);
+ return $haystack;
+}
+
+define("CAST_HANDLE", true);
+define("DONT_CAST_HANDLE", false);
+
+define("ACCESS_HANDLE_DIRECT", 1);
+define("ACCESS_HANDLE_FUNCTION", 2);
+
+define("REGISTER_SEL", true);
+define("DONT_REGISTER_SEL", false);
+
+define("USE_HANDLE", true);
+define("DONT_USE_HANDLE", false);
+
+class TPasCocoaParser {
+
+ // Frameworks to parse
+ var $frameworks = array( "foundation" => array( "root" => "/foundation/Foundation.inc",
+ "bridge" => "/bridgesupport/foundation.xml",
+ "headers" => "/System/Library/Frameworks/Foundation.framework/Headers",
+ "include_pattern" => "{[$]+include (NS.*).inc}",
+ "header_pattern" => "^NS(.*)\.h",
+ "enabled" => false,
+ ),
+
+ "appkit" => array( "root" => "/appkit/AppKit.inc",
+ "bridge" => "/bridgesupport/appkit.xml",
+ "headers" => "/System/Library/Frameworks/AppKit.framework/Headers",
+ "include_pattern" => "{[$]+include (NS.*).inc}",
+ "header_pattern" => "^NS(.*)\.h",
+ "enabled" => false,
+ ),
+
+ "uikit" => array( "root" => "/uikit/UIKit.inc",
+ "bridge" => "/bridgesupport/appkit.xml",
+ //"headers" => "/Users/ryanjoseph/Desktop/iphone/UIKit.framework/Headers",
+ "headers" => "/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/System/Library/Frameworks/UIKit.framework/Headers",
+ "include_pattern" => "{[$]+include (UI.*).inc}",
+ "header_pattern" => "^UI(.*)\.h",
+ "enabled" => false,
+ ),
+
+ "webkit" => array( "root" => "/webkit/WebKit.inc",
+ "bridge" => "/bridgesupport/webkit.xml",
+ "headers" => "/System/Library/Frameworks/WebKit.framework/Headers",
+ "include_pattern" => "{[$]+include (.*).inc}",
+ "header_pattern" => "^(.*)\.h",
+ "enabled" => false,
+ ),
+
+ "coredata" => array( "root" => "/coredata/CoreData.inc",
+ "bridge" => "/bridgesupport/coredata.xml",
+ "headers" => "/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/CoreData.framework/Headers",
+ "include_pattern" => "{[$]+include (.*).inc}",
+ "header_pattern" => "^(.*)\.h",
+ "enabled" => false,
+ ),
+ );
+
+ var $maximum_method_length = 111; // WE GET THIS ERROR: NSDelegatesAll.pas(6109,296) Error: Identifier not found "NSDelegateController_NSLayoutManagerDelegate_layoutManager_shouldUseTemporaryAttributes_forDrawingToScreen_atCharacterIndex_effectiveRange"
+
+ var $output; // current output file handle
+ var $root; // root for printing/locating resources
+ var $out; // directory to print
+ var $show; // print output to screen instead of file
+ var $framework; // current framework being parsed
+ var $current_class; // reference to current class structure being parsed
+ var $current_header; // reference to current header structure being parsed
+ var $method_count; // count of all methods parsed
+ var $class_count; // count of all classes parsed
+ var $warning_count; // count of parser warnings
+ var $parser_skipping; // the parser is skipping lines in the current file
+ var $inside_macro_block; // the parser is inside a macro block, no nesting!
+ var $instance_var_scope; // current scope of the instance variable parser
+ var $cocoa_classes = array(); // array of all NS*** classes
+ var $cocoa_categories = array(); // array of all NS*** categories
+ var $dump = array(); // Convert Pascal classes
+ var $delegate_methods = array(); // Delegate methods and types from GEN_BRIDGE_METADATA XML data
+ var $delegate_method_names = array(); // Delegate method name array
+ var $type_encodings = array(); // Master listing of type encodings for each method in the frameworks
+
+ /**
+ * PARSER OPTIONS
+ */
+ var $objc_id = "NSObjectRef"; // Default type for generic objects
+ var $objc_id_real = "NSObjectRef"; // The real type of generic objects (id)
+ var $objc_id_base = "Pointer"; // The base type for all "Ref" types
+ var $sel_string = "SELString"; // The selector string type which registers selectors internally
+ var $protocol_suffix = "Protocol"; // All protocols append this suffix
+ var $pointer_type_suffx = "Ref"; // NS*** pointers in parameter lists are suffixed with this
+ var $class_pointer_suffix = "Pointer"; // Pointers to NS*** classes are suffxed with this
+ var $register_selectors = true; // Register selectors automatically inside the wrappers
+ var $show_added_messages = false; // show messages when methods are added to a class
+ var $show_class_hierarchy = false;
+ var $objects_are_wrappers = false; // Treat all objects (id) like wrappers. i.e aObject.Handle;
+ var $replace_hinted_params = false; // replace comment hints with hinted type - (void * /* CMProfileRef */)colorSyncProfile;
+ var $master_delegate_class = "NSDelegateController"; // Name of the master delegate class
+ var $master_delegate_file = "NSDelegatesAll"; // Name of the master delegate file (no extension)
+ var $trailing_underscore = false; // Append the trailing underscore for last parameter
+ var $record_keyword = "record"; // The keyword used for printing records
+ var $bitpacked_record_keyword = "bitpacked record"; // The keyword used for printing bitpacked records
+ var $string_macro = "NSString";
+
+ // Pascal keywords to protect
+ var $reserved_keywords = array( "const", "object", "string", "array", "var", "set", "interface", "classname", "unit",
+ "self", "type", "raise", "property", "to", "for", "with", "function", "procedure", "result",
+ "pointer", "create", "new", "dispose", "label", "packed", "record", "char", "class",
+ );
+
+ // FPC methods that can't be overloaded
+ var $reserved_methods = array("className");
+
+ // Types which can not be altered by reserved keywords
+ var $reserved_types = array("Pointer");
+
+ // Objective-c types to convert
+ var $replace_types = array( "id"=>"NSObjectRef", "void"=>"Pointer", "BOOL"=>"LongBool", "long"=>"LongInt", "int"=>"Integer",
+ "unsigned long"=>"UInt32", "unsigned short"=>"UInt8", "void *"=>"Pointer", "unsigned int"=>"UInt16",
+ "NSUInteger"=>"UInt32", "NSInteger"=>"SInt32", "Class"=>"Pobjc_class", "uint"=>"UInt16",
+ "uint8_t"=>"UInt8", "signed int"=>"Integer", "const char"=>"PChar", "const void"=>"Pointer",
+ "const uint8_t"=>"Pointer", "unsigned"=>"UInt8", "int32_t"=>"SInt32", "float"=>"Float32",
+ "unsigned long long"=>"UInt64", "int64_t"=>"SInt64", "uint32_t"=>"UInt32", "uint16_t"=>"UInt16",
+ "unsigned char"=>"char", "short"=>"SInt8", "double"=>"Float64", "long long"=>"SInt64",
+
+ // macros
+ "IBAction"=>"void",
+
+ // special pointers
+ "const id *"=>"NSObjectArrayOfObjectsPtr", "Protocol *"=>"ObjcProtocol", "NSObject *"=>"NSObjectRef",
+ "const char *"=>"PChar", "const void *"=>"Pointer", "unsigned char *"=>"Pointer", "char *"=>"Pointer",
+ "unsigned *"=>"Pointer",
+ );
+
+ // These "types" are hints to the Objective-C garbage collector
+ var $garbage_collector_hints = array("__strong", "__weak");
+
+ var $null_macros = array("IBOutlet", "IBAction");
+
+ // External NSString macros. These should be moved into the frameworks array
+ var $external_string_macros = "APPKIT_EXTERN|FOUNDATION_EXPORT|UIKIT_EXTERN|COREDATA_EXTERN";
+
+ // Types which have known pointers declared in the headers
+ var $pointer_types = array( // MacOSAll types
+ "CGFloat"=>"psingle", "UInt32"=>"UInt32Ptr", "SInt32"=>"SInt32Ptr",
+
+ // Cocoa types
+ "BOOL"=>"pboolean",
+
+ "unsigned char"=>"pchar",
+ "unsigned short"=>"pcushort", "unsigned int"=>"pcuint", "uint"=>"pcuint", "signed int"=>"pcint",
+ "float"=>"psingle", "double"=>"pdouble", "long long"=>"pclonglong","long"=>"pclong", "unsigned long"=>"pculong",
+ "int"=>"pinteger","uint8_t"=>"pbyte","unsigned"=>"pbyte","unsigned long long"=>"pculonglong"
+ );
+
+ var $objc_object_array = "id; objParams: array of const"; // Type which represents a dynamic array of Objective-c objects (id)
+
+ // Symbols to ignore
+ var $ignore_symbol = array("NSApp");
+
+ // Categories to ignore
+ var $ignore_categories = array("NSCoderMethods", "NSDeprecatedKeyValueCoding", "NSDeprecated");
+
+ // Methods to ignore
+ var $ignore_methods = array( "retain", "release", "retainCount", "copyWithZone", "mutableCopyWithZone",
+ "allocWithZone", "alloc", "copy", "mutableCopy", "self_", "autorelease", "awakeFromNib",
+ "observationInfo",
+ );
+
+ // default protected keywords by class/category
+ // these may be useful if super classes were not parsed before
+ var $default_protected = array( "*"=>array("description", "classDescription"),
+ "NSDeprecated"=>array("accessoryView"),
+ "NSToolbarSupport"=>array("toolbar"),
+ "DOMNode"=>array("version"),
+ "WebView"=>array("frame"),
+ "DOMImplementation"=>array("version"),
+ );
+
+ // Send methods that have a custom design
+ var $custom_send_methods = array( "NSArray.arrayWithObjects", "NSArray.initWithObjects",
+ "NSDictionary.dictionaryWithObjectsAndKeys", "NSDictionary.initWithObjectsAndKeys",
+ "NSSet.setWithObjects", "NSSet.initWithObjects",
+ );
+
+ var $toll_free_bridge = array(
+ "NSString"=>"CFStringRef", "NSArray"=>"CFArrayRef", "NSMutableString"=>"CFMutableStringRef",
+ "NSData"=>"CFDataRef", "NSDictionary"=>"CFDictionaryRef", "NSSet"=>"CFSetRef",
+ "NSMutableArray"=>"CFMutableArrayRef", "NSMutableCharacterSetRef"=>"CFMutableCharacterSetRef",
+ "NSMutableData"=>"CFMutableDataRef", "NSMutableDictionary"=>"CFMutableDictionaryRef",
+ "NSMutableSet"=>"CFMutableSetRef", "NSNumber"=>"CFNumberRef", "NSURL"=>"CFURLRef",
+ "NSError"=>"CFErrorRef",
+
+ /* The Cocoa versions of these API's are much better and not very common, should we replace them?
+ "NSOutputStream"=>"CFWriteStreamRef", "NSPasteboard"=>"PasteboardRef"
+ "NSInputStream"=>"CFReadStreamRef", "NSTimer"=>"CFRunLoopTimerRef",
+ "NSTimeZone"=>"CFTimeZoneRef", "NSCharacterSet"=>"CFCharacterSetRef",
+ "NSDate"=>"CFDateRef",
+ */
+ );
+
+ // types that use objc_msgSend_stret on all architectures
+ var $struct_types = array( "NSRect", "NSDecimal", "NSFastEnumerationState", "NSMapTableValueCallBacks",
+ "NSHashTableCallBacks", "NSMapTableKeyCallBacks",
+
+ // TEMPORARY PARSER HACKS
+ "aeDesc_",
+ );
+
+ // structs that use objc_msgSend or objc_msgSend_stret depending on architecture
+ // "On Mac OS X Intel/i386, records whose size is 1, 2, 4 or 8 bytes are returned using registers"
+ var $struct_register_types = array( "NSRange", "NSPoint", "NSSize", "NSAffineTransformStruct" );
+
+ // Functions that return types will invoke objc_msgSend_fpret
+ // NOTE: we must also know the exact type so we can make the proper function pointer
+ var $float_types = array( // C-types
+ "float", "long double", "double",
+
+ // Cocoa types
+ "NSTimeInterval",
+
+ // Pascal types
+ "Float64", "Float32",
+
+ // CarbonTypes
+ "CGFloat",
+ );
+
+ var $skip_blocks = array( "^#if __LP64__ \|\| NS_BUILD_32_LIKE_64"=>"^#(else|endif)+",
+ );
+
+ var $macro_blocks = array( "^#if (__LP64__)"=>"\$ifdef cpu64",
+ "^#if ![[:space:]]*(__LP64__)"=>"\$ifndef cpu64",
+ "^#ifdef __BIG_ENDIAN__"=>"\$ifdef fpc_big_endian",
+ //"^#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_[0-9]+_[0-9]+"=>"*",
+ );
+
+ // these categories should be placed into NSObject
+ var $base_categories = array( "NSArchiverCallback", "NSClassDescriptionPrimitives", "NSCoderMethods", "NSComparisonMethods",
+ "NSDelayedPerforming", "NSDeprecatedKeyValueCoding", "NSDeprecatedKeyValueObservingCustomization",
+ "NSDistributedObjects", "NSErrorRecoveryAttempting", "NSKeyValueCoding", "NSPlaceholders",
+ "NSKeyValueObserverRegistration", "NSKeyValueObserving", "NSKeyValueObservingCustomization",
+ "NSKeyedArchiverObjectSubstitution", "NSKeyedUnarchiverObjectSubstitution", "NSDeprecatedMethods",
+ "NSScriptKeyValueCoding", "NSThreadPerformAdditions", "NSServicesRequests", "NSKeyValueBindingCreation",
+ "NSAccessibility", "NSAccessibilityAdditions",
+ );
+
+ // These really don't feel like they should be in NSObject, removing until we know where to put them.
+ // Maybe a new class? NSCategories...
+
+ // "NSURLClient", "NSScripting", "NSScriptClassDescription", "NSScriptObjectSpecifiers",
+ // "NSScriptingComparisonMethods", "NSFontManagerResponderMethod", "NSMenuValidation",
+ // "NSColorPanelResponderMethod", "NSFontPanelValidationAdditions", "NSToolbarItemValidation",
+ // "NSDictionaryControllerKeyValuePair", "NSEditor",
+ /**
+ * COMMON REGULAR EXPRESIONS
+ */
+ var $regex_objc_method_params = "^(-|\+)[[:space:]]*\((.*)\)[[:space:]]*([a-zA-Z0-9]+):(.*);";
+ var $regex_objc_method_no_params = "^(-|\+)[[:space:]]*\((.*)\)[[:space:]]*([a-zA-Z0-9]+);";
+ var $regex_objc_category = "^@interface ([a-zA-Z]+)[[:space:]]*\(([a-zA-Z]+)\)";
+ var $regex_objc_class = "^@interface ([a-zA-Z]+)[[:space:]]*:[[:space:]]*([a-zA-Z]+)[[:space:]]*(<(.*)>)*";
+ var $regex_objc_class_no_super = "^@interface ([a-zA-Z]+)[[:space:]]*<(.*)>[[:space:]]*";
+ var $regex_objc_protocol = "^@protocol ([a-zA-Z]+)";
+ var $regex_procedure_type = "^[[:space:]]*(void|IBAction)+[[:space:]]*$";
+ var $regex_scope_compiler_directive = "^\s*@(private|protected|public)(;*)+\s*$";
+ var $regex_objc_property = "^@property\((.*)\)[[:space:]]*(.*);";
+
+ /**
+ * TEMPLATES
+ */
+
+ // Template for implemented function
+ var $template_implemented_function = "function [CLASS].implemented_[NAME][PARAMS_HEADER]: [RETURN];
+begin
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ Result := [RETURN](super_[NAME][PARAMS_BODY_WRAPPER]);
+ {\$else}
+ Result := [RETURN](super_[NAME][PARAMS_BODY]);
+ {\$endif}
+end;";
+
+ // Template for implemented procedure
+ var $template_implemented_procedure = "procedure [CLASS].implemented_[NAME][PARAMS_HEADER];
+begin
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ super_[NAME][PARAMS_BODY_WRAPPER];
+ {\$else}
+ super_[NAME][PARAMS_BODY];
+ {\$endif}
+end;";
+
+ // Template for constructor
+ var $template_constructor = "constructor [CLASS][NAME][PARAMS_HEADER];
+type
+ TmsgSendWrapper = function (param1: id; param2: SEL[PARAMS_PROC]): id; cdecl;
+var
+ vmethod: TmsgSendWrapper;
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+
+ RegisterSubClass;
+ allocbuf := objc_msgSend(ClassID, SEL_alloc, []);
+ vmethod := TmsgSendWrapper(@objc_msgSend);
+ Handle := vmethod(allocbuf, SEL_[SELNAME][PARAMS_LIST_WRAPPER]);
+ retainCount := 1;
+ AssignSelf(Handle);
+ AddMethods;
+ BindMethods;
+end;";
+
+ // Template for constructor that does not allocate memory
+ var $template_constructor_no_alloc = "constructor [CLASS][NAME][PARAMS_HEADER];
+type
+ TmsgSendWrapper = function (param1: id; param2: SEL[PARAMS_PROC]): id; cdecl;
+var
+ vmethod: TmsgSendWrapper;
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+
+ RegisterSubClass;
+ vmethod := TmsgSendWrapper(@objc_msgSend);
+ Handle := vmethod(ClassID, SEL_[SELNAME][PARAMS_LIST_WRAPPER]);
+ AutoReleaseObject;
+ AssignSelf(Handle);
+ AddMethods;
+ BindMethods;
+end;";
+
+ // Template for function to send Objective-c message that returns an auto-generated/memory managed wrapper object.
+ var $template_function_make_wrapper = "function [CLASS][NAME][PARAMS_HEADER]: [RETURN];
+type
+ TmsgSendWrapper = function (param1: id; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
+var
+ vmethod: TmsgSendWrapper;
+ wrapper: [RETURN];
+begin
+ vmethod := TmsgSendWrapper(@[MSG_SEND]);
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]));
+ {\$else}
+ Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]));
+ {\$endif}
+
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ wrapper := [RETURN](GetWrapper(Result));
+ if wrapper = nil then
+ Result := [RETURN]([RETURN].CreateWithHandle(Pobjc_object(Result)).deferObject)
+ else
+ Result := wrapper;
+ {\$endif}
+end;";
+
+ var $template_function_make_wrapper_no_params = "function [CLASS][NAME]: [RETURN];
+var
+ wrapper: [RETURN];
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+
+ Result := [RETURN]([MSG_SEND]([OBJC_OBJECT], SEL_[SELNAME], []));
+
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ wrapper := [RETURN](GetWrapper(Result));
+ if wrapper = nil then
+ Result := [RETURN]([RETURN].CreateWithHandle(Pobjc_object(Result)).deferObject)
+ else
+ Result := wrapper;
+ {\$endif}
+end;";
+
+ // Template for protocol function to send Objective-c message that returns an auto-generated/memory managed wrapper object.
+ var $template_protocol_make_wrapper = "function [CLASS][NAME][PARAMS_HEADER]: [RETURN];
+type
+ TmsgSendWrapper = function (param1: id; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
+var
+ vmethod: TmsgSendWrapper;
+begin
+ vmethod := TmsgSendWrapper(@[MSG_SEND]);
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]));
+ {\$else}
+ Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]));
+ {\$endif}
+
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ Result := [RETURN]([RETURN].CreateWithHandle(Pobjc_object(Result)).deferObject);
+ {\$endif}
+end;";
+
+ var $template_protocol_make_wrapper_no_params = "function [CLASS][NAME]: [RETURN];
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+ Result := [RETURN]([MSG_SEND]([OBJC_OBJECT], SEL_[SELNAME], []));
+
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ Result := [RETURN]([RETURN].CreateWithHandle(Pobjc_object(Result)).deferObject);
+ {\$endif}
+end;";
+
+ // Template for function to send Objective-c message
+ var $template_function_objc_send = "function [CLASS][NAME][PARAMS_HEADER]: [RETURN];
+type
+ TmsgSendWrapper = function (param1: [TARGET_TYPE]; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
+var
+ vmethod: TmsgSendWrapper;
+ super: objc_super;
+begin
+ vmethod := TmsgSendWrapper(@[MSG_SEND]);
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+
+ [GET_SUPER_CLASS]
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]));
+ {\$else}
+ Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]));
+ {\$endif}
+end;";
+
+ // Template for function to send Objective-c message (no params)
+ var $template_function_objc_send_no_params = "function [CLASS][NAME]: [RETURN];
+var
+ super: objc_super;
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+ [GET_SUPER_CLASS]
+ Result := [RETURN]([MSG_SEND]([OBJC_OBJECT], SEL_[SELNAME], []));
+end;";
+
+ // Template for function to send Objective-c message which returns a struct
+ var $template_function_objc_send_struct = "function [CLASS][NAME][PARAMS_HEADER]: [RETURN];
+type
+ TmsgSendWrapper = function (param1: [TARGET_TYPE]; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
+var
+ vmethod: TmsgSendWrapper;
+ super: objc_super;
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+ vmethod := TmsgSendWrapper(@[MSG_SEND]);
+ [GET_SUPER_CLASS]
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]));
+ {\$else}
+ Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]));
+ {\$endif}
+end;";
+
+ // Template for function to send Objective-c message which returns a struct
+ var $template_function_objc_send_struct_cpu = "function [CLASS][NAME][PARAMS_HEADER]: [RETURN];
+type
+ TmsgSendWrapper_reg = function (param1: [TARGET_TYPE]; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
+ TmsgSendWrapper_stret = function (param1: [TARGET_TYPE]; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
+var
+ vmethod_reg: TmsgSendWrapper_reg;
+ vmethod_stret: TmsgSendWrapper_stret;
+ super: objc_super;
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+ [GET_SUPER_CLASS]
+ {\$ifdef CPUi386}
+ vmethod_reg := TmsgSendWrapper_reg(@[MSG_SEND_REGISTER]);
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ Result := vmethod_reg([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]);
+ {\$else}
+ Result := vmethod_reg([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]);
+ {\$endif}
+ {\$else}
+ vmethod_stret := TmsgSendWrapper_stret(@[MSG_SEND_STRET]);
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ Result := [RETURN](vmethod_stret([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]));
+ {\$else}
+ Result := [RETURN](vmethod_stret([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]));
+ {\$endif}
+ {\$endif}
+end;";
+
+ // Template for function to send Objective-c message (no params) which returns a struct
+ var $template_function_objc_send_no_params_struct = "function [CLASS][NAME]: [RETURN];
+var
+ super: objc_super;
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+ [GET_SUPER_CLASS]
+ [MSG_SEND](@Result, [OBJC_OBJECT], SEL_[SELNAME], []);
+end;";
+
+ // Template for function to send Objective-c message (no params) which returns CPU dependent struct
+ var $template_function_objc_send_no_params_struct_cpu = "function [CLASS][NAME]: [RETURN];
+type
+ TmsgSendWrapper = function (param1: [TARGET_TYPE]; param2: SEL): [RETURN]; cdecl;
+var
+ vmethod: TmsgSendWrapper;
+ super: objc_super;
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+ [GET_SUPER_CLASS]
+ {\$ifdef CPUi386}
+ vmethod := TmsgSendWrapper(@[MSG_SEND_REGISTER]);
+ Result := vmethod([OBJC_OBJECT], SEL_[SELNAME] );
+ {\$else}
+ [MSG_SEND_STRET](@Result, [OBJC_OBJECT], SEL_[SELNAME], []);
+ {\$endif}
+end;";
+
+ // Template for procedure to send Objective-c message
+ var $template_procedure_objc_send = "procedure [CLASS][NAME][PARAMS_HEADER];
+type
+ TmsgSendWrapper = procedure (param1: [TARGET_TYPE]; param2: SEL[PARAMS_PROC]); cdecl;
+var
+ vmethod: TmsgSendWrapper;
+ super: objc_super;
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+ vmethod := TmsgSendWrapper(@[MSG_SEND]);
+ [GET_SUPER_CLASS]
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]);
+ {\$else}
+ vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]);
+ {\$endif}
+end;";
+
+ // Template for procedure to send Objective-c message
+ var $template_procedure_objc_send_no_params = "procedure [CLASS][NAME];
+var
+ super: objc_super;
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+ [GET_SUPER_CLASS]
+ [MSG_SEND]([OBJC_OBJECT], SEL_[SELNAME], []);
+end;";
+
+ // Template for procedure to call implemented class method. This is the procedure which the Objectice-c methods are sent to
+ var $template_procedure_objc_wrapper = "procedure [CLASS]_[NAME](_self: id; _cmd: SEL[PARAMS_HEADER]); cdecl;
+var
+ this: [CLASS];
+ [VARIABLES]
+begin
+ this := [CLASS]([CLASS].GetSelf(_self));
+ if this <> nil then
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ begin
+ [WRAPPERS_CREATE]
+ this.implemented_[NAME][PARAMS_LIST_WRAPPER];
+ [WRAPPERS_RELEASE]
+ end;
+ {\$else}
+ this.implemented_[NAME][PARAMS_LIST];
+ {\$endif}
+end;";
+
+ // Template for procedure to call implemented class method. This is the procedure which the Objectice-c methods are sent to
+ var $template_function_objc_wrapper = "function [CLASS]_[NAME](_self: id; _cmd: SEL[PARAMS_HEADER]): [RETURN]; cdecl;
+var
+ this: [CLASS];
+ [VARIABLES]
+begin
+ this := [CLASS]([CLASS].GetSelf(_self));
+ if this <> nil then
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ begin
+ [WRAPPERS_CREATE]
+ Result := [RETURN](this.implemented_[NAME][PARAMS_LIST_WRAPPER]);
+ [WRAPPERS_RELEASE]
+ end;
+ {\$else}
+ Result := [RETURN](this.implemented_[NAME][PARAMS_LIST]);
+ {\$endif}
+end;";
+
+
+ // Template for method to override Objective-c method
+ var $template_method_override = "procedure [CLASS].override_[NAME];
+begin
+ AddMethod('[OBJC_METHOD]', '[TYPE_ENCODING]', Pointer(@[CLASS]_[NAME]));
+end;";
+
+ // Template for method to override Objective-c method
+ var $template_method_override_DEPRECATED = "procedure [CLASS].override_[NAME];
+begin
+ OverrideMethod('[OBJC_METHOD]', Pointer(@[CLASS]_[NAME]));
+end;";
+
+ // Template for method to add method to Objective-c runtime
+ var $template_method_add_runtime = "procedure [CLASS].add_[NAME];
+begin
+ AddMethod('[OBJC_METHOD]', '[TYPES]', Pointer(@[CLASS]_[NAME]));
+end;";
+
+ // Template for implemented delegate procedure
+ var $template_procedure_delegate = "procedure [CLASS].[NAME][PARAMS];
+begin
+end;";
+
+ // Template for implemented delegate procedure
+ var $template_function_delegate = "function [CLASS].[NAME][PARAMS]: [RETURN];
+begin
+end;";
+
+
+ // Template for implemented delegate procedure
+ var $template_procedure_delegate_objc = "procedure [CLASS]_[NAME][PARAMS_HEADER]; cdecl;
+var
+ this: [CLASS];
+ [VARIABLES]
+begin
+ this := [CLASS]([CLASS].GetSelf(_self));
+ if this <> nil then
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ begin
+ [WRAPPERS_CREATE]
+ this.[NAME][PARAMS_LIST_WRAPPER];
+ [WRAPPERS_RELEASE]
+ end;
+ {\$else}
+ this.[NAME][PARAMS_LIST];
+ {\$endif}
+end;";
+
+ // Template for implemented delegate procedure
+ var $template_function_delegate_objc = "function [CLASS]_[NAME][PARAMS_HEADER]: [RETURN]; cdecl;
+var
+ this: [CLASS];
+ [VARIABLES]
+begin
+ this := [CLASS]([CLASS].GetSelf(_self));
+ if this <> nil then
+ {\$ifdef NSOBJECT_AUTO_WRAPPER}
+ begin
+ [WRAPPERS_CREATE]
+ Result := [RETURN](this.[NAME][PARAMS_LIST_WRAPPER]);
+ [WRAPPERS_RELEASE]
+ end;
+ {\$else}
+ Result := [RETURN](this.[NAME][PARAMS_LIST]);
+ {\$endif}
+end;";
+
+ // Template for create override in delegate class
+ var $template_delegate_create = "constructor [CLASS].Create;
+begin
+ CreateClassDefinition(ClassName, 'NSObject');
+
+ ClassID := objc_getClass('[CLASS]');
+ allocbuf := objc_msgSend(ClassId, SEL_alloc, []);
+ Handle := objc_msgSend(allocbuf, SEL_init, []);
+ retainCount := 1;
+
+ { Adds custom methods, if any }
+ AddMethods;
+ BindMethods;
+
+ { Assign our wrapper instance }
+ if Handle <> nil then
+ AssignSelf(Handle);
+end;";
+
+ // Template for constructor
+ var $template_constructor_constarray = "constructor [CLASS][NAME][PARAMS_HEADER];
+type
+ TmsgSendWrapper = function (param1: id; param2: SEL; param3: [CFTYPE]): id; cdecl;
+var
+ vmethod: TmsgSendWrapper;
+ paramList: [CFTYPE];
+ i: integer;
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+ RegisterSubClass;
+ [ALLOC_PARAM_LIST]
+ allocbuf := objc_msgSend(ClassID, SEL_alloc, []);
+ vmethod := TmsgSendWrapper(@objc_msgSend);
+ Handle := vmethod(allocbuf, SEL_[SELNAME], paramList);
+ retainCount := 1;
+ AssignSelf(Handle);
+ AddMethods;
+ BindMethods;
+ CFRelease(paramList);
+end;";
+
+ // Template for constructor that does not allocate memory
+ var $template_constructor_constarray_no_alloc = "constructor [CLASS][NAME][PARAMS_HEADER];
+type
+ TmsgSendWrapper = function (param1: id; param2: SEL; param3: [CFTYPE]): id; cdecl;
+var
+ vmethod: TmsgSendWrapper;
+ paramList: [CFTYPE];
+ i: integer;
+begin
+ if SEL_[SELNAME] = nil then
+ SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
+ RegisterSubClass;
+ [ALLOC_PARAM_LIST]
+ vmethod := TmsgSendWrapper(@objc_msgSend);
+ Handle := vmethod(ClassID, SEL_[SELNAME], paramList);
+ AutoReleaseObject;
+ AssignSelf(Handle);
+ AddMethods;
+ BindMethods;
+ CFRelease(paramList);
+end;";
+
+ // template to create param list for NSDictionary methods
+ var $template_dictionary_param_list = "paramList := CFDictionaryCreateMutable(nil, 0, @kCFTypeDictionaryKeyCallBacks, @kCFTypeDictionaryValueCallBacks);
+ i := High(firstObject);
+ while i > 0 do
+ begin
+ CFDictionaryAddValue(paramList, firstObject[i].VPointer, firstObject[i - 1].VPointer);
+ i := i - 2;
+ end;";
+
+ // template to create param list for NSArray methods
+ var $template_array_param_list = "paramList := CFArrayCreateMutable(nil, 0, @kCFTypeArrayCallBacks);
+ for i := 0 to High(firstObj) do
+ CFArrayAppendValue(paramList, firstObj[i].VPointer);";
+
+ // template to create param list for NSSet methods
+ var $template_set_param_list = "paramList := CFSetCreateMutable(nil, 0, @kCFTypeSetCallBacks);
+ for i := 0 to High(firstObj) do
+ CFSetAddValue(paramList, firstObj[i].VPointer);";
+
+ /**
+ * UTILITIES
+ */
+
+ // Skips blocks in the current file being parsed
+ function SkipBlock ($line) {
+
+ if ($line != "") {
+ foreach ($this->skip_blocks as $key => $value) {
+ if (@ereg($key, $line)) $this->parser_skipping = true;
+ if (@ereg($value, $line)) $this->parser_skipping = false;
+ }
+ }
+
+ return $this->parser_skipping;
+ }
+
+ function IsKeywordReserved($keyword) {
+ $keyword = strtolower($keyword);
+ if (in_array($keyword, $this->reserved_keywords)) return true;
+ }
+
+ // Replace type with pointer equivalent
+ function ReplacePointerType ($type) {
+
+ $type = "Pointer {".$type."}";
+ /*
+ foreach ($this->pointer_types as $objc_type => $replace_type) {
+ if ($objc_type == $type) {
+ $type = $replace_type;
+ break;
+ }
+ }
+ */
+ return $type;
+ }
+
+ // Makes a struct field into an inline array (or returns field un-changed)
+ function MakeFieldInlineArray ($io_field, $line, $name, $type) {
+
+ if (eregi("\[([0-9]+)\];", $line, $array_size)) {
+ $length = (int)$array_size[1] - 1;
+ if ($length > 0) {
+ $io_field = " $name: array[0..$length] of $type;";
+ }
+ }
+
+ return $io_field;
+ }
+
+ // Makes a type bitpacked (or returns type un-changed)
+ function MakeFieldBitPacked ($ioType, $field, &$bitpacked) {
+ $bitpacked = false;
+
+ if (eregi(":([0-9]+);$", $field, $bitpack)) {
+ $length = (int)$bitpack[1];
+ if ($length > 1) {
+ $ioType = "0..((1 shl $length)-1)";
+ } else {
+ $ioType = "0..$length";
+ }
+
+ $bitpacked = true;
+ }
+
+ return $ioType;
+ }
+
+ // Replace objc type with preferred type
+ function ReplaceObjcType ($type) {
+
+ foreach ($this->replace_types as $objc_type => $replace_type) {
+ if ($objc_type == $type) {
+ $type = $replace_type;
+ break;
+ }
+ }
+
+ return $type;
+ }
+
+ // Exchanges the preferred objc type with the real type
+ function SwapObjcTypeWithReal ($type) {
+ if ($type == $this->objc_id) $type = $this->objc_id_real;
+
+ return $type;
+ }
+
+ // Replace garbage collector hints
+ function ReplaceGarbageCollectorHints ($string, &$io_hint) {
+ $io_hint = false;
+
+ foreach ($this->garbage_collector_hints as $hint) {
+ $out_string = str_ireplace($hint, "", $string);
+ if ($out_string != $string) {
+ $io_hint = $hint;
+ $string = $out_string;
+ }
+ }
+
+ return $string;
+ }
+
+
+ // Replace type of reference parameter with pointer
+ function ReplaceReferenceParameterType ($type) {
+ foreach ($this->pointer_types as $key => $value) {
+ if ($key == $type) {
+ $found = true;
+ $type = $value;
+ break;
+ }
+ }
+
+ if (!$found) $type = $type."Pointer";
+
+ return $type;
+ }
+
+ // Replace NS*** "toll free bridge" types with CoreFoundation type
+ function ReplaceTollFreeBridgeType ($type) {
+ foreach ($this->toll_free_bridge as $objc_type => $replace_type) {
+ if ($objc_type == $type) {
+ $type = istr_replace_word($type, $replace_type, $type);
+ break;
+ }
+ }
+
+ return $type;
+ }
+
+ // Replace all NS*** classes in a string with the preffered generic type $this->objc_id
+ function ReplaceNSTypes ($string) {
+ foreach ($this->cocoa_classes as $class) {
+ $string = istr_replace_word($class, $this->objc_id, $string);
+ }
+ return $string;
+ }
+
+ // Replace all NS*** classes in a string with id
+ function ReplaceNSTypesWithReal ($string) {
+ foreach ($this->cocoa_classes as $class) {
+ $string = istr_replace_word($class, $this->objc_id_real, $string);
+ }
+ return $string;
+ }
+
+ // Replace all NS*** classes in a string with their reference equivalent (i.e NSStringRef = id)
+ function ReplaceNSTypesWithRef ($string) {
+ foreach ($this->cocoa_classes as $class) {
+ $string = istr_replace_word($class, $class."Ref", $string);
+ }
+ return $string;
+ }
+
+ // Copies the name from an Objective-C method definition
+ function CopyObjcMethodName ($method) {
+
+ // cut out comments first
+ $method = eregi_replace("(/\*.*\*/)", "", $method);
+ $method = eregi_replace("//.*$", "", $method);
+ $method = trim($method, " ");
+
+ $params = explode(":", $method);
+ $name = "";
+
+ if (count($params) > 1) {
+ foreach ($params as $value) {
+ $value = trim($value, " ");
+ if (eregi("([a-zA-Z0-9_]+)$", $value, $captures)) $name .= $captures[1].":";
+ }
+ } else {
+ if (eregi("([a-zA-Z0-9_]+)[[:space:]]*(;)*$", $method, $captures)) $name = $captures[1];
+ }
+
+ return $name;
+ }
+
+ // Converts a function pointer to Pascal function
+ function ConvertFunctionPointerToPascal ($result, $param_string) {
+
+ if ($result != "") {
+ $params = explode(",", $param_string);
+ $function = "function (";
+ $count = 0;
+
+ foreach ($params as $param) {
+ $count ++;
+ $param = trim($param, " ");
+ $param = $this->ReplaceObjcType($param);
+ $param = $this->SwapObjcTypeWithReal($param);
+ $param = trim($param, "*");
+
+ $function .= "param$count: $param; ";
+ }
+
+ $function = rtrim($function, "; ");
+ $function .= "): $result; cdecl;";
+ }
+
+ //print("$function\n");
+ return $function;
+ }
+
+ // Converts a C parameter string to Pascal
+ function ConvertCParamsPascal ($string) {
+
+ $params = explode(",", $string);
+ $param_string = "";
+
+ foreach ($params as $param) {
+
+ $param = istr_replace_word("const", "", $param);
+ $param = trim($param, " ");
+
+ $pair = explode(" ", $param);
+ $name = $pair[1];
+ $type = $pair[0];
+
+ $type = $this->ReplaceObjcType($type);
+ $type = $this->SwapObjcTypeWithReal($type);
+ $type = $this->ReplaceTollFreeBridgeType($type);
+ $type = $this->ReplaceNSTypesWithRef($type);
+
+ if (($name[0] == "*") && ($name[1] == "*")) {
+ $name = trim($name, "*");
+ $type = $this->ReplacePointerType($type);
+ } elseif ($name[0] == "*") {
+ $name = trim($name, "*");
+
+ $name = $name."Pointer";
+ //$name = "var $name";
+
+ $name = trim($name, " ");
+ } else {
+ $name = trim($name, "*");
+ }
+
+ // Remove array brackets (NSUInteger[])p
+ if (eregi("\[[0-9]*\]", $name)) {
+ $name = "$name";
+ $type = "Pointer {array of $type}";
+ $name = eregi_replace("\[[0-9]*\]", "", $name);
+ }
+
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+
+ // multiple parameters
+ if ($type == "...") {
+ $param_string .= "varargs: array of const";
+ break;
+ }
+
+ $param_string .= "$name: $type; ";
+ }
+
+ $param_string = trim($param_string, "; ");
+ return $param_string;
+ }
+
+ // Remove OS X versions macros from a line
+ // NOTE: These should be re-inlcuded in Pascal
+ function RemoveOSVersionMacros ($line) {
+ $line = eregi_replace("[[:space:]]*AVAILABLE_MAC_OS_X_VERSION_[0-9]+_[0-9]+_AND_LATER[[:space:]]*", "", $line);
+ return $line;
+ }
+
+ // Removes all comments from a line
+ function RemoveComments ($line) {
+ // remove single-line comments
+ $line = eregi_replace("[[:space:]]+//(.*)", "", $line);
+
+ // remove multi-line comments /* ... */
+ $line = eregi_replace("/\*.*\*/", "", $line);
+
+ return $line;
+ }
+
+ // Performs additional formatting on Objective-c type i.e. (out NSObject **)
+ function FormatObjcType ($type, &$modifiers) {
+ $modifiers = "";
+
+ // toss out all const identifiers
+ $type = istr_replace_word("const", "", $type);
+
+ // replace inout paramaters
+ $type = istr_replace_word("inout", "", $type);
+ $type = istr_replace_word("out", "", $type);
+ $type_clean = trim($type, "* ");
+
+ // Replace types before cleaning
+ $type = $this->ReplaceObjcType($type);
+
+ // Remove protocol which type conforms to (id <NSURLHandleClient>)
+ $type = eregi_replace("<.*>", "", $type);
+
+ // Remove array brackets (NSUInteger[])p
+ $type = eregi_replace("\[[0-9]*\]", "", $type);
+
+ // var params to non-object types (NSRange *)
+ if (ereg("([a-zA-Z0-9_]+)[[:space:]]*[*]+$", $type, $captures)) {
+ if ((!in_array($captures[1], $this->cocoa_classes)) && ($captures[1] != "id")) {
+ $type = $this->ReplaceReferenceParameterType($type_clean); //"$type_clean$this->pointer_type_suffx";
+ //$modifiers = "var ";
+ }
+ }
+
+ // Handle NS*** pointers (NSError **)
+ if (ereg("(NS[a-zA-Z0-9_]+)[[:space:]]*\*\*$", $type, $captures)) {
+ if (in_array($captures[1], $this->cocoa_classes)) {
+ $type = "$type_clean$this->class_pointer_suffix";
+ //$modifiers = "var ";
+ }
+ }
+
+ // clean the type
+ $type = trim($type, "* ");
+
+ //print("$type\n");
+ return $type;
+ }
+
+ // Performs additional formatting on Objective-c parameter types
+ function FormatObjcParams ($string) {
+ $params = explode(":", $string);
+ $string = "";
+
+ if (count($params) > 0) {
+ foreach ($params as $value) {
+ if (ereg("\((.*)\)", $value, $captures)) {
+ $new_value = $this->ReplaceObjcType($captures[1]);
+
+ if ($new_value != $captures[1]) $value = ereg_replace("\((.*)\)", "($new_value)", $value);
+
+ $string .= ":$value";
+ }
+ }
+ }
+
+ $string = ltrim($string, ":");
+ //print("$string\n");
+ return $string;
+ }
+
+ // Converts an Objective-c parameter string to Pascal
+ function ConvertObjcParamsToPascal ($string, $protected_keywords, &$variable_arguments) {
+ $params = explode(":", $string);
+ $list = array();
+ $list["pairs"] = array();
+ $param_list = array();
+ $variable_arguments = false;
+
+ if (count($params) > 0) {
+ //print_r($params);
+ foreach ($params as $value) {
+ $value = trim($value);
+ $valid = false;
+ $modifiers = "";
+
+ // function pointer (callback)
+ if (eregi("\(([a-zA-Z0-9_]+)[[:space:]]\((.*)\)\((.*)\)\)([a-zA-Z0-9_]+)", $value, $captures)) {
+ $name = $captures[4];
+
+ $type = $this->current_header["name_clean"].ucwords($name);
+
+ // attempt to build a function pointer from the parameter and append the class type
+ if ($this->current_header) {
+ $function_pointer = $this->ConvertFunctionPointerToPascal($captures[1], $captures[3]);
+
+ if (!@in_array($function_pointer, $this->current_header["types"]["callbacks"])) {
+ $count = 0;
+ while (@array_key_exists($type, $this->current_header["types"]["callbacks"])) {
+ $count ++;
+ $type = "$type$count";
+ }
+
+ // append the new type to the the current class
+ $this->current_header["types"]["callbacks"][$type] = $function_pointer;
+ } else {
+ // Use the name of the existing callback of matching type
+ $type = array_search($function_pointer, $this->current_header["types"]["callbacks"]);
+ }
+ }
+
+ $valid = true;
+ } elseif (eregi("\(([a-zA-Z_]+).*\)([a-zA-Z_]+).*\.\.\.", $value, $captures)) { // variable arguments
+ $name = $captures[2];
+ $type = $captures[1];
+ $variable_arguments = true;
+ $valid = true;
+ } elseif (eregi("\((.*)\)[[:space:]]*([a-zA-Z_]+)", $value, $captures)) { // standard parameter
+
+ // pointers params to non-object types (NSRange *)
+ if (ereg("[a-zA-Z0-9_]+Ptr$", $captures[2])) {
+ $captures[1] = trim($captures[1], "* ");
+ $captures[1] = $this->ReplaceObjcType($captures[1]);
+
+ $type = $captures[1].$this->class_pointer_suffix;//$this->ReplacePointerType($captures[1]);
+ $name = $captures[2];
+ } else {
+ $type = $this->FormatObjcType($captures[1], $modifiers);
+ $name = $captures[2];
+ }
+
+
+ $valid = true;
+ }
+
+ if ($valid) {
+
+ // protect reserved keywords
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+
+ if (!in_array($type, $this->reserved_types)) {
+ if ($this->IsKeywordReserved($type)) $type .= "_";
+ }
+
+ if (@in_array($name, $protected_keywords)) $name .= "_";
+ if (@in_array($type, $protected_keywords)) $type .= "_";
+
+ // replace objc types
+ $type = $this->ReplaceObjcType($type);
+ $type = $this->ReplaceTollFreeBridgeType($type);
+
+ // make sure we label duplicate params, which are allowed in Objective-C
+ while (in_array($name, $param_list)) {
+ $count ++;
+ $name = "$name$count";
+ }
+
+ // id is always a wrapper
+ if (($this->objects_are_wrappers) && ($type == $this->objc_id)) {
+ $name_list = "$type(GetHandle($name))";
+ } else {
+ $name_list = $name;
+ }
+
+ // add modifiers to the name if there are any
+ $name_with_modifiers = $modifiers.$name;
+
+ // create pair array
+ $pair["name"] = $name;
+ $pair["type"] = $type;
+
+ // append list
+ $list["pairs"][] = $pair;
+ $list["string_with_modifiers"] .= "$name_with_modifiers: $type; ";
+ $list["string"] .= "$name: $type; ";
+ $list["list"] .= "$name_list, ";
+ $param_list[] = $name;
+ }
+ }
+ }
+
+ // clean up the strings
+ $list["string"] = trim($list["string"], "; ");
+ $list["string_with_modifiers"] = trim($list["string_with_modifiers"], "; ");
+ $list["list"] = trim($list["list"], ", ");
+
+ return $list;
+ }
+
+ // Converts an Objective-c method name to Pascal
+ function ConvertObjcMethodName ($method) {
+ $params = explode(":", $method);
+ $name = "";
+
+ if (count($params) > 1) {
+ foreach ($params as $value) {
+ if (eregi("([a-zA-Z0-9]+)$", $value, $captures)) $name .= $captures[1]."_";
+ }
+ } else {
+ if (eregi("([a-zA-Z0-9]+)(;)*$", $params[0], $captures)) $name .= $captures[1]."_";
+ }
+
+ // clean it up
+ if (!$this->trailing_underscore) $name = trim($name, "_");
+
+ $name = $this->ReplaceObjcType($name);
+
+ return $name;
+ }
+
+ // Converts an Objective-C method to Pascal format
+ function ConvertObjcMethodToPascal ($class, $source, $parts, $protected_keywords, $has_params) {
+
+ // replace "hinted" params comment with hinted type
+ if ($this->replace_hinted_params) {
+
+ // param string
+ if (eregi("(/\*[[:space:]]*(.*)[[:space:]]*\*/)", $parts[4], $captures)) {
+ // ??? change the parameter to the hinted type
+ //$parts[4] = eregi_replace("(/\*.*\*/)", $captures[2], $parts[4]);
+ //$parts[4] = trim($parts[4], " ");
+ }
+
+ // return type
+ if (eregi("(/\*[[:space:]]*(.*)[[:space:]]*\*/)", $parts[2], $captures)) $parts[2] = $captures[2];
+
+ //print_r($parts);
+
+ } else { // remmove comments from params and return type
+ $parts[4] = eregi_replace("(/\*.*\*/)", "", $parts[4]);
+ $parts[4] = trim($parts[4], " ");
+
+ $parts[2] = eregi_replace("(/\*.*\*/)", "", $parts[2]);
+ $parts[2] = trim($parts[2], " ");
+ }
+
+ $return_type_clean = $parts[2];
+
+ // perform preformatting before attempting to protect keywords
+ $parts[2] = $this->FormatObjcType($parts[2], $modifiers);
+ $parts[4] = $this->FormatObjcParams($parts[4]);
+
+ // protect keywords in the parameter and return type
+ if (count($protected_keywords) > 0) {
+ foreach ($protected_keywords as $keyword) {
+ $parts[4] = istr_replace_word($keyword, $keyword."_", $parts[4]);
+ $parts[2] = istr_replace_word($keyword, $keyword."_", $parts[2]);
+ }
+ }
+
+ if ($has_params) {
+ $name = $this->ConvertObjcMethodName($source);
+
+ // merge default protected keywords for the class/category
+ if ($this->default_protected["*"]) $protected_keywords = array_merge($this->default_protected["*"], $protected_keywords);
+ if ($this->default_protected[$class]) $protected_keywords = array_merge($this->default_protected[$class], $protected_keywords);
+
+ $param_array = $this->ConvertObjcParamsToPascal($parts[4], $protected_keywords, $variable_arguments);
+ $params = "(".$param_array["string"].")";
+ $params_with_modifiers = "(".$param_array["string_with_modifiers"].")";
+ } else {
+ $params = "";
+ $params_with_modifiers = "";
+ $name = $parts[3];
+ $param_array = null;
+ }
+
+ //print("$params_with_modifiers\n");
+
+ // protect method name from keywords
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+
+ // clean return type
+ $return_type = trim($parts[2], "* ");
+ $return_type = $this->ReplaceObjcType($return_type);
+ $return_type = $this->ReplaceTollFreeBridgeType($return_type);
+
+ $virtual = "";
+ $class_prefix = "";
+
+ // determine the type based on return value
+ if (ereg($this->regex_procedure_type, $return_type_clean)) {
+ $kind = "procedure";
+ } else {
+ $kind = "function";
+
+ // make sure Objective-c objects that are returned from fuctions are not NSObject (and thus auto-wrapped)
+ if ($return_type == $this->objc_id) $return_type = $this->objc_id_real;
+
+ // method name starts with "init or alloc"
+ if ((ereg("^(init|alloc)+[^ialization]", $name)) && ($parts[1] == "-")) {
+ $struct["alloc"] = true;
+ $kind = "constructor";
+ $virtual = " virtual;";
+ }
+
+ // Class methods with the words: With, By or From in the name
+ if ((ereg("^([a-zA-Z]+)(With|By|From)+", $name, $captures)) && ($parts[1] == "+")) $kind = "constructor";
+
+ // Class methods which return "id" are constructors
+ if (($parts[1] == "+") && ($return_type == $this->objc_id_real)) $kind = "constructor";
+
+ // method result is the class name
+ if ($return_type == $class) $kind = "constructor";
+ }
+
+ // determine if this is a class method
+ if (($kind != "constructor") && ($parts[1] == "+")) $class_prefix = "class ";
+
+ // Determine if the method needs a particular modifier
+ // ??? THIS IS NOT COMPILING???
+ //if (ereg($this->objc_object_array, $params)) $modifier = " cdecl;";
+
+ // Replace SEL with the string equivalent
+ if ($this->register_selectors) {
+ $params_with_modifiers = str_replace_word("SEL", $this->sel_string, $params_with_modifiers);
+ }
+
+ // make method templates
+ if ($kind != "function") {
+ $method = "$class_prefix$kind $name$params_with_modifiers;$modifier$virtual";
+ $method_template = "[KIND] [PREFIX]$name"."[PARAMS];$modifier";
+ } else {
+ $method = $class_prefix."function $name$params_with_modifiers: $return_type;$modifier$virtual";
+ $method_template = "[KIND] [PREFIX]$name"."[PARAMS]: [RETURN];$modifier";
+ $method_template_function = "function [PREFIX]$name"."[PARAMS]: [RETURN];$modifier";
+ }
+
+ $method_template_procedure = "procedure [PREFIX]$name"."[PARAMS];$modifier";
+ $method_template_function = "function [PREFIX]$name"."[PARAMS]: [RETURN];$modifier";
+
+ // ??? DEBUGGING
+ //print("$method\n");
+
+ // build structure
+ $struct["def"] = $method;
+ $struct["template"] = $method_template;
+ $struct["template_function"] = $method_template_function;
+ $struct["template_procedure"] = $method_template_procedure;
+ $struct["objc_method"] = $this->CopyObjcMethodName($source);
+ $struct["class_prefix"] = $class_prefix;
+ //$struct["def_objc"] = eregi("(.*);", $source, $captures[1]);
+ if ($return_type == "void") $return_type = "";
+ $struct["return"] = $return_type;
+ if (in_array($return_type, $this->cocoa_classes)) $struct["returns_wrapper"] = true;
+ $struct["param_string_clean"] = trim($params, "()");
+ $struct["param_string_clean_with_modifiers"] = trim($params_with_modifiers, "()");
+ $struct["param_string"] = $params;
+ $struct["param_string_with_modifiers"] = $params_with_modifiers;
+ $struct["param_array"] = $param_array["pairs"];
+ $struct["param_list"] = $param_array["list"];
+ $struct["class"] = $class;
+ $struct["name"] = $name;
+ $struct["kind"] = $kind;
+
+ if ($struct["param_array"] != null) $struct["has_params"] = true;
+
+ // determine if the method can be overriden
+ // (!eregi("^(set|get|is)+", $name))
+ if ($kind != "constructor") $struct["can_override"] = true;
+
+ /*
+ TEMPORARY! we don't know how to handle super methods that have have floating point values
+ */
+ if (in_array($struct["return"], $this->float_types)) {
+ $struct["can_override"] = false;
+ print(" # WARNING: method $name can't override because the return type is float\n");
+ $this->warning_count ++;
+ }
+
+ // FPC bug work around
+ if (strlen($name) > $this->maximum_method_length) {
+ $struct["can_override"] = false;
+ print(" # WARNING: method $name can't override because the name is too long\n");
+ $this->warning_count ++;
+ }
+
+ return $struct;
+ }
+
+ // Print string to output file
+ function PrintOutput ($indent, $string) {
+ for ($i=0; $i < $indent; $i++) {
+ $indent_string .= " ";
+ }
+
+ if (($this->output) && (!$this->show)) fwrite($this->output, "$indent_string$string\n");
+
+ if ($this->show) print("$indent_string$string\n");
+ }
+
+ // Returns the message sending template for a method structure
+ function GetMsgSendTemplate ($method, $super) {
+ if ($method["kind"] == "function") {
+ if ($method["has_params"]) {
+ $template = $this->template_function_objc_send;
+ } else {
+ $template = $this->template_function_objc_send_no_params;
+ }
+ } else {
+ if ($method["has_params"]) {
+ $template = $this->template_procedure_objc_send;
+ } else {
+ $template = $this->template_procedure_objc_send_no_params;
+ }
+ }
+
+ // method returns a NS*** class wrapper. Now, super methods can't return wrappers
+ if (!$super) {
+ if (($method["kind"] == "function") && (in_array($method["return"], $this->cocoa_classes))) {
+ if ($method["has_params"]) {
+ $template = $this->template_function_make_wrapper;
+ } else {
+ $template = $this->template_function_make_wrapper_no_params;
+ }
+ }
+ }
+
+ // method returns a struct
+ if (($method["kind"] == "function") && (in_array($method["return"], $this->struct_types))) {
+ if ($method["has_params"]) {
+ $template = $this->template_function_objc_send_struct;
+ } else {
+ $template = $this->template_function_objc_send_no_params_struct;
+ }
+ }
+
+ // method returns an architecture dependent struct
+ if (($method["kind"] == "function") && (in_array($method["return"], $this->struct_register_types))) {
+ if ($method["has_params"]) {
+ $template = $this->template_function_objc_send_struct_cpu;
+ } else {
+ $template = $this->template_function_objc_send_no_params_struct_cpu;
+ }
+ }
+
+ // method is a constructor
+ if ($method["kind"] == "constructor") {
+ $template = $this->template_constructor_no_alloc;
+ if ($method["alloc"]) $template = $this->template_constructor;
+ }
+
+ return $template;
+ }
+
+ // Returns a class hierarchy array
+ function GetClassHierarchy ($class, &$hierarchy) {
+ if (!$hierarchy) $hierarchy = array();
+ $hierarchy[] = $class["name"];
+
+ if ($class["super_class"]) {
+ $hierarchy[] = $this->GetClassHierarchy($class["super_class"], $hierarchy);
+ } else {
+ $hierarchy[] = "NSObject";
+ }
+
+ return $class["name"];
+ }
+
+ // returns if a keyword is protected in a class hierarchy
+ function IsKeywordProtected ($keyword, $in_class) {
+ $keywords = $this->GetClassHierarchy($in_class, $hierarchy);
+
+ foreach ($hierarchy as $key) {
+ if (@in_array($keyword, $keywords)) { //$this->dump["master"][$key]["protected_keywords"]
+ return true;
+ }
+ }
+ }
+
+ // Returns all protected keywords in a class hierarchy
+ function GetProtectedKeywords ($in_class) {
+ $this->GetClassHierarchy($in_class, $hierarchy);
+ $keywords = array();
+
+ foreach ($hierarchy as $class) {
+ if ($this->dump["master"][$class]["protected_keywords"]) {
+ foreach ($this->dump["master"][$class]["protected_keywords"] as $keyword) $keywords[] = $keyword;
+ }
+ }
+
+ return $keywords;
+ }
+
+
+ // Returns header a category should be moved to
+ function FindCategoryHeader ($category) {
+
+ foreach ($this->dump as $name => $header) {
+ if ((@array_key_exists($category, $header["classes"])) && ($category != "NSObject")) {
+ return $name;
+ }
+ }
+ }
+
+ // Adds a method structure to a class and performs checks for overloaded methods
+ function AddMethodToClass (&$method, &$class) {
+
+ // ignore methods
+ if (in_array($method["name"], $this->ignore_methods)) return false;
+
+ if (@!in_array($method["name"], $class["declared_methods"])) {
+
+ $class["all"][$method["name"]] = $method;
+ $class["protected_keywords"][] = $method["name"];
+ $class["declared_methods"][] = $method["name"];
+ $this->dump["all_methods"][$class["name"]][] = $method["objc_method"];
+
+ if ($this->show_added_messages) print(" @ Added ".$method["name"]." to ".$class["name"]."\n");
+
+ $this->method_count ++;
+ return true;
+ } else {
+ print(" ! ".$method["def"]." already exists in ".$class["name"]." defined as ".$class["all"][$method["name"]]["def"]."\n");
+ }
+ }
+
+ // Adds a typedef to the header and handles organization to prevent order conflicts
+ function AddTypeDef (&$header, $typedef) {
+ $header["types"]["typedef"][] = $typedef;
+ }
+
+ // Returns a paramater list string with options to modify
+ function MakeParamList ($param_array, $use_handle, $cast_handle, $direct, $register_selector) {
+ $params = "";
+ foreach ($param_array as $pair) {
+
+ // register selector parameters
+ if (($register_selector) && ($pair["type"] == "SEL")) {
+ $params .= "sel_registerName(".$pair["name"]."), ";
+ continue;
+ }
+
+ // use the object handle for NSObject descendants
+ if ($use_handle) {
+ if (in_array($pair["type"], $this->cocoa_classes)) {
+
+ // cast the param to the original class type
+ if ($cast_handle) {
+ if ($direct == ACCESS_HANDLE_DIRECT) {
+ $params .= $pair["type"]."(".$pair["name"].".Handle), ";
+ } else {
+ $params .= $pair["type"]."(GetHandle(".$pair["name"].")), ";
+ }
+ } else {
+ if ($direct == ACCESS_HANDLE_DIRECT) {
+ $params .= $pair["name"].".Handle, ";
+ } else {
+ $params .= "GetHandle(".$pair["name"]."), ";
+ }
+ }
+
+ } else {
+ if (($this->objects_are_wrappers) && ($pair["type"] == $this->objc_id)) { // id is always a wrapper
+ if ($direct == ACCESS_HANDLE_DIRECT) {
+ $params .= $pair["type"]."(".$pair["name"].".Handle), ";
+ } else {
+ $params .= $pair["type"]."(GetHandle(".$pair["name"].")), ";
+ }
+ } else {
+ $params .= $pair["name"].", ";
+ }
+ }
+ } else { // append without modification
+ $params .= $pair["name"].", ";
+ }
+ }
+
+ return trim($params, ", ");
+ }
+
+ // Returns a list of paramameter variables with NS*** class types cast to "id" or the original class
+ function MakeObjcTypeParamList ($param_array, $objc_type) {
+ $params = "";
+ foreach ($param_array as $pair) {
+ if (in_array($pair["type"], $this->cocoa_classes)) {
+ if ($objc_type) {
+ $params .= "$this->objc_id(".$pair["name"]."), ";
+ } else {
+ $params .= $pair["type"]."(".$pair["name"]."), ";
+ }
+ } else {
+ $params .= $pair["name"].", ";
+ }
+ }
+ return trim($params, ", ");
+ }
+
+ /**
+ * PRINTING METHODS
+ */
+
+ // Prints implemented methods
+ function PrintImplementedMethods ($class) {
+
+ // print implemented methods
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Implemented methods }");
+ foreach ($class["all"] as $method) {
+ if ($method["can_override"]) {
+
+ if ($method["kind"] == "function") {
+ $template = $this->template_implemented_function;
+ } else {
+ $template = $this->template_implemented_procedure;
+ }
+
+ $template = str_replace("[CLASS]", $class["name"], $template);
+ $template = str_replace("[NAME]", $method["name"], $template);
+
+ $method["return"] = $this->ReplaceNSTypesWithRef($method["return"]);
+ $template = str_replace("[RETURN]", $method["return"], $template);
+ $template = str_replace("[PARAMS_HEADER]", $method["param_string_with_modifiers"], $template);
+
+ // build parameter list
+ if ($method["has_params"]) {
+
+ // auto-generate wrappers
+ $params = "(";
+ $params .= $this->MakeParamList($method["param_array"], USE_HANDLE, CAST_HANDLE, ACCESS_HANDLE_FUNCTION, DONT_REGISTER_SEL);
+ $params .= ")";
+ $template = str_replace("[PARAMS_BODY_WRAPPER]", $params, $template);
+
+ // standard params
+ $params = "(";
+ $params .= $this->MakeObjcTypeParamList($method["param_array"], true);
+ $params .= ")";
+ $template = str_replace("[PARAMS_BODY]", $params, $template);
+
+
+ } else {
+ $template = str_replace("[PARAMS_BODY]", "", $template);
+ $template = str_replace("[PARAMS_BODY_WRAPPER]", "", $template);
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, $template);
+ }
+ }
+
+ }
+
+ // Prints Objective-C wrapper procedures
+ function PrintObjcWrapperProcedures ($class) {
+
+ // print implemented methods
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Objective-c wrapper procedures }");
+ foreach ($class["all"] as $method) {
+ if ($method["can_override"]) {
+
+ if ($method["kind"] == "function") {
+ $template = $this->template_function_objc_wrapper;
+ } else {
+ $template = $this->template_procedure_objc_wrapper;
+ }
+
+ $template = str_replace("[CLASS]", $class["name"], $template);
+ $template = str_replace("[NAME]", $method["name"], $template);
+ $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
+
+ $method["return"] = $this->ReplaceNSTypesWithRef($method["return"]);
+ $template = str_replace("[RETURN]", $method["return"], $template);
+
+ if ($method["has_params"]) {
+ $method["param_string_clean"] = $this->ReplaceNSTypes($method["param_string_clean"]);
+
+ // Make sure we always the id type in objc wrappers
+ $params_header = $this->ReplaceNSTypesWithRef($method["param_string_clean_with_modifiers"]);
+ $template = str_replace("[PARAMS_HEADER]", "; $params_header", $template);
+
+ // auto-generate wrappers
+ $wrappers_variables = "";
+ $wrappers_create = "";
+ $wrappers_release = "";
+ $variable_list = "";
+
+ foreach ($method["param_array"] as $pair) {
+ if (in_array($pair["type"], $this->cocoa_classes)) {
+
+ $wrappers_variables .= "object_".$pair["name"].": ".$pair["type"]."\n;";
+ $wrappers_create .= "object_".$pair["name"]." := ".$pair["type"].".CreateWithHandle(".$pair["name"].");\n";
+ $wrappers_release .= "object_".$pair["name"].".release;\n";
+ $variable_list .= "object_".$pair["name"].", ";
+ } else {
+ $variable_list .= $pair["name"].", ";
+ }
+ }
+ $variable_list = trim($variable_list, ", ");
+
+ $template = str_replace("[VARIABLES]", $wrappers_variables, $template);
+ $template = str_replace("[WRAPPERS_CREATE]", $wrappers_create, $template);
+ $template = str_replace("[WRAPPERS_RELEASE]", $wrappers_release, $template);
+
+ $template = str_replace("[PARAMS_LIST_WRAPPER]", "($variable_list)", $template);
+
+ $params = $this->MakeObjcTypeParamList($method["param_array"], false);
+ $template = str_replace("[PARAMS_LIST]", "($params)", $template);
+
+ } else {
+ $template = str_replace("[PARAMS_HEADER]", "", $template);
+ $template = str_replace("[PARAMS_LIST]", "", $template);
+ $template = str_replace("[PARAMS_LIST_WRAPPER]", "", $template);
+ $template = str_replace("[VARIABLES]", "", $template);
+ $template = str_replace("[WRAPPERS_CREATE]", "", $template);
+ $template = str_replace("[WRAPPERS_RELEASE]", "", $template);
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, $template);
+ }
+ }
+ }
+
+ // Prints send message objects with a custom implementation
+ function PrintCustomSendMessageMethods ($class, $method) {
+
+ // NSArray
+ if ($class["name"] == "NSArray") {
+ if ($method["name"] == "arrayWithObjects") $template = $this->template_constructor_constarray_no_alloc;
+ if ($method["name"] == "initWithObjects") $template = $this->template_constructor_constarray;
+
+ $template = str_replace("[CFTYPE]", "CFArrayRef", $template);
+ $template = str_replace("[ALLOC_PARAM_LIST]", $this->template_array_param_list, $template);
+
+ if ($method["name"] == "arrayWithObjects") $template = str_replace("[OBJC_METHOD]", "arrayWithArray:", $template);
+ if ($method["name"] == "initWithObjects") $template = str_replace("[OBJC_METHOD]", "initWithArray:", $template);
+ }
+
+ // NSDictionary
+ if ($class["name"] == "NSDictionary") {
+ if ($method["name"] == "dictionaryWithObjectsAndKeys") $template = $this->template_constructor_constarray_no_alloc;
+ if ($method["name"] == "initWithObjectsAndKeys") $template = $this->template_constructor_constarray;
+
+ $template = str_replace("[CFTYPE]", "CFDictionaryRef", $template);
+ $template = str_replace("[ALLOC_PARAM_LIST]", $this->template_dictionary_param_list, $template);
+
+ if ($method["name"] == "dictionaryWithObjectsAndKeys") $template = str_replace("[OBJC_METHOD]", "dictionaryWithDictionary:", $template);
+ if ($method["name"] == "initWithObjectsAndKeys") $template = str_replace("[OBJC_METHOD]", "initWithDictionary:", $template);
+ }
+
+ // NSSet
+ if ($class["name"] == "NSSet") {
+ if ($method["name"] == "setWithObjects") $template = $this->template_constructor_constarray_no_alloc;
+ if ($method["name"] == "initWithObjects") $template = $this->template_constructor_constarray;
+
+ $template = str_replace("[CFTYPE]", "CFSetRef", $template);
+ $template = str_replace("[ALLOC_PARAM_LIST]", $this->template_set_param_list, $template);
+
+ if ($method["name"] == "setWithObjects") $template = str_replace("[OBJC_METHOD]", "setWithSet:", $template);
+ if ($method["name"] == "initWithObjects") $template = str_replace("[OBJC_METHOD]", "initWithSet:", $template);
+ }
+
+ $template = str_replace("[PARAMS_HEADER]", $method["param_string_with_modifiers"], $template);
+ $template = str_replace("[CLASS]", $class["name"].".", $template);
+ $template = str_replace("[NAME]", $method["name"], $template);
+ $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, $template);
+ }
+
+ // Prints send message objects
+ function PrintSendMessageMethods ($class) {
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Objective-c send message methods }");
+ foreach ($class["all"] as $method) {
+
+ // handle custom methods
+ if (in_array($class["name"].".".$method["name"], $this->custom_send_methods)) {
+ $this->PrintCustomSendMessageMethods($class, $method);
+ continue;
+ }
+
+ $template = $this->GetMsgSendTemplate($method, false);
+
+ $template = $method["class_prefix"].$template;
+
+ $template = str_replace("[CLASS]", $class["name"].".", $template);
+ $template = str_replace("[NAME]", $method["name"], $template);
+ $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
+ $template = str_replace("[RETURN]", $method["return"], $template);
+
+ // Replace SEL with the string equivalent so it can be registered inside the wrapper
+ if ($this->register_selectors) {
+ $params_header = str_replace_word("SEL", $this->sel_string, $method["param_string_with_modifiers"]);
+ $register = REGISTER_SEL;
+ } else {
+ $params_header = $method["param_string_with_modifiers"];
+ $register = DONT_REGISTER_SEL;
+ }
+
+ $template = str_replace("[PARAMS_HEADER]", $params_header, $template);
+
+ if ($method["has_params"]) {
+ $template = str_replace("[PARAMS_PROC]", "; ".$method["param_string_clean_with_modifiers"], $template);
+
+ $params_wrapper = $this->MakeParamList($method["param_array"], USE_HANDLE, CAST_HANDLE, ACCESS_HANDLE_FUNCTION, $register);
+ $params_list = $this->MakeParamList($method["param_array"], DONT_USE_HANDLE, DONT_CAST_HANDLE, ACCESS_HANDLE_FUNCTION, $register);
+
+ $template = str_replace("[PARAMS_LIST_WRAPPER]", ", ".$params_wrapper, $template);
+ $template = str_replace("[PARAMS_LIST]", ", ".$params_list, $template);
+ } else {
+ $template = str_replace("[PARAMS_PROC]", "", $template);
+ $template = str_replace("[PARAMS_LIST]", "", $template);
+ $template = str_replace("[PARAMS_LIST_WRAPPER]", "", $template);
+ }
+
+ $template = str_replace("[TARGET_TYPE]", $this->objc_id_real, $template);
+ $template = str_replace("[OBJC_METHOD]", $method["objc_method"], $template);
+ $template = str_replace("[GET_SUPER_CLASS]", "", $template);
+
+ // decide reference to objc object by method type
+ if ($method["class_prefix"] == "") {
+ $template = str_replace("[OBJC_OBJECT]", "Handle", $template);
+ } else {
+ $template = str_replace("[OBJC_OBJECT]", "getClass", $template);
+ }
+
+ $template = str_replace("[MSG_SEND_STRET]", "objc_msgSend_stret", $template);
+ $template = str_replace("[MSG_SEND_REGISTER]", "objc_msgSend", $template);
+
+ if (in_array($method["return"], $this->struct_types)) { // structure
+ $template = str_replace("[MSG_SEND]", "objc_msgSend_stret", $template);
+ } elseif (in_array($method["return"], $this->float_types)) { // floating point
+ $template = str_replace("[MSG_SEND]", "objc_msgSend_fpret", $template);
+ } else { // simple type
+ $template = str_replace("[MSG_SEND]", "objc_msgSend", $template);
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, $template);
+ }
+ }
+
+ // Prints override methods
+ function PrintOverrideMethods ($class) {
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Override methods }");
+ foreach ($class["all"] as $method) {
+ if ($method["can_override"]) {
+
+ $template = $this->template_method_override;
+
+ $template = str_replace("[CLASS]", $class["name"], $template);
+ $template = str_replace("[NAME]", $method["name"], $template);
+ $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
+ $template = str_replace("[OBJC_METHOD]", $method["objc_method"], $template);
+ $template = str_replace("[TYPE_ENCODING]", $this->type_encodings[$class["name"]][$method["objc_method"]], $template);
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, $template);
+ }
+ }
+ }
+
+ // Prints implemented methods that contain sending code
+ function PrintImplementedSuperMethods ($class) {
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Implemented methods }");
+ foreach ($class["all"] as $method) {
+ if ($method["can_override"]) {
+
+ $template = $this->GetMsgSendTemplate($method, true);
+
+ $template = str_replace("[CLASS]", $class["name"].".", $template);
+ $template = str_replace("[NAME]", "implemented_".$method["name"], $template);
+ $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
+ $method["return"] = $this->ReplaceNSTypesWithRef($method["return"]);
+ $template = str_replace("[RETURN]", $method["return"], $template);
+
+ // Replace SEL with the string equivalent so it can be registered inside the wrapper
+ if ($this->register_selectors) {
+ $params_header = str_replace_word("SEL", $this->sel_string, $method["param_string_with_modifiers"]);
+ $register = REGISTER_SEL;
+ } else {
+ $params_header = $method["param_string_with_modifiers"];
+ $register = DONT_REGISTER_SEL;
+ }
+ $template = str_replace("[PARAMS_HEADER]", $params_header, $template);
+
+ if ($method["has_params"]) {
+ $template = str_replace("[PARAMS_PROC]", "; ".$method["param_string_clean_with_modifiers"], $template);
+
+ $params_wrapper = $this->MakeParamList($method["param_array"], USE_HANDLE, CAST_HANDLE, ACCESS_HANDLE_FUNCTION, $register);
+ $params_list = $this->MakeParamList($method["param_array"], DONT_USE_HANDLE, DONT_CAST_HANDLE, ACCESS_HANDLE_FUNCTION, $register);
+
+ $template = str_replace("[PARAMS_LIST_WRAPPER]", ", ".$params_wrapper, $template);
+ $template = str_replace("[PARAMS_LIST]", ", ".$params_list, $template);
+ } else {
+ $template = str_replace("[PARAMS_PROC]", "", $template);
+ $template = str_replace("[PARAMS_LIST]", "", $template);
+ }
+
+ $template = str_replace("[TARGET_TYPE]", "Pobjc_super", $template);
+ $template = str_replace("[OBJC_METHOD]", $method["objc_method"], $template);
+ $template = str_replace("[OBJC_OBJECT]", "@super", $template);
+ $template = str_replace("[GET_SUPER_CLASS]", "super := getSuperClass;", $template);
+
+ $template = str_replace("[MSG_SEND_STRET]", "objc_msgSendSuper_stret", $template);
+ $template = str_replace("[MSG_SEND_REGISTER]", "objc_msgSendSuper", $template);
+
+ if (in_array($method["return"], $this->struct_types)) {
+ $template = str_replace("[MSG_SEND]", "objc_msgSendSuper_stret", $template);
+ } else {
+ $template = str_replace("[MSG_SEND]", "objc_msgSendSuper", $template);
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, $template);
+ }
+ }
+ }
+
+ // Prints super methods
+ function PrintSuperMethods ($class) {
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Super methods }");
+ foreach ($class["all"] as $method) {
+ if ($method["can_override"]) {
+
+ $template = $this->GetMsgSendTemplate($method, true);
+
+ $template = str_replace("[CLASS]", $class["name"].".", $template);
+ $template = str_replace("[NAME]", "super_".$method["name"], $template);
+ $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
+
+ $method["return"] = $this->ReplaceNSTypesWithRef($method["return"]);
+ $template = str_replace("[RETURN]", $method["return"], $template);
+
+ //$method["param_string"] = $this->ReplaceNSTypesWithReal($method["param_string"]);
+ //$method["param_string_clean"] = $this->ReplaceNSTypesWithReal($method["param_string_clean"]);
+
+ $template = str_replace("[PARAMS_HEADER]", $method["param_string_with_modifiers"], $template);
+ $template = str_replace("[PARAMS_PROC]", "; ".$method["param_string_clean"], $template);
+ $template = str_replace("[PARAMS_LIST_WRAPPER]", ", ".$method["param_list"], $template);
+ $template = str_replace("[PARAMS_LIST]", ", ".$method["param_list"], $template);
+ $template = str_replace("[TARGET_TYPE]", "Pobjc_super", $template);
+ $template = str_replace("[OBJC_METHOD]", $method["objc_method"], $template);
+ $template = str_replace("[OBJC_OBJECT]", "@super", $template);
+ $template = str_replace("[GET_SUPER_CLASS]", "", $template);
+
+ if (in_array($method["return"], $this->struct_types)) {
+ $template = str_replace("[MSG_SEND]", "objc_msgSendSuper_stret", $template);
+ } else {
+ $template = str_replace("[MSG_SEND]", "objc_msgSendSuper", $template);
+ }
+
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, $template);
+ }
+ }
+ }
+
+ function PrintProtocolDeclaration ($protocol, $method) {
+ $template = $method["template"];
+ $template = str_replace("[PREFIX]", $protocol["name"]."_", $template);
+
+ if ($method["param_array"] == 0) {
+ $param = "sourceObject: NSObjectRef";
+ } else {
+ $param = "sourceObject: NSObjectRef; ";
+ }
+
+ $template = str_replace("[PARAMS]", "($param".$method["param_string_clean_with_modifiers"].")", $template);
+ $template = str_replace("[KIND]", $method["kind"], $template);
+ $template = str_replace("[RETURN]", $method["return"], $template);
+
+ $this->PrintOutput(0, $template);
+ }
+
+ // Prints all the protocols in the header
+ function PrintHeaderProtocols ($header, $implemented) {
+
+ if (!$header["protocols"]) return;
+
+ foreach ($header["protocols"] as $protocol) {
+
+ if ($implemented) {
+
+ if (!$protocol["methods"]) continue;
+
+ foreach ($protocol["methods"] as $name => $method) {
+ if ($method["kind"] != "constructor") {
+ //$this->PrintProtocolDeclaration($protocol, $method);
+
+ $template = $this->GetMsgSendTemplate($method, false);
+
+ // choose the protocol version
+ if ($template == $this->template_function_make_wrapper) $template = $this->template_protocol_make_wrapper;
+ if ($template == $this->template_function_make_wrapper_no_params) $template = $this->template_protocol_make_wrapper_no_params;
+
+ $template = str_replace("[CLASS]", $protocol["name"]."_", $template);
+ if ($method["param_array"] == 0) {
+ // add header params token to accommodate our extra parameter
+ $template = str_replace("[NAME]", $method["name"]."[PARAMS_HEADER]", $template);
+ } else {
+ $template = str_replace("[NAME]", $method["name"], $template);
+ }
+ $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
+ $template = str_replace("[RETURN]", $method["return"], $template);
+
+ if ($method["param_array"] == 0) {
+ $source_param = "sourceObject: NSObjectRef";
+ } else {
+ $source_param = "sourceObject: NSObjectRef; ";
+ }
+
+ // Replace SEL with the string equivalent so it can be registered inside the wrapper
+ if ($this->register_selectors) {
+ $params_header = str_replace_word("SEL", $this->sel_string, $method["param_string_clean_with_modifiers"]);
+ $register = REGISTER_SEL;
+ } else {
+ $params_header = $method["param_string_clean_with_modifiers"];
+ $register = DONT_REGISTER_SEL;
+ }
+
+ $template = str_replace("[PARAMS_HEADER]", "($source_param$params_header)", $template);
+
+ if ($method["has_params"]) {
+ $template = str_replace("[PARAMS_PROC]", "; ".$method["param_string_clean"], $template);
+
+ $params_wrapper = $this->MakeParamList($method["param_array"], USE_HANDLE, CAST_HANDLE, ACCESS_HANDLE_DIRECT, $register);
+ $params_list = $this->MakeParamList($method["param_array"], DONT_USE_HANDLE, DONT_CAST_HANDLE, ACCESS_HANDLE_DIRECT, $register);
+
+ $template = str_replace("[PARAMS_LIST_WRAPPER]", ", ".$params_wrapper, $template);
+ $template = str_replace("[PARAMS_LIST]", ", ".$params_list, $template);
+ } else {
+ $template = str_replace("[PARAMS_PROC]", "", $template);
+ $template = str_replace("[PARAMS_LIST]", "", $template);
+ }
+
+ $template = str_replace("[TARGET_TYPE]", $this->objc_id_real, $template);
+ $template = str_replace("[OBJC_METHOD]", $method["objc_method"], $template);
+ $template = str_replace("[GET_SUPER_CLASS]", "", $template);
+
+ $template = str_replace("[MSG_SEND_STRET]", "objc_msgSend_stret", $template);
+ $template = str_replace("[MSG_SEND_REGISTER]", "objc_msgSend", $template);
+
+ // use the source object as the the target
+ $template = str_replace("[OBJC_OBJECT]", "sourceObject", $template);
+
+ if (in_array($method["return"], $this->struct_types)) { // structure
+ $template = str_replace("[MSG_SEND]", "objc_msgSend_stret", $template);
+ } elseif (in_array($method["return"], $this->float_types)) { // floating point
+ $template = str_replace("[MSG_SEND]", "objc_msgSend_fpret", $template);
+ } else { // simple type
+ $template = str_replace("[MSG_SEND]", "objc_msgSend", $template);
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, $template);
+
+
+ }
+ }
+
+ } else {
+ if ($protocol["methods"]) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Protocol: ".$protocol["name"]." }");
+
+ foreach ($protocol["methods"] as $name => $method) {
+ if ($method["kind"] != "constructor") {
+ $this->PrintProtocolDeclaration($protocol, $method);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ function PrintSelectorVariables ($class) {
+
+ // class has no methods, bail!
+ if (!$class["methods"]) return;
+
+ $this->PrintOutput(0,"var");
+
+ foreach ($class["all"] as $method) {
+ $sel_name = str_replace(":", "_", $method["objc_method"]);
+ $this->PrintOutput(1, "SEL_$sel_name: SEL;");
+ }
+
+ }
+
+ // Prints a classes implementation in Pascal format to a file handle
+ function PrintClassImplementation ($class) {
+
+ // class has no methods, bail!
+ if (!$class["methods"]) return;
+
+ $name = $class["name"];
+
+ $this->PrintOutput(0,"");
+ $this->PrintOutput(0, "{ Selectors for $name }");
+ $this->PrintSelectorVariables($class);
+
+ $this->PrintOutput(0,"");
+ $this->PrintOutput(0, "{ Implementation for $name }");
+
+ // Global accessor object
+ $this->PrintOutput(0,"");
+ $this->PrintOutput(0,"var");
+ $this->PrintOutput(1, "__".$class["name"].": ".$class["name"].";");
+
+ // getClass method
+ $this->PrintOutput(0,"");
+ $this->PrintOutput(0,"class function $name.getClass: $this->objc_id_real;");
+ $this->PrintOutput(0,"begin");
+ $this->PrintOutput(1,"Result := objc_getClass('$name');");
+ $this->PrintOutput(0,"end;");
+
+ // withObject static accessor
+ $this->PrintOutput(0,"");
+ $this->PrintOutput(0, "class function $name.withObject (inObject: Pointer): $name;");
+ $this->PrintOutput(0,"begin");
+ $this->PrintOutput(1,"if __$name = nil then");
+ $this->PrintOutput(2,"__$name := $name.Create;");
+ $this->PrintOutput(1,"__$name.Handle := inObject;");
+ $this->PrintOutput(1,"result := __$name;");
+ $this->PrintOutput(0,"end;");
+
+ $this->PrintImplementedSuperMethods($class);
+ // DEPRECTAED IN FAVOR OF IMPLEMENTED SUPER METHODS
+ //$this->PrintImplementedMethods($class);
+ //$this->PrintSuperMethods($class);
+ $this->PrintObjcWrapperProcedures($class);
+ $this->PrintOverrideMethods($class);
+ $this->PrintSendMessageMethods($class);
+ }
+
+ // Prints a calls in Pascal format to a file handle
+ public function PrintClass ($class) {
+
+ // class has no methods, bail!
+ if (!$class["methods"]) return;
+
+ // the delegate class is the super class of NSObject
+ if ($class["name"] == "NSObject") $class["super"] = $this->master_delegate_class;
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ ".$class["name"]." }");
+ $this->PrintOutput(1, $class["name"]." = class(".$class["super"].")");
+ $this->PrintOutput(1, "public");
+
+ // getClass override
+ $this->PrintOutput(2, "class function getClass: $this->objc_id_real; override;");
+
+ // static wrapper accessor
+ $class_name = $class["name"];
+ $this->PrintOutput(2, "class function withObject (inObject: Pointer): $class_name;");
+
+ // print class-level methods
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(2, "{ Class Methods }");
+ foreach ($class["methods"] as $method) {
+ $this->PrintOutput(2, $method["def"]);
+ }
+
+ // print category-level methods
+ if (count($class["categories"]) > 0) {
+ foreach ($class["categories"] as $name => $category) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(2, "{ Category: $name }");
+
+ if ($category["methods"]) {
+ foreach ($category["methods"] as $method) {
+ $this->PrintOutput(2, $method["def"]);
+ }
+ }
+ }
+ }
+
+ // print implemented methods
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(1, "protected");
+ $this->PrintOutput(2, "{ Implemented Methods }");
+ foreach ($class["all"] as $method) {
+ if ($method["can_override"]) {
+
+ $template = $method["template"];
+ $template = str_replace("[PREFIX]", "implemented_", $template);
+ $template = str_replace("[PARAMS]", $method["param_string_with_modifiers"], $template);
+ $template = str_replace("[KIND]", $method["kind"], $template);
+
+ // implemented methods always return id instead of wrappers
+ $method["return"] = $this->ReplaceNSTypesWithRef($method["return"]);
+
+ $template = str_replace("[RETURN]", $method["return"], $template);
+
+ $this->PrintOutput(2, $template." virtual;");
+ }
+ }
+
+ // print override methods
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(2, "{ Override Methods }");
+ foreach ($class["all"] as $method) {
+ if ($method["can_override"]) {
+
+ $template = $method["template_procedure"];
+ $template = str_replace("[PREFIX]", "override_", $template);
+ $template = str_replace("[PARAMS]", "", $template);
+ $template = str_replace("[RETURN]", "", $template);
+
+ $this->PrintOutput(2, $template);
+ }
+ }
+
+ // print super methods
+ /* DEPRECTAED IN FAVOR OF IMPLEMENTED SUPER METHODS
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(2, "{ Super Methods }");
+ foreach ($class["all"] as $method) {
+ if ($method["can_override"]) {
+
+ $template = $method["template"];
+ $template = str_replace("[PREFIX]", "super_", $template);
+ $template = str_replace("[PARAMS]", $method["param_string_with_modifiers"], $template);
+ $template = str_replace("[KIND]", $method["kind"], $template);
+ $template = str_replace("[RETURN]", $this->ReplaceNSTypesWithRef($method["return"]), $template);
+
+ $this->PrintOutput(2, $template);
+ }
+ }
+ */
+ $this->PrintOutput(1, "end;");
+ }
+
+ function PrintDelegateReference ($valid_categories) {
+
+ ksort($this->delegate_methods);
+
+ $this->PrintOutput(0, "unit $this->master_delegate_file;");
+ $this->PrintOutput(0, "interface");
+ $this->PrintOutput(0, "uses");
+ $this->PrintOutput(1, "ctypes, objc, MacOSAll");
+
+ $this->PrintOutput(0, "type");
+ $this->PrintOutput(1, "$this->master_delegate_class = class");
+ $this->PrintOutput(1, "public");
+
+ // implemented methods
+ foreach ($this->delegate_methods as $category => $selectors) {
+ if (in_array($category, $this->ignore_categories)) continue;
+
+ // make sure the category is valid
+ $valid = false;
+ foreach ($valid_categories as $pattern) {
+ if (eregi($pattern, $category)) {
+ $valid = true;
+ break;
+ }
+ }
+ if (!$valid) continue;
+
+ $this->PrintOutput(2, "");
+ $this->PrintOutput(2, "{ $category }");
+
+ foreach ($selectors as $selector) {
+
+ // FPC long name bug work-around
+ if (strlen($selector["name_pascal"]) > $this->maximum_method_length) continue;
+
+ if ($selector["kind"] == "procedure") {
+ $this->PrintOutput(2, $selector["kind"]." ".$selector["name_pascal"].$selector["param_string"].";");
+ } else {
+ $this->PrintOutput(2, $selector["kind"]." ".$selector["name_pascal"].$selector["param_string"].": ".$selector["method"]["return"].";");
+ }
+
+ }
+ }
+
+ $this->PrintOutput(1, "end;");
+ }
+
+
+ function PrintDelegateClass ($valid_categories) {
+
+ ksort($this->delegate_methods);
+
+ $this->PrintOutput(0, "{\$ifdef FORWARD}");
+ $this->PrintOutput(1, "$this->master_delegate_class = class;");
+ $this->PrintOutput(0, "{\$endif}");
+
+ $this->PrintOutput(0, "{\$ifdef CLASSES}");
+ $macro = strtoupper($this->master_delegate_class);
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_C}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_C}");
+
+ $this->PrintOutput(1, "$this->master_delegate_class = class(NSObjectCore)");
+ $this->PrintOutput(1, "public");
+
+ //$this->PrintOutput(2, "constructor Create; override;");
+
+ // implemented methods
+ foreach ($this->delegate_methods as $category => $selectors) {
+ if (in_array($category, $this->ignore_categories)) continue;
+
+ // make sure the category is valid
+ $valid = false;
+ foreach ($valid_categories as $pattern) {
+ if (eregi($pattern, $category)) {
+ $valid = true;
+ break;
+ }
+ }
+ if (!$valid) continue;
+
+ $this->PrintOutput(2, "");
+ $this->PrintOutput(2, "{ $category }");
+
+ foreach ($selectors as $selector) {
+
+ // FPC long name bug work-around
+ if (strlen($selector["name_pascal"]) > $this->maximum_method_length) continue;
+
+ if ($selector["kind"] == "procedure") {
+ $this->PrintOutput(2, $selector["kind"]." ".$selector["name_pascal"].$selector["param_string"]."; virtual;");
+ } else {
+ $this->PrintOutput(2, $selector["kind"]." ".$selector["name_pascal"].$selector["param_string"].": ".$selector["method"]["return"]."; virtual;");
+ }
+
+ }
+ }
+
+ // add methods
+ $this->PrintOutput(2, "");
+ $this->PrintOutput(2, "{ Adding methods }");
+ foreach ($this->delegate_methods as $category => $selectors) {
+ if (in_array($category, $this->ignore_categories)) continue;
+
+ // make sure the category is valid
+ $valid = false;
+ foreach ($valid_categories as $pattern) {
+ if (eregi($pattern, $category)) {
+ $valid = true;
+ break;
+ }
+ }
+ if (!$valid) continue;
+
+ foreach ($selectors as $selector) {
+ // FPC long name bug work-around
+ if (strlen("add_".$selector["name_pascal"]) > $this->maximum_method_length) continue;
+
+ $this->PrintOutput(2, "procedure add_".$selector["name_pascal"].";");
+ }
+ }
+
+ $this->PrintOutput(1, "end;");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$ifdef IMPLEMENTATION}");
+
+ // create constructor method
+ /*
+ $this->PrintOutput(0, "");
+ $template = str_replace("[CLASS]", $this->master_delegate_class, $this->template_delegate_create);
+ $this->PrintOutput(0, $template);
+ */
+
+ // print implemented methods
+ foreach ($this->delegate_methods as $category => $selectors) {
+ if (in_array($category, $this->ignore_categories)) continue;
+
+ // make sure the category is valid
+ $valid = false;
+ foreach ($valid_categories as $pattern) {
+ if (eregi($pattern, $category)) {
+ $valid = true;
+ break;
+ }
+ }
+ if (!$valid) continue;
+
+ // place-holder methods
+ foreach ($selectors as $selector) {
+
+ // FPC long name bug work-around
+ if (strlen($selector["name_pascal"]) > $this->maximum_method_length) continue;
+
+ if ($selector["kind"] == "procedure") {
+ $this->PrintOutput(0, $selector["kind"]." ".$this->master_delegate_class.".".$selector["name_pascal"].$selector["param_string"].";");
+ } else {
+ $this->PrintOutput(0, $selector["kind"]." ".$this->master_delegate_class.".".$selector["name_pascal"].$selector["param_string"].": ".$selector["method"]["return"].";");
+ }
+
+ $this->PrintOutput(0, "begin");
+ $this->PrintOutput(0, "end;");
+ $this->PrintOutput(0, "");
+ }
+
+ // objc wrappers
+ foreach ($selectors as $selector) {
+
+ // FPC long name bug work-around
+ if (strlen($selector["name_pascal"]) > $this->maximum_method_length) continue;
+
+ if ($selector["kind"] == "function") {
+ $template = $this->template_function_delegate_objc;
+ } else {
+ $template = $this->template_procedure_delegate_objc;
+ }
+
+ $template = str_replace("[CLASS]", $this->master_delegate_class, $template);
+ $template = str_replace("[NAME]", $selector["name_pascal"], $template);
+
+ $selector["method"]["return"] = $this->ReplaceNSTypes($selector["method"]["return"]);
+ $template = str_replace("[RETURN]", $selector["method"]["return"], $template);
+
+ if ($selector["method"]["has_params"]) {
+ $selector["method"]["param_string_clean"] = $this->ReplaceNSTypesWithRef($selector["method"]["param_string_clean"]);
+ $template = str_replace("[PARAMS_HEADER]", " (_self: $this->objc_id_real; _cmd: SEL; ".$selector["method"]["param_string_clean"].")", $template);
+
+ // auto-generate wrappers
+ $wrappers_variables = "";
+ $wrappers_create = "";
+ $wrappers_release = "";
+ $variable_list = "";
+
+ foreach ($selector["method"]["param_array"] as $pair) {
+ if (in_array($pair["type"], $this->cocoa_classes)) {
+
+ $wrappers_variables .= "object_".$pair["name"].": ".$pair["type"].";\n";
+ $wrappers_create .= "object_".$pair["name"]." := ".$pair["type"].".CreateWithHandle(".$pair["name"].");\n";
+ $wrappers_release .= "object_".$pair["name"].".release;\n";
+ $variable_list .= "object_".$pair["name"].", ";
+ } else {
+ $variable_list .= $pair["name"].", ";
+ }
+ }
+ $variable_list = trim($variable_list, ", ");
+
+ $template = str_replace("[VARIABLES]", $wrappers_variables, $template);
+ $template = str_replace("[WRAPPERS_CREATE]", $wrappers_create, $template);
+ $template = str_replace("[WRAPPERS_RELEASE]", $wrappers_release, $template);
+
+ $template = str_replace("[PARAMS_LIST_WRAPPER]", "($variable_list)", $template);
+
+ $params = $this->MakeObjcTypeParamList($selector["method"]["param_array"], false);
+ $template = str_replace("[PARAMS_LIST]", "($params)", $template);
+
+ } else {
+ $template = str_replace("[PARAMS_HEADER]", "(_self: $this->objc_id_real; _cmd: SEL)", $template);
+ $template = str_replace("[PARAMS_LIST]", "", $template);
+ $template = str_replace("[PARAMS_LIST_WRAPPER]", "", $template);
+ $template = str_replace("[VARIABLES]", "", $template);
+ $template = str_replace("[WRAPPERS_CREATE]", "", $template);
+ $template = str_replace("[WRAPPERS_RELEASE]", "", $template);
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, $template);
+ }
+
+ // add methods
+ foreach ($selectors as $selector) {
+
+ // FPC long name bug work-around
+ if (strlen($selector["name_pascal"]) > $this->maximum_method_length) continue;
+
+ $template = $this->template_method_add_runtime;
+
+ $template = str_replace("[CLASS]", $this->master_delegate_class, $template);
+ $template = str_replace("[NAME]", $selector["name_pascal"], $template);
+ $template = str_replace("[TYPES]", $selector["types"], $template);
+ $template = str_replace("[OBJC_METHOD]", $selector["name"], $template);
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, $template);
+ }
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+
+ print("* Printed delegate class to "."$this->root$this->out/foundation/$this->master_delegate_file.inc\n");
+ }
+
+ // Prints all externally defined symbols
+ function PrintExternalSymbols ($header) {
+ if (!$this->dump[$header["name"]]["types"]) return;
+ foreach ($this->dump[$header["name"]]["types"] as $key => $type_array) {
+
+ // External string constants
+ if ($key == "string_constant") {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ External string constants }");
+ $this->PrintOutput(0, "var");
+
+ foreach ($type_array as $type) $this->PrintOutput(1, $type);
+ }
+
+ if ($key == "external_symbol") {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ External symbols }");
+ $this->PrintOutput(0, "var");
+
+ foreach ($type_array as $type) $this->PrintOutput(1, $type);
+ }
+ }
+ }
+
+ // Prints all types in the header
+ function PrintTypes ($header) {
+ if (!$this->dump[$header["name"]]["types"]) return;
+
+ foreach ($this->dump[$header["name"]]["types"] as $key => $type_array) {
+
+ // External defines
+ if ($key == "defines") {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Defines }");
+ $this->PrintOutput(0, "const");
+
+ foreach ($type_array as $type) $this->PrintOutput(1, $type);
+ }
+
+ // External CFString constants
+ /*
+ if ($key == "string_constant") {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ External string constants }");
+ $this->PrintOutput(0, "var");
+
+ foreach ($type_array as $type) $this->PrintOutput(1, $type);
+ }
+ */
+
+ // Named Enumerations
+ /*
+ if ($key == "named_enums") {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Sets }");
+ foreach ($type_array as $type) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "type");
+ $this->PrintOutput(1, $type);
+ }
+ }
+ */
+
+ // Enumerations
+ if ($key == "enums") {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Constants }");
+ foreach ($type_array as $block) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "const");
+ foreach ($block as $type) $this->PrintOutput(1, $type);
+ }
+ }
+
+ // Typedefs
+ if (($key == "typedef") || ($key == "named_enums")) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Types }");
+ $this->PrintOutput(0, "type");
+
+ foreach ($type_array as $type) $this->PrintOutput(1, $type);
+ }
+
+ // CallBacks
+ if ($key == "callbacks") {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Callbacks }");
+ $this->PrintOutput(0, "type");
+
+ foreach ($type_array as $name => $type) $this->PrintOutput(1, "$name = $type");
+ }
+
+ }
+ }
+
+ // Prints all records in the header
+ function PrintRecords ($header) {
+ if (!$this->dump[$header["name"]]["types"]) return;
+
+ foreach ($this->dump[$header["name"]]["types"] as $key => $type_array) {
+ // Structures
+ if ($key == "structs") {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Records }");
+
+ foreach ($type_array as $type) {
+ $this->PrintOutput(0, "type");
+ $this->PrintOutput(1, $type);
+ }
+ }
+ }
+ }
+
+ // Prints all callbacks in the header
+ function PrintCallBacks ($header) {
+ if (!$this->dump[$header["name"]]["types"]) return;
+
+ foreach ($this->dump[$header["name"]]["types"] as $key => $type_array) {
+ if ($key == "callbacks") {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Callbacks }");
+ $this->PrintOutput(0, "type");
+
+ foreach ($type_array as $name => $type) $this->PrintOutput(1, "$name = $type");
+ }
+ }
+ }
+
+ // Prints all external functions in the header
+ function PrintFunctions ($header) {
+ if (!$this->dump[$header["name"]]["types"]) return;
+
+ foreach ($this->dump[$header["name"]]["types"] as $key => $type_array) {
+ if ($key == "functions") {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Functions }");
+
+ foreach ($type_array as $type) $this->PrintOutput(0, $type);
+ }
+ }
+ }
+
+ // Prints all classes from the header in reference format (not for compiling)
+ function PrintHeaderReference ($header, $path) {
+
+ $this->output = fopen($path, "w+");
+
+ //$this->PrintOutput(0, "{ ".ucfirst($header["framework"]).".framework ".$header["name"]." }");
+ $this->PrintOutput(0, "unit ".$header["name_clean"].";");
+ $this->PrintOutput(0, "interface");
+ $this->PrintOutput(0, "uses");
+ $this->PrintOutput(1, "ctypes, objc, MacOSAll;");
+
+ if ($header["classes"]) {
+ foreach ($header["classes"] as $class) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "type");
+ $this->PrintOutput(1, $class["name"]."Ref = ".$this->objc_id_real.";");
+ $this->PrintOutput(1, $class["name"]."Pointer = Pointer;");
+ }
+ }
+
+ // types
+ $this->PrintTypes($header);
+ $this->PrintRecords($header);
+ $this->PrintFunctions($header);
+ $this->PrintExternalSymbols($header);
+
+ if ($header["classes"]) {
+
+ foreach ($header["classes"] as $class) {
+ if (in_array($class["name"], $this->cocoa_classes)) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "type");
+
+ $this->PrintOutput(1, $class["name"]." = object(".$class["super"].")");
+
+ // print class-level methods
+ if (count($class["methods"]) > 0) {
+ $this->PrintOutput(0, "");
+ foreach ($class["methods"] as $method) {
+ $this->PrintOutput(2, $method["def"]);
+ }
+ }
+
+ // print category-level methods
+ if (count($class["categories"]) > 0) {
+ foreach ($class["categories"] as $name => $category) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(2, "{ Category: $name }");
+
+ if ($category["methods"]) {
+ foreach ($category["methods"] as $method) {
+ $this->PrintOutput(2, $method["def"]);
+ }
+ }
+ }
+ }
+
+ $this->PrintOutput(1, "end;");
+ }
+ }
+ }
+
+ // print procedural protocols
+ if ($header["protocols"]) {
+ foreach ($header["protocols"] as $protocol) {
+ if ($protocol["methods"]) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{ Protocol: ".$protocol["name"]." }");
+
+ foreach ($protocol["methods"] as $name => $method) {
+ if ($method["kind"] != "constructor") {
+ $this->PrintProtocolDeclaration($protocol, $method);
+ }
+ }
+ }
+ }
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "implementation");
+ $this->PrintOutput(0, "end.");
+ }
+
+ // Prints all classes from the header
+ public function PrintHeader ($header) {
+ global $version;
+
+ $this->output = fopen($header["path"], "w+");
+
+ $this->PrintOutput(0, "{ Parsed from ".ucfirst($header["framework"]).".framework ".$header["name"]." }");
+
+ $date = date("D M j G:i:s T Y");
+ $this->PrintOutput(0, "{ Version $version - $date }");
+ $this->PrintOutput(0, "");
+
+ $macro = strtoupper(substr($header["name"], 0, (strripos($header["name"], "."))));
+
+ if ($header["classes"]) {
+ $this->PrintOutput(0, "{\$ifdef HEADER}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_H}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_H}");
+
+
+ foreach ($header["classes"] as $class) {
+ $this->PrintOutput(0, "type");
+
+ // Make a id "reference" to each class which is an object but reveals the name of the class
+ if ($class["name"]."Ref" == $this->objc_id_real) {
+ $ref = $this->objc_id_base; // replace duplicates with the "base id"
+ } else {
+ $ref = $this->objc_id_real;
+ }
+
+ $this->PrintOutput(1, $class["name"]."Ref = ".$ref.";");
+
+ // Make a pointer to each class
+ $this->PrintOutput(1, $class["name"]."Pointer = Pointer;");
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef TYPES}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_T}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_T}");
+ $this->PrintTypes($header);
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef RECORDS}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_R}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_R}");
+ $this->PrintRecords($header);
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef FUNCTIONS}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_F}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_F}");
+ $this->PrintFunctions($header);
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef CALLBACKS}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_F}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_F}");
+ $this->PrintCallBacks($header);
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef EXTERNAL_SYMBOLS}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_T}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_T}");
+ $this->PrintExternalSymbols($header);
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+
+ if ($header["classes"]) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef FORWARD}");
+
+ foreach ($header["classes"] as $class) {
+ // if the class contains methods make a forward declaration, otherwise a dummy class to NSObject
+ if (count($class["all"]) > 0) {
+ $this->PrintOutput(1, $class["name"]." = class;");
+ } else {
+ $this->PrintOutput(1, $class["name"]." = NSObject;");
+ }
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ }
+
+ if ($header["classes"]) {
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef CLASSES}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_C}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_C}");
+
+ foreach ($header["classes"] as $class) {
+ if (in_array($class["name"], $this->cocoa_classes)) {
+ $this->PrintClass($class);
+ //print(" - Printed class ".$class["name"]."\n");
+ }
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+ }
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef PROTOCOLS}");
+ $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_P}");
+ $this->PrintOutput(0, "{\$define $macro"."_PAS_P}");
+ $this->PrintHeaderProtocols($header, false);
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$endif}");
+ $this->PrintOutput(0, "{\$endif}");
+
+ $this->PrintOutput(0, "");
+ $this->PrintOutput(0, "{\$ifdef IMPLEMENTATION}");
+
+ $this->PrintHeaderProtocols($header, true);
+
+ if ($header["classes"]) {
+ foreach ($header["classes"] as $class) {
+ if (in_array($class["name"], $this->cocoa_classes)) {
+ $this->PrintClassImplementation($class);
+ }
+ }
+ }
+
+ $this->PrintOutput(0, "{\$endif}");
+ }
+
+ // Prints all headers parsed
+ function PrintAllHeaders ($output_path, $ignore_output, $only_files, $print_header_references) {
+
+ foreach ($this->dump as $file => $header) {
+ if (eregi("^[a-zA-Z]+\.h", $file)) {
+
+ // ignore these files
+ if (@in_array($header["path_partial"], $ignore_output)) continue;
+
+ // only parse these files
+ if ((@count($only_files) > 0) && (@!in_array($header["name"], $only_files))) continue;
+
+ $name_clean = substr($file, 0, (strripos($file, ".")));
+
+ // assign output path
+ if ($output_path != "") $header["path"] = $output_path."/".$name_clean.".inc";
+
+ $this->PrintHeader($header);
+
+ if ($print_header_references) $this->PrintHeaderReference($header, $this->root.$this->out."/reference/".$name_clean.".pas");
+
+ print("* Printed $name_clean.h to ".$header["path"]."\n");
+ }
+ }
+ }
+
+ /**
+ * PARSING METHODS
+ */
+
+ // Insert macro blocks to replace c-style blocks
+ function InsertMacroBlocks ($line, &$in_macro_block) {
+
+ // only insert if we are in a block already.
+ // NOTE: this does not handle nesting!
+ if ($in_macro_block) {
+
+ // macro else statment
+ if (eregi("#else", $line)) {
+ return "{\$else}";
+ }
+
+ // macro endif statment
+ if (eregi("#endif", $line)) {
+ $in_macro_block = false;
+ return "{\$endif}";
+ }
+ }
+
+ foreach ($this->macro_blocks as $key => $value) {
+ if (eregi($key, $line, $captures)) {
+ $in_macro_block = true;
+
+ // replace the c-macro with a Pascal version
+ if ($value == "*") {
+ $captures[0] = trim($captures[0], "#");
+ return "{\$".$captures[0]."}";
+ } else {
+ return "{".$value."}";
+ }
+ }
+ }
+ }
+
+ function ParseInstanceVariables ($line, &$struct) {
+ $field = null;
+ $field_bitpacked = false;
+ //print("$line\n");
+
+ // insert macros
+ if ($macro = $this->InsertMacroBlocks($line, $this->inside_macro_block)) {
+ if ($struct["valid"]) {
+ $struct["fields"][] = $macro;
+ return null;
+ } else {
+ return $macro;
+ }
+
+ }
+ // got struct
+ if (eregi("^[[:space:]]*struct.*{", $line)) {
+ $struct["valid"] = true;
+ return null;
+ }
+
+ if (eregi("^[[:space:]]*}[[:space:]]*([a-zA-Z_0-9]+);", $line, $captures)) {
+ $struct["name"] = "_".trim($captures[1], " ");
+ //print_r($struct);
+ return "struct";
+ }
+
+ // set field prefix to protect scope
+ if (!$struct["valid"]) $field_prefix = "_";
+
+ // remove null-defined macros:
+ $line = str_ireplace($this->null_macros, "", $line);
+
+ // replace garbage collector hints in the field
+ $line = $this->ReplaceGarbageCollectorHints($line, $garbage_collector_hint);
+
+ if (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_* ]+).*;", $line, $captures)) { // double-word single
+
+ $name = trim($captures[3], "* ");
+ $name = str_replace(" ", "", $name);
+ $name = str_replace(" ", "", $name);
+
+ if (eregi("^[[:space:]]*struct", $captures[1])) {
+ $type = $captures[2];
+ } else {
+ $type = $captures[1]." ".$captures[2];
+ }
+
+ $type = $this->ReplaceObjcType($type);
+ $type = $this->SwapObjcTypeWithReal($type);
+ $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+ if ($captures[3][0] == "*") $this->ReplacePointerType($type);
+
+ $field = "$field_prefix$name: $type;";
+ $field = $this->MakeFieldInlineArray($field, $line, $name, $type);
+ $field = eregi_replace("<.*>", "", $field);
+
+ } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_* ]+)(.*);", $line, $captures)) { // double-word type list
+ $name = trim($captures[2], "* ");
+ $name = str_replace(" ", "", $name);
+ $name = str_replace(" ", "", $name);
+
+ $type = $this->ReplaceObjcType($captures[1]);
+ $type = $this->SwapObjcTypeWithReal($type);
+ $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+ if ($captures[2][0] == "*") $this->ReplacePointerType($type);
+
+ $field = "$field_prefix$name: $type;";
+ $field = $this->MakeFieldInlineArray($field, $line, $name, $type);
+ $field = eregi_replace("<.*>", "", $field);
+
+ } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_*]+)(.*);", $line, $captures)) { // single word type list
+ $name = trim($captures[2], "* ");
+ $name = str_replace(" ", "", $name);
+ $name = str_replace(" ", "", $name);
+
+ $type = $this->ReplaceObjcType($captures[1]);
+ $type = $this->SwapObjcTypeWithReal($type);
+ $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+ if ($captures[2][0] == "*") $this->ReplacePointerType($type);
+ $type = trim($type, "*");
+
+ $field = "$field_prefix$name: $type;";
+ $field = $this->MakeFieldInlineArray($field, $line, $name, $type);
+ $field = eregi_replace("<.*>", "", $field);
+ }
+
+ // mark the field as having a garbage collector field
+ if ($garbage_collector_hint) $field = "$field {garbage collector: $garbage_collector_hint }";
+
+ // return field
+ if ($struct["valid"]) {
+ if ($field_bitpacked) $struct["bitpacked"] = true;
+ $struct["fields"][] = $field;
+ } else {
+ return $field;
+ }
+ }
+
+ // Parses a struct field into a list
+ function ParseStructList ($input, $name, $type) {
+ $field = "";
+
+ $list = explode(",", $input);
+ if (count($list) > 1) {
+ $field = " ";
+ foreach ($list as $key) {
+ $key = trim($key, " ");
+ $field .= "$key, ";
+ }
+
+ $field = rtrim($field, ", ");
+ $field .= ": $type;\n";
+ } else {
+ $field = " $name: $type;\n";
+ }
+
+ return $field;
+ }
+
+ // Parse external symbols, enums and typedef's from the header
+ function ParseHeaderTypes ($file) {
+ $contents = ReadTextFile($file);
+ $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
+ $field_bitpacked = false;
+
+ $lines = explode("\n", $contents);
+ foreach ($lines as $line) {
+
+ // skip blocks
+ if ($this->SkipBlock($line)) continue;
+
+ // garbage collector hints
+ $line = $this->ReplaceGarbageCollectorHints($line, $garbage_collector_hint);
+
+ // remove macros
+ $line = $this->RemoveOSVersionMacros($line);
+
+ // remove comments
+ $line = $this->RemoveComments($line);
+ $line = trim($line, " ");
+
+ if ($got_struct) {
+
+ // insert macros
+ if ($macro = $this->InsertMacroBlocks($line, $this->inside_macro_block)) $struct_fields .= "$macro\n";
+
+ // collect fields
+ if (eregi("^[[:space:]]*([a-zA-Z0-9_*]+)[[:space:]]*[*]*\((.*)\)\((.*)\);", $line, $captures)) { // function pointer (callback)
+ //continue;
+ $name = trim($captures[2], "*");
+ $result = $this->ReplaceNSTypesWithReal($captures[1]);
+ $result = $this->ReplaceObjcType($result);
+ $result = ": ".$this->SwapObjcTypeWithReal($result);
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+
+ if ($captures[1] == "void") {
+ $kind = "procedure";
+ $result = "";
+ } else {
+ $kind = "function";
+ }
+
+ // ??? convert params to Pascal
+ //$method = $this->ConvertFunctionPointerToPascal($result, $captures[3]);
+ //$params = $method["param_string_clean"];
+ $params = "context: Pointer {bad params!!}";
+
+ $struct_fields .= " $name: $kind ($params)$result; cdecl;\n";
+ //print("$name: $kind ($params)$result; cdecl;\n");
+ } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_* ]+)(.*);", $line, $captures)) { // double-word single
+ $name = trim($captures[3], "* ");
+ $name = str_replace(" ", "", $name);
+ $name = str_replace(" ", "", $name);
+ $type = $captures[1]." ".$captures[2];
+ $type = $this->ReplaceObjcType($type);
+ $type = $this->SwapObjcTypeWithReal($type);
+ $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+ if ($captures[3][0] == "*") $this->ReplacePointerType($type);
+
+ //$struct_fields .= " $name: $type;\n";
+ $struct_fields .= $this->ParseStructList($captures[3]+$captures[4], $name, $type);
+
+ } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_* ]+)(.*);", $line, $captures)) { // double-word type list
+ $name = trim($captures[2], "* ");
+ $name = str_replace(" ", "", $name);
+ $name = str_replace(" ", "", $name);
+ $type = $this->ReplaceObjcType($captures[1]);
+ $type = $this->SwapObjcTypeWithReal($type);
+ $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+ if ($captures[2][0] == "*") $this->ReplacePointerType($type);
+
+ $struct_fields .= $this->ParseStructList("$captures[2]$captures[3]", $name, $type);
+
+ } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_* ]+)(.*);", $line, $captures)) { // single word type list
+ $name = trim($captures[2], "* ");
+ $captures[1] = str_replace(" ", "", $captures[1]);
+ $captures[1] = str_replace(" ", "", $captures[1]);
+ $type = $this->ReplaceObjcType($captures[1]);
+ $type = $this->SwapObjcTypeWithReal($type);
+ $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+ if ($captures[2][0] == "*") $this->ReplacePointerType($type);
+
+ //$struct_fields .= " $name: $type;\n";
+ $struct_fields .= $this->ParseStructList($captures[2], $name, $type);
+ }
+
+
+ // got end of struct
+ if (ereg("^}[[:space:]]*([a-zA-Z_0-9]+);", $line, $captures)) {
+
+ if ($struct_name == "") {
+ $struct_name = $captures[1];
+ $make_pointer = true;
+ } else {
+ $struct_type = $captures[1];
+ }
+
+ if ($field_bitpacked) {
+ $struct = "$struct_name = $this->bitpacked_record_keyword\n";
+ } else {
+ $struct = "$struct_name = $this->record_keyword\n";
+ }
+
+ $struct .= $struct_fields;
+ $struct .= " end;\n";
+ if (($struct_type) && ($struct_name != $struct_type)) {
+ $struct .= "$struct_type = $struct_name;\n";
+ // SEE NOTE BELOW
+ //$struct .= $struct_type."Pointer = ^$struct_type;\n";
+ $make_pointer = false;
+ }
+
+ // make an extra pointer for us since Pascal may need it
+ // NOTE: remove this until we can protect against duplicate types
+ //if ($make_pointer) $struct .= $struct_name."Pointer = ^$struct_name;\n";
+
+ $this->dump[$file_name]["types"]["structs"][] = $struct;
+ $this->dump["global_structs"][] = $struct_name;
+ $got_struct = false;
+ $field_bitpacked = false;
+ }
+ }
+
+
+ // got struct
+ if (ereg("^typedef struct(.*){", $line, $captures)) {
+
+ $struct_name = trim($captures[1], " ");
+ $struct_type = null;
+ $struct_fields = "";
+
+ $make_pointer = false;
+ $got_struct = true;
+ }
+
+ // integer #define
+ if (ereg("#define[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([0-9.]+)", $line, $captures)) {
+ $this->dump[$file_name]["types"]["defines"][] = $captures[1]." = ".$captures[2].";";
+ }
+
+ // parse enum fields
+ if (($got_enum) || ($got_named_enum)) {
+ //print($line."\n");
+
+ // insert macros
+ //if ($macro = $this->InsertMacroBlocks($line, $this->inside_macro_block)) $this->dump[$file_name]["types"]["enums"][$block_count][] = $macro;
+
+ if (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*=[[:space:]]*([a-zA-Z_]+)[,]*[[:space:]]*$", $line, $captures)) { // string value
+ $captures[2] = trim($captures[2], ", ");
+ $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$captures[2].";";
+ } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*=[[:space:]]*([0-9-]+)[,]*[[:space:]]*$", $line, $captures)) { // integer value
+ $captures[2] = trim($captures[2], ", ");
+ $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$captures[2].";";
+ } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*=[[:space:]]*([0-9]+[xX]+[a-fA-F0-9]+)", $line, $captures)) { // hexadecimal value
+ $captures[2] = trim($captures[2], ", ");
+ $captures[2] = eregi_replace("^0x", "$", $captures[2]);
+ $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$captures[2].";";
+ } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*=[[:space:]]*([0-9]+[[:space:]]*<<[[:space:]]*[0-9]+)", $line, $captures)) { // << shl value, no ()
+ $captures[2] = str_replace("<<", " shl ", $captures[2]);
+ $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$captures[2].";";
+ } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*=[[:space:]]*\(([0-9]+[[:space:]]*<<[[:space:]]*[0-9]+)\)", $line, $captures)) { // << shl value
+ $captures[2] = trim($captures[2], ", ");
+ $captures[2] = str_replace("<<", " shl ", $captures[2]);
+ $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$captures[2].";";
+ } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*[,}]*[[:space:]]*$", $line, $captures)) { // non-value
+
+ // omit lines which started nested structures.
+ // bad practice but the single-line regex parser can't handle them
+ if (!eregi("[=|]+", $line)) {
+ $captures[1] = trim($captures[1], ", ");
+ $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$auto_increment.";";
+ $auto_increment ++;
+ }
+ }
+
+ // found the end
+ if (ereg("^};", $line)) $got_enum = false;
+ }
+
+ // ==== got enum ===
+ if (ereg("^enum {", $line)) {
+ $got_enum = true;
+ $block_count ++;
+ $auto_increment = 0;
+ }
+
+ // terminate named enum
+ if ($got_named_enum) {
+ if (ereg("^}[[:space:]]*([a-zA-Z0-9_]+);", $line, $captures)) {
+ $got_named_enum = false;
+
+ $named_enum = trim($named_enum, ", \n");
+
+ $this->dump[$file_name]["types"]["named_enums"][] = "$captures[1] = culong;";
+ $this->dump["global_types"][$captures[1]] = $captures[1];
+ }
+ }
+
+ // ==== got named enum ===
+ if (ereg("^typedef enum {", $line)) {
+ $got_named_enum = true;
+ $named_enum = "";
+ $auto_increment = 0;
+ $block_count ++;
+ }
+
+ // ==== external string constant ===
+ if (eregi("^($this->external_string_macros)+[[:space:]]+NSString[[:space:]]+\*[[:space:]]*(const)*[[:space:]]*([a-zA-Z_]+);", $line, $captures)) {
+ $name = $captures[3];
+
+ if (in_array($name, $this->ignore_symbol)) continue;
+
+ $this->dump[$file_name]["types"]["string_constant"][] = "$name: $this->string_macro; external name '_$name';";
+ }
+
+ // ==== external symbol ===
+ if (eregi("^($this->external_string_macros)+[[:space:]]+([a-zA-Z_ ]+)[[:space:]]+([a-zA-Z_]+);", $line, $captures)) {
+ $name = $captures[3];
+ $type = $captures[2];
+
+ // ignore symbols
+ if (in_array($name, $this->ignore_symbol)) continue;
+
+ $type = istr_replace_word("const", "", $type);
+ $type = trim($type, " ");
+
+ $this->dump[$file_name]["types"]["external_symbol"][] = "$name: $type; external name '_$name';";
+ }
+
+
+ // ==== external procedures ===
+ if (ereg("^($this->external_string_macros)+[[:space:]]+(.*)[[:space:]]+(\*)*([a-zA-Z0-9_]+)\((.*)\)", $line, $captures)) {
+
+ $result = $this->ConvertReturnType($captures[2]);
+ $name = $captures[4];
+ $params = "";
+ $captures[2] = trim($captures[2], " ");
+ $captures[5] = trim($captures[5], " ");
+
+ // ignore symbols
+ if (in_array($name, $this->ignore_symbol)) continue;
+
+ if ($captures[5] != "void") $params = "(".$this->ConvertCParamsPascal($captures[5]).")";
+
+ if ($captures[2] == "void") {
+ $this->dump[$file_name]["types"]["functions"][] = "procedure $name$params; cdecl; external name '$name';";
+ } else {
+ $this->dump[$file_name]["types"]["functions"][] = "function $name$params: $result; cdecl; external name '$name';";
+ }
+ }
+
+ // ==== got typedef ===
+ if (ereg("^typedef[[:space:]]+struct[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_]+);", $line, $captures)) { // defined struct type
+ $real_type = $captures[1];
+ $struct_type = $captures[1];
+ $new_type = $captures[2];
+
+ $this->AddTypeDef($this->dump[$file_name], "$struct_type = Pointer;");
+
+ $struct_type = $this->ReplaceObjcType($struct_type);
+ $struct_type = $this->SwapObjcTypeWithReal($struct_type);
+ $this->AddTypeDef($this->dump[$file_name], "$new_type = $struct_type;");
+
+ $this->dump["global_types"][$struct_type] = "Pointer";
+ $this->dump["global_types"][$new_type] = $real_type;
+ } elseif (ereg("^typedef[[:space:]]+struct[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_*]+);", $line, $captures)) { // pointer to struct
+ $real_type = $captures[1];
+ $clean_name = trim($captures[2], "*");
+ $pointer_type = $captures[1];
+
+ // ??? maybe check to see if this type exists like NSRect *NSRect is NSRectPointer which exists
+ $pointer_type = "Pointer";
+
+ //$captures[2] = $this->FormatObjcType($captures[2], $modifiers);
+ //$this->dump[$file_name]["types"]["typedef"][] = "$pointer_type = Pointer;";
+ $this->AddTypeDef($this->dump[$file_name], "$clean_name = $pointer_type;");
+
+
+ //$this->dump["global_types"][$pointer_type] = "Pointer";
+ $this->dump["global_types"][$clean_name] = $real_type;
+ } elseif (ereg("^typedef[[:space:]]+(const)*[[:space:]]*struct[[:space:]]+([a-zA-Z0-9_*]+)[[:space:]]+([a-zA-Z0-9_]+);", $line, $captures)) { // struct type (complex)
+ $real_type = $captures[1];
+
+ $captures[2] = $this->FormatObjcType($captures[2], $modifiers);
+ $this->AddTypeDef($this->dump[$file_name], $captures[3]." = ".$captures[2].";");
+
+ $this->dump["global_types"][$captures[3]] = $real_type;
+ } elseif (ereg("^typedef[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_*]+);", $line, $captures)) { // single-word type
+ $real_type = $captures[1];
+
+ // type is a pointer
+ if ($captures[2][0] == "*") {
+ $captures[2] = trim($captures[2], "*");
+ $captures[1] = $this->ReplaceObjcType($captures[1]);
+ $captures[1] = $this->SwapObjcTypeWithReal($captures[1]);
+ $this->AddTypeDef($this->dump[$file_name], $captures[2]." = ^".$captures[1].";");
+
+ $this->dump["global_types"][$captures[2]] = $real_type;
+ } else {
+ $captures[2] = trim($captures[2], "*");
+ $captures[1] = $this->ReplaceObjcType($captures[1]);
+ $captures[1] = $this->SwapObjcTypeWithReal($captures[1]);
+ $this->AddTypeDef($this->dump[$file_name],$captures[2]." = ".$captures[1].";");
+
+ $this->dump["global_types"][$captures[2]] = $real_type;
+ }
+ } elseif (ereg("^typedef[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_*]+);", $line, $captures)) { // double-word type
+ $real_type = $captures[1];
+
+ $captures[3] = trim($captures[3], "*");
+ $long_type = $captures[1]." ".$captures[2];
+ $long_type = $this->ReplaceObjcType($long_type);
+ $long_type = $this->SwapObjcTypeWithReal($long_type);
+ $this->AddTypeDef($this->dump[$file_name], $captures[3]." = $long_type;");
+
+ $this->dump["global_types"][$captures[3]] = $real_type;
+ }
+ }
+
+ //print_r($this->dump[$file_name]["types"]);
+ }
+
+ // Parse all protocols in a header
+ function ParseHeaderProtocols ($file) {
+ $contents = ReadTextFile($file);
+ $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
+
+ $lines = explode("\n", $contents);
+ foreach ($lines as $line) {
+
+ // parse protocol
+ if ($got_protocol) {
+
+ // remove comments
+ $line = $this->RemoveComments($line);
+
+ // found property
+ if (eregi($this->regex_objc_property, $line, $captures)) {
+ $property = $this->ParseClassProperty($current_protocol, $captures);
+
+ if ($property["setter"]) {
+ $this->current_header["protocols"][$current_protocol]["methods"][$method["objc_method"]] = $property["setter"];
+ }
+
+ if ($property["getter"]) {
+ $this->current_header["protocols"][$current_protocol]["methods"][$method["objc_method"]] = $property["getter"];
+ }
+
+ continue;
+ }
+
+ // found method
+ $method = null;
+ if (eregi($this->regex_objc_method_params, $line, $captures)) {
+ $method = $this->ConvertObjcMethodToPascal($current_protocol, $line, $captures, array(), true);
+ } elseif (eregi($this->regex_objc_method_no_params, $line, $captures)) {
+ $method = $this->ConvertObjcMethodToPascal($current_protocol, $line, $captures, array(), false);
+ }
+
+ // append to classes
+ if (($method) && (!in_array($current_protocol, $this->ignore_categories)) && (!in_array($method["name"], $this->ignore_methods)) ) {
+ $this->current_header["protocols"][$current_protocol]["methods"][$method["objc_method"]] = $method;
+ }
+
+ // found the end
+ if (ereg("^@end", $line)) $got_protocol = false;
+ }
+
+ // got protocol
+ if ((eregi($this->regex_objc_protocol, $line, $captures)) && (!eregi(".*;$", $line))) {
+ $got_protocol = true;
+ $current_protocol = $captures[1];
+ print("+ Protocol $current_protocol\n");
+ $this->current_header["protocols"][$current_protocol]["name"] = $captures[1];
+ }
+ }
+
+ //print_r($this->current_class);
+ }
+
+
+ // Parse all categories in a header
+ function ParseHeaderCategories ($file) {
+ $contents = ReadTextFile($file);
+ $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
+
+ $lines = explode("\n", $contents);
+ foreach ($lines as $line) {
+
+ // parse category
+ if ($got_category) {
+
+ // remove comments
+ $line = $this->RemoveComments($line);
+
+ // found property
+ if (eregi($this->regex_objc_property, $line, $captures)) {
+ $property = $this->ParseClassProperty($current_category, $captures);
+
+ if ($property["setter"]) {
+ if ($this->AddMethodToClass($property["setter"], $this->current_class)) {
+ $this->dump[$category_owner]["classes"][$current_class]["categories"][$current_category]["methods"][] = $property["setter"];
+ }
+ }
+
+ if ($property["getter"]) {
+ if ($this->AddMethodToClass($property["getter"], $this->current_class)) {
+ $this->dump[$category_owner]["classes"][$current_class]["categories"][$current_category]["methods"][] = $property["getter"];
+ }
+ }
+
+ continue;
+ }
+
+ // found method
+ $method = null;
+ if (eregi($this->regex_objc_method_params, $line, $captures)) {
+ $method = $this->ConvertObjcMethodToPascal($current_category, $line, $captures, $this->GetProtectedKeywords($this->current_class), true);
+ } elseif (eregi($this->regex_objc_method_no_params, $line, $captures)) {
+ $method = $this->ConvertObjcMethodToPascal($current_category, $line, $captures, $this->GetProtectedKeywords($this->current_class), false);
+ }
+
+ // append to classes
+ if (($method) && (!in_array($method["name"], $this->ignore_categories))) {
+ if ($current_class) {
+ if ($this->AddMethodToClass($method, $this->current_class)) {
+ $this->dump[$category_owner]["classes"][$current_class]["categories"][$current_category]["methods"][] = $method;
+ }
+ } else {
+
+ // add base categories to NSObject
+ if (in_array($current_category, $this->base_categories)) {
+ if ($this->AddMethodToClass($method, $this->dump["NSObject.h"]["classes"]["NSObject"])) {
+ $this->dump["NSObject.h"]["classes"]["NSObject"]["categories"][$current_category]["methods"][] = $method;
+ }
+ }
+
+ $this->dump["categories"][$current_category]["methods"][$method["objc_method"]] = $method;
+ }
+ }
+
+ // found the end
+ if (ereg("^@end", $line)) $got_category = false;
+ }
+
+ // got category
+ if (eregi($this->regex_objc_category, $line, $captures)) {
+
+ // ??? if the current header is NSObject, then we DO want to accept these categories, they are NOT delegates this time...
+
+ // append category to it's super class
+ $category_owner = $this->FindCategoryHeader($captures[1]);
+ if (($category_owner) && ($captures[1] != "NSObject")) {
+ $got_category = true;
+ $current_category = $captures[2];
+ $current_class = $captures[1];
+ $this->current_class = &$this->dump[$category_owner]["classes"][$current_class];
+
+ $this->dump[$category_owner]["classes"][$current_class]["categories"][$current_category]["name"] = $captures[2];
+ $this->dump[$category_owner]["classes"][$current_class]["categories"][$current_category]["super"] = $captures[1];
+
+ print(" -> Category $current_category belongs to $current_class in $category_owner\n");
+ } else {
+
+ if ($captures[1] == "NSObject") {
+ print(" + Category ".$captures[2]."->".$captures[1]." belongs to NSObject\n");
+ $got_category = true;
+ } else {
+ $this->warning_count ++;
+ print("# WARNING: Category ".$captures[2]." (".$captures[1].") has no header\n");
+ $got_category = false;
+ }
+
+ $current_category = $captures[2];
+ $current_class = null;
+
+ $this->dump["categories"][$current_category]["name"] = $captures[2];
+ $this->dump["categories"][$current_category]["super"] = $captures[1];
+ }
+
+ }
+ }
+
+ //print_r($this->current_class);
+ }
+
+ // Parse all "pre-defined" category methods in a header
+ function PreparseCategoryMethods ($file) {
+ $contents = ReadTextFile($file);
+ $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
+
+ $lines = explode("\n", $contents);
+ foreach ($lines as $line) {
+
+ // parse category
+ if ($got_category) {
+
+ // found method
+ $method = null;
+ if (eregi($this->regex_objc_method_params, $line, $captures)) {
+ $method = $this->ConvertObjcMethodToPascal($current_category, $line, $captures, array(), true);
+ } elseif (eregi($this->regex_objc_method_no_params, $line, $captures)) {
+ $method = $this->ConvertObjcMethodToPascal($current_category, $line, $captures, array(), false);
+ }
+
+ // append to classes
+ if (($method) && ($current_class)) {
+ $this->dump[$category_owner]["category_methods"][] = $method["name"];
+ //print($method["name"]."\n");
+ }
+
+ // found the end
+ if (ereg("^@end", $line)) $got_category = false;
+ }
+
+ // got category
+ if (eregi($this->regex_objc_category, $line, $captures)) {
+ $category_owner = $this->FindCategoryHeader($captures[1]);
+ if ($category_owner) {
+ $got_category = true;
+ $current_category = $captures[2];
+ $current_class = $captures[1];
+ } else {
+ $current_class = null;
+ }
+ }
+ }
+
+ return $this->dump[$category_owner]["category_methods"];
+ }
+
+ // Preparses a class for protected keywords
+ function PreparseClass ($lines, $line_count) {
+ $protected_keywords = array();
+
+ for ($i=$line_count; $i < count($lines); $i++) {
+ $line = $lines[$i - 1];
+
+ // found method
+ if (eregi($this->regex_objc_method_params, $line, $captures)) {
+ $method = $this->ConvertObjcMethodToPascal($current, $line, $captures, $protected_keywords, true);
+ $this->current_class["protected_keywords"][] = $method["name"];
+ } elseif (eregi($this->regex_objc_method_no_params, $line, $captures)) {
+ $method = $this->ConvertObjcMethodToPascal($current, $line, $captures, $protected_keywords, false);
+ $this->current_class["protected_keywords"][] = $method["name"];
+ }
+
+ // class ended
+ if (ereg("^@end", $line)) return $protected_keywords;
+ }
+ }
+
+ // Gets the preferred property name from attributes
+ function GetPropertyName ($kind, $params, &$name) {
+ foreach ($params as $value) {
+ $pair = explode("=", $value);
+
+ if ($pair[0] == $kind) {
+ $name = $pair[1];
+ return true;
+ break;
+ }
+ }
+ }
+
+ // Convert a method return type to Pascal
+ function ConvertReturnType ($type) {
+ $type = trim($type, " ");
+ $type = $this->ReplaceObjcType($type);
+
+ // if the type was not converted remove the * and process further
+ $type = trim($type, "* ");
+ $type = $this->ReplaceObjcType($type);
+
+ // format the return type again to make sure it's clean
+ $type = $this->FormatObjcType($type, $null_modifier);
+
+ return $type;
+ }
+
+ // Parse a property into accessor methods
+ function ParseClassProperty ($class, $parts) {
+ $property["parameters"] = explode(",", $parts[1]);
+ $method = array();
+
+ // property name
+ if (eregi("([a-zA-Z0-9]+)$", $parts[2], $captures)) $property["name"] = ucwords($captures[1]);
+
+ // property type
+ $type = istr_replace_word($captures[1], "", $parts[2]);
+ $type = $this->ConvertReturnType($type);
+
+ // setter
+ if (!in_array("readonly", $property["parameters"])) {
+ $method["setter"] = array();
+
+ $name = $property["name"];
+ if (!$this->GetPropertyName("setter", $property["parameters"], $name)) {
+ $name = "set$name";
+ }
+
+ // protect method name from keywords
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+
+ $method["setter"]["def"] = "procedure $name (newValue: $type);";
+ $method["setter"]["objc_method"] = "$name:";
+ $method["setter"]["class"] = $class;
+ $method["setter"]["name"] = $name;
+ $method["setter"]["kind"] = "procedure";
+ }
+
+ // getter
+ $method["getter"] = array();
+
+ $name = $property["name"];
+ if (!$this->GetPropertyName("getter", $property["parameters"], $name)) {
+ $name = strtolower(substr($name, 0, 1)) . substr($name, 1);
+ }
+
+ // protect method name from keywords
+ if ($this->IsKeywordReserved($name)) $name .= "_";
+
+ $method["getter"]["def"] = "function $name: $type;";
+ $method["getter"]["objc_method"] = $name;
+ $method["getter"]["class"] = $class;
+ $method["getter"]["name"] = $name;
+ $method["getter"]["kind"] = "function";
+
+ return $method;
+ }
+
+ // Main entry to parse a header
+ function ParseHeaderClasses ($file) {
+ $contents = ReadTextFile($file);
+
+ $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
+ $line_count = 0;
+
+ $lines = explode("\n", $contents);
+ foreach ($lines as $line) {
+ $line_count++;
+
+ // remove external class macros
+ $line = eregi_replace("^[A-Z0-9]+_EXTERN_CLASS[[:space:]]+", "", $line);
+
+ // parse instance vars
+ if ($got_instance_vars) {
+
+ // scope compiler directive
+ if (eregi($this->regex_scope_compiler_directive, $line, $captures)) {
+ $this->instance_var_scope = $captures[1];
+ continue;
+ }
+
+ // remove comments
+ $line = $this->RemoveComments($line);
+
+ // parse instance variables
+ $result = $this->ParseInstanceVariables($line, $struct);
+
+ // parse structures
+ if ($result == "struct") {
+ //print_r($struct);
+ //$this->dump[$file_name]["classes"][$current]["ivars"][] = $struct["name"].": $current"."_".$struct["name"].";";
+ $this->dump[$file_name]["classes"][$current]["ivars_structs"][] = $struct;
+
+ // print inline-record type
+ if ($struct["bitpacked"]) {
+ $this->dump[$file_name]["classes"][$current]["ivars"][] = $struct["name"].": ".$this->bitpacked_record_keyword;
+ } else {
+ $this->dump[$file_name]["classes"][$current]["ivars"][] = $struct["name"].": ".$this->record_keyword;
+ }
+
+
+ // print fields
+ if ($struct["fields"]) {
+ foreach ($struct["fields"] as $field) $this->dump[$file_name]["classes"][$current]["ivars"][] = " ".$field;
+ }
+ $this->dump[$file_name]["classes"][$current]["ivars"][] = " end;";
+
+ $struct = null;
+ } elseif($result != null) {
+ //print($result);
+ $this->dump[$file_name]["classes"][$current]["ivars"][] = $result;
+ }
+
+ // instance var section terminated.
+ if (eregi("^\s*}\s*$", $line)) {
+ $struct = null;
+ $got_instance_vars = false;
+ $this->instance_var_scope = null;
+ }
+
+ } elseif ($got_class) { // parse the class
+
+ // the instance variable section started after the class line and no other ivar's were parsed yet
+ if (!$this->dump[$file_name]["classes"][$current]["ivars"]) {
+ if (eregi("{\s*$", $line)) {
+ $got_instance_vars = true;
+ continue;
+ }
+ }
+
+ // remove comments
+ $line = $this->RemoveComments($line);
+
+ // found property
+ if (eregi($this->regex_objc_property, $line, $captures)) {
+ $property = $this->ParseClassProperty($current, $captures);
+
+ if ($property["setter"]) {
+ if ($this->AddMethodToClass($property["setter"], $this->dump[$file_name]["classes"][$current])) {
+ $this->dump[$file_name]["classes"][$current]["methods"][] = $property["setter"];
+ }
+ }
+
+ if ($property["getter"]) {
+ if ($this->AddMethodToClass($property["getter"], $this->dump[$file_name]["classes"][$current])) {
+ $this->dump[$file_name]["classes"][$current]["methods"][] = $property["getter"];
+ }
+ }
+
+ continue;
+ }
+
+ // found method
+ if (eregi($this->regex_objc_method_params, $line, $captures)) {
+ $method = $this->ConvertObjcMethodToPascal($current, $line, $captures, $this->GetProtectedKeywords($this->current_class), true);
+ if ($this->AddMethodToClass($method, $this->dump[$file_name]["classes"][$current])) {
+ $this->dump[$file_name]["classes"][$current]["methods"][] = $method;
+ }
+
+ } elseif (eregi($this->regex_objc_method_no_params, $line, $captures)) {
+ $method = $this->ConvertObjcMethodToPascal($current, $line, $captures, $this->GetProtectedKeywords($this->current_class), false);
+ if ($this->AddMethodToClass($method, $this->dump[$file_name]["classes"][$current])) {
+ $this->dump[$file_name]["classes"][$current]["methods"][] = $method;
+ }
+ }
+
+ // found the end
+ if (ereg("^@end", $line)) $got_class = false;
+ }
+
+ // ==== got class ====
+ if ((eregi($this->regex_objc_class, $line, $captures)) || (eregi($this->regex_objc_class_no_super, $line, $captures))) {
+ $current = $captures[1];
+ $got_class = true;
+
+ // check for instance variable section
+ if (eregi("{\s*$", $line)) $got_instance_vars = true;
+
+ // get the protocol which the class conforms to
+ if (eregi($this->regex_objc_class, $line, $captures)) {
+ if ($captures[3]) $this->dump[$file_name]["classes"][$current]["conforms"] = $captures[3];
+ } else {
+ if ($captures[2]) $this->dump[$file_name]["classes"][$current]["conforms"] = $captures[2];
+ }
+
+ // clean up the conforms string
+ if ($this->dump[$file_name]["classes"][$current]["conforms"]) {
+ $conform_protocols = explode(",", $this->dump[$file_name]["classes"][$current]["conforms"]);
+
+ foreach ($conform_protocols as $protocol) {
+ $protocol = trim($protocol, "<> ");
+ $protocol_clean .= $protocol."$this->protocol_suffix, ";
+ }
+
+ $protocol_clean = trim($protocol_clean, ", ");
+ $this->dump[$file_name]["classes"][$current]["conforms"] = $protocol_clean;
+
+ $protocol_clean = "";
+ }
+
+ $this->dump[$file_name]["classes"][$current]["name"] = $captures[1];
+ $this->dump[$file_name]["classes"][$current]["super"] = $captures[2];
+ $this->dump[$file_name]["classes"][$current]["super_class"] = &$this->dump["master"][$captures[2]];
+ $this->dump[$file_name]["classes"][$current]["file_name"] = $file_name;
+ $this->dump[$file_name]["classes"][$current]["file_clean"] = substr($file_name, 0, (strripos($file_name, ".")));
+ $this->dump[$file_name]["classes"][$current]["protected_keywords"] = array();
+ $this->dump[$file_name]["classes"][$current]["declared_methods"] = array();
+ $this->dump[$file_name]["category_methods"] = array();
+
+ $this->current_class = &$this->dump[$file_name]["classes"][$current];
+
+ // append master class listing
+ $this->dump["master"][$current] = &$this->dump[$file_name]["classes"][$current];
+
+ // preparse for protected keywords
+ $this->PreparseClass($lines, $line_count);
+
+ // preparse for category methods that may present naming conflicts
+ $category_methods = $this->PreparseCategoryMethods($file);
+
+ // add category methods to protected keywords
+ if ($category_methods) $this->current_class["protected_keywords"] = array_merge($this->current_class["protected_keywords"], $category_methods);
+
+ // print class hierarchy
+ if ($this->show_class_hierarchy) {
+ $this->GetClassHierarchy($this->current_class, $hierarchy);
+ $hierarchy_string = "";
+ foreach ($hierarchy as $value) {
+ $hierarchy_string .= "$value->";
+ }
+ $hierarchy_string = trim($hierarchy_string, "->");
+ print(" - $current: $hierarchy_string\n");
+ }
+
+ $this->class_count ++;
+ //print_r($this->dump[$file_name]["classes"][$current]);
+ }
+
+ }
+
+ //print_r($this->dump[$file_name]["classes"][$current]);
+ }
+
+ // Parse categories which depend on another header
+ function ParseHeaderDependents ($file) {
+ $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
+
+ $this->ParseHeaderCategories($file);
+
+ print("+ Parsed $file_name for dependents\n");
+ }
+
+
+ // Main entry to parse a header
+ function ParseHeader ($file) {
+ $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
+ $name_clean = substr($file_name, 0, (strripos($file_name, ".")));
+
+ // get framework we're parsing from
+ if (eregi("/([a-zA-Z]+)\.framework/", $file, $captures)) $this->framework = strtolower($captures[1]);
+
+ // get the output path
+ $this->dump[$file_name]["path"] = "$this->root$this->out/$this->framework/$name_clean.inc";
+ $this->dump[$file_name]["path_partial"] = "$this->framework/$name_clean.inc";
+ $this->dump[$file_name]["framework"] = $this->framework;
+ $this->dump[$file_name]["name"] = $file_name;
+ $this->dump[$file_name]["name_clean"] = $name_clean;
+ $this->current_header = &$this->dump[$file_name];
+
+ $this->ParseHeaderProtocols($file);
+ $this->ParseHeaderClasses($file);
+ $this->ParseHeaderTypes($file);
+
+ print("+ Parsed $file_name\n");
+ }
+
+ // Parse all AppKit and Foundation framework headers
+ function ParseCocoaFrameworks ($ignore_files, $parse_only) {
+
+ foreach ($this->frameworks as $framework_name => $framework_info) {
+
+ // framework is disabled
+ if ($framework_info["enabled"] != 1) continue;
+
+ if ($this->out != "/") {
+ $path = $this->root.$this->out."/".$framework_info["root"];
+ } else {
+ $path = $this->root.$framework_info["root"];
+ }
+
+ $contents = ReadTextFile($path);
+ $lines = explode("\n", $contents);
+
+ foreach ($lines as $line) {
+ if (eregi($framework_info["include_pattern"], $line, $captures)) {
+ $header = $captures[1].".h";
+ $path = $framework_info["headers"]."/$header";
+
+ // main header
+ if ($parse_only) {
+ if (@in_array($header, $parse_only)) $this->ParseHeader($path);
+ } elseif (@!in_array($header, $ignore_files)) {
+ $this->ParseHeader($path);
+ }
+
+ // header dependents
+ if ($parse_only) {
+ if (@in_array($header, $parse_only)) $this->ParseHeaderDependents($path);
+ } elseif (@!in_array($header, $ignore_files)) {
+ $this->ParseHeaderDependents($path);
+ }
+ }
+ }
+
+ }
+
+ // diagnostics
+ print("\n• Parsed $this->method_count methods in $this->class_count classes.\n\n");
+
+ if ($this->warning_count > 0) print("• $this->warning_count warnings were encountered.\n\n");
+ }
+
+ // Parse headers in a system framework
+ function ParseFramework ($ignore_files, $parse_only) {
+ }
+
+ // Parses XML file generated by GEN_BRIDGE_METADATA -f /System/Library/Frameworks/AppKit.framework/
+ function ParseBridgeSupportXML ($file, $categories) {
+ $contents = ReadTextFile($file);
+
+ $lines = explode("\n", $contents);
+ foreach ($lines as $line) {
+
+ if ($got_informal_protocol) {
+
+ if (eregi("<method type='(.*)' selector='(.*)'/>", $line, $captures)) {
+
+ $set["name"] = $captures[2];
+ $set["name_pascal"] = str_replace(":", "_", $set["name"]);
+ $set["name_pascal"] = rtrim($set["name_pascal"], "_");
+ $set["types"] = $captures[1];
+ $set["param_string"] = $categories[$informal_protocol]["methods"][$captures[2]]["param_string"];
+ $set["method"] = &$categories[$informal_protocol]["methods"][$captures[2]];
+
+ if ($captures[1][0] == "v") {
+ $set["kind"] = "procedure";
+ } else {
+ $set["kind"] = "function";
+ }
+
+ // add the selector if the name isn't reserved for Pascal
+ if ((!in_array($set["name_pascal"], $this->reserved_keywords)) && (!in_array($set["name_pascal"], $this->reserved_methods))) {
+ $this->delegate_methods[$informal_protocol][] = $set;
+ $this->delegate_method_names[] = $set["name_pascal"];
+ }
+ }
+
+ // end tag
+ if ($line == "</informal_protocol>") $got_informal_protocol = false;
+ }
+
+ // got informal_protocol
+ if (eregi("<informal_protocol name='(.*)'>", $line, $captures)) {
+ $informal_protocol = $captures[1];
+ //print("\"$informal_protocol\", ");
+ $got_informal_protocol = true;
+ }
+ }
+
+ print("+ Parsed bridge support XMl file at $file\n");
+ //print_r($this->delegate_methods);
+ }
+
+ // Parse all classes/categories (non-delegate) from the header
+ function ParseAllHeaderClasses ($file) {
+ $contents = ReadTextFile($file);
+
+ $lines = explode("\n", $contents);
+ foreach ($lines as $line) {
+
+ // remove external class macros
+ $line = eregi_replace("^[A-Z0-9]+_EXTERN_CLASS[[:space:]]+", "", $line);
+
+ // classes
+ if (eregi($this->regex_objc_class, $line, $captures)) $this->cocoa_classes[] = $captures[1];
+ if (eregi($this->regex_objc_class_no_super, $line, $captures)) $this->cocoa_classes[] = $captures[1];
+
+ // categories
+ if (eregi($this->regex_objc_category, $line, $captures)) {
+ $this->cocoa_categories[] = $captures[1];
+ }
+ }
+ }
+
+ // Build array of all known Cocoa classes in frameworks
+ function BuildCocoaClasses () {
+
+ foreach ($this->frameworks as $framework_name => $framework_info) {
+
+ // framework is disabled
+ if ($framework_info["enabled"] != 1) continue;
+
+ $handle = opendir($framework_info["headers"]);
+ while (($file = readdir($handle)) !== false) {
+ if (eregi($framework_info["header_pattern"], $file)) {
+ $this->ParseAllHeaderClasses($framework_info["headers"]."/$file");
+ }
+ }
+ closedir($handle);
+ }
+ }
+
+ function ProcessFile ($file, $print) {
+ $this->ParseHeader($file);
+ $this->ParseHeaderDependents($file);
+
+ if ($print) $this->PrintAllHeaders("", null, null, false);
+ }
+
+ function ParseDelegateClasses () {
+
+ foreach ($this->frameworks as $framework_name => $framework_info) {
+
+ // framework is disabled
+ if ($framework_info["enabled"] != 1) continue;
+
+ $this->ParseBridgeSupportXML("$this->root".$framework_info["bridge"], $this->dump["categories"]);
+ }
+
+ // These are expressions which match valid class names or the names themself
+ $delegate_categories = array( "(Delegation|Delegate|Notification|DataSource|Handler)+",
+ "NSDraggingDestination", "NSDistantObjectRequestMethods", "NSDraggingSource",
+ "NSEditorRegistration", "NSFileManagerFileOperationAdditions", "NSPasteboardOwner",
+ );
+
+ $this->output = fopen("$this->root$this->out/foundation/$this->master_delegate_file.inc", "w+");
+ $this->PrintDelegateClass($delegate_categories);
+ fclose($this->output);
+
+ $this->output = fopen("$this->root$this->out/$this->master_delegate_file.pas", "w+");
+ $this->PrintDelegateReference($delegate_categories);
+ fclose($this->output);
+ }
+
+ function LoadTypeEncodings ($name) {
+ $contents = ReadTextFile("$this->root/$name");
+
+ $lines = explode("\n", $contents);
+ foreach ($lines as $line) {
+ $row = explode("|", $line);
+
+ $this->type_encodings[$row[0]][$row[1]] = $row[2];
+ }
+
+ //print_r($this->type_encodings);
+ }
+
+ // Prints out code to generate type encodings with GenerateTypeEncodings.p
+ // Paste the output of the function into GenerateTypeEncodings.p, run the program and save the output into a text file
+ // which is loaded into this script.
+ function PrintTypeEncodingGlue () {
+ $count = 0;
+ $block = true;
+ $block_count = 1;
+ $limit = 2000;
+
+ foreach ($this->dump["all_methods"] as $class => $method) {
+ foreach ($method as $name) {
+
+ if ($count == 0) {
+ print("\n");
+ print("procedure PrintGlue$block_count;\n");
+ print("begin\n");
+
+ $block_count ++;
+ }
+
+ $count ++;
+
+ print("aMethod := class_getInstanceMethod(objc_getClass('$class'), sel_registerName(PChar('$name')));\n");
+ print("if aMethod <> nil then\n");
+ print("writeln('$class|$name|', method_getTypeEncoding(aMethod));\n");
+
+ if ($count == $limit) {
+ print("end;\n");
+ $count = 0;
+ }
+ }
+ }
+
+ if ($count < $limit) {
+ print("end;\n");
+ $block_count --;
+ }
+
+ print("\n========= IMPLEMENTATION =========\n");
+ for ($i=1; $i < $block_count + 1; $i++) {
+ print("PrintGlue$i;\n");
+ }
+ }
+
+ function __construct ($directory, $out_directory, $frameworks, $show) {
+ $this->root = $directory;
+ $this->out = $out_directory;
+ $this->show = $show;
+ if ($frameworks) {
+ foreach ($frameworks as $name) {
+ $this->frameworks[$name]["enabled"] = true;
+ }
+ }
+ $this->BuildCocoaClasses();
+ //$this->LoadTypeEncodings("TypeEncodingsAll.txt");
+ }
+}
+?> \ No newline at end of file
diff --git a/packages/cocoaint/utils/parser.php b/packages/cocoaint/utils/parser.php
index 9c43fdf7d5..b7418bbbd6 100755
--- a/packages/cocoaint/utils/parser.php
+++ b/packages/cocoaint/utils/parser.php
@@ -109,7 +109,7 @@ function HandleCommandLineOptions ($argv) {
}
// ??? TESTING
-$testing = true;
+$testing = false;
if ($testing) {
$GLOBALS["argv"][] = "-webkit";
@@ -236,7 +236,6 @@ if ($options["out"]) {
// setup -iphone options
if ($options["iphone"]) {
- if (!$root_path) $root_path .= "/units/i386-darwin/cocoaint/src";
$options["all"] = true;
$options["objp"] = true;
$options["frameworks"] = array("uikit");