pascocoa_parser.php 144 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163
  1. <?php
  2. function ReadTextFile ($path) {
  3. if ($handle = fopen($path, "r")) {
  4. return fread($handle, 400 * 1024);
  5. fclose($handle);
  6. }
  7. }
  8. function str_replace_word ($needle, $replacement, $haystack) {
  9. $pattern = "/\b$needle\b/";
  10. $haystack = preg_replace($pattern, $replacement, $haystack);
  11. return $haystack;
  12. }
  13. function istr_replace_word ($needle, $replacement, $haystack) {
  14. $pattern = "/\b$needle\b/i";
  15. $haystack = preg_replace($pattern, $replacement, $haystack);
  16. return $haystack;
  17. }
  18. define("CAST_HANDLE", true);
  19. define("DONT_CAST_HANDLE", false);
  20. define("ACCESS_HANDLE_DIRECT", 1);
  21. define("ACCESS_HANDLE_FUNCTION", 2);
  22. define("REGISTER_SEL", true);
  23. define("DONT_REGISTER_SEL", false);
  24. define("USE_HANDLE", true);
  25. define("DONT_USE_HANDLE", false);
  26. class TPasCocoaParser {
  27. // Frameworks to parse
  28. var $frameworks = array( "foundation" => array( "root" => "/foundation/Foundation.inc",
  29. "bridge" => "/bridgesupport/foundation.xml",
  30. "headers" => "/System/Library/Frameworks/Foundation.framework/Headers",
  31. "include_pattern" => "{[$]+include (NS.*).inc}",
  32. "header_pattern" => "^NS(.*)\.h",
  33. "enabled" => false,
  34. ),
  35. "appkit" => array( "root" => "/appkit/AppKit.inc",
  36. "bridge" => "/bridgesupport/appkit.xml",
  37. "headers" => "/System/Library/Frameworks/AppKit.framework/Headers",
  38. "include_pattern" => "{[$]+include (NS.*).inc}",
  39. "header_pattern" => "^NS(.*)\.h",
  40. "enabled" => false,
  41. ),
  42. "uikit" => array( "root" => "/uikit/UIKit.inc",
  43. "bridge" => "/bridgesupport/appkit.xml",
  44. //"headers" => "/Users/ryanjoseph/Desktop/iphone/UIKit.framework/Headers",
  45. "headers" => "/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/System/Library/Frameworks/UIKit.framework/Headers",
  46. "include_pattern" => "{[$]+include (UI.*).inc}",
  47. "header_pattern" => "^UI(.*)\.h",
  48. "enabled" => false,
  49. ),
  50. "webkit" => array( "root" => "/webkit/WebKit.inc",
  51. "bridge" => "/bridgesupport/webkit.xml",
  52. "headers" => "/System/Library/Frameworks/WebKit.framework/Headers",
  53. "include_pattern" => "{[$]+include (.*).inc}",
  54. "header_pattern" => "^(.*)\.h",
  55. "enabled" => false,
  56. ),
  57. "coredata" => array( "root" => "/coredata/CoreData.inc",
  58. "bridge" => "/bridgesupport/coredata.xml",
  59. "headers" => "/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/CoreData.framework/Headers",
  60. "include_pattern" => "{[$]+include (.*).inc}",
  61. "header_pattern" => "^(.*)\.h",
  62. "enabled" => false,
  63. ),
  64. );
  65. var $maximum_method_length = 111; // WE GET THIS ERROR: NSDelegatesAll.pas(6109,296) Error: Identifier not found "NSDelegateController_NSLayoutManagerDelegate_layoutManager_shouldUseTemporaryAttributes_forDrawingToScreen_atCharacterIndex_effectiveRange"
  66. var $output; // current output file handle
  67. var $root; // root for printing/locating resources
  68. var $out; // directory to print
  69. var $show; // print output to screen instead of file
  70. var $framework; // current framework being parsed
  71. var $current_class; // reference to current class structure being parsed
  72. var $current_header; // reference to current header structure being parsed
  73. var $method_count; // count of all methods parsed
  74. var $class_count; // count of all classes parsed
  75. var $warning_count; // count of parser warnings
  76. var $parser_skipping; // the parser is skipping lines in the current file
  77. var $inside_macro_block; // the parser is inside a macro block, no nesting!
  78. var $instance_var_scope; // current scope of the instance variable parser
  79. var $cocoa_classes = array(); // array of all NS*** classes
  80. var $cocoa_categories = array(); // array of all NS*** categories
  81. var $dump = array(); // Convert Pascal classes
  82. var $delegate_methods = array(); // Delegate methods and types from GEN_BRIDGE_METADATA XML data
  83. var $delegate_method_names = array(); // Delegate method name array
  84. var $type_encodings = array(); // Master listing of type encodings for each method in the frameworks
  85. /**
  86. * PARSER OPTIONS
  87. */
  88. var $objc_id = "NSObjectRef"; // Default type for generic objects
  89. var $objc_id_real = "NSObjectRef"; // The real type of generic objects (id)
  90. var $objc_id_base = "Pointer"; // The base type for all "Ref" types
  91. var $sel_string = "SELString"; // The selector string type which registers selectors internally
  92. var $protocol_suffix = "Protocol"; // All protocols append this suffix
  93. var $pointer_type_suffx = "Ref"; // NS*** pointers in parameter lists are suffixed with this
  94. var $class_pointer_suffix = "Pointer"; // Pointers to NS*** classes are suffxed with this
  95. var $register_selectors = true; // Register selectors automatically inside the wrappers
  96. var $show_added_messages = false; // show messages when methods are added to a class
  97. var $show_class_hierarchy = false;
  98. var $objects_are_wrappers = false; // Treat all objects (id) like wrappers. i.e aObject.Handle;
  99. var $replace_hinted_params = false; // replace comment hints with hinted type - (void * /* CMProfileRef */)colorSyncProfile;
  100. var $master_delegate_class = "NSDelegateController"; // Name of the master delegate class
  101. var $master_delegate_file = "NSDelegatesAll"; // Name of the master delegate file (no extension)
  102. var $trailing_underscore = false; // Append the trailing underscore for last parameter
  103. var $record_keyword = "record"; // The keyword used for printing records
  104. var $bitpacked_record_keyword = "bitpacked record"; // The keyword used for printing bitpacked records
  105. var $string_macro = "NSString";
  106. // Pascal keywords to protect
  107. var $reserved_keywords = array( "const", "object", "string", "array", "var", "set", "interface", "classname", "unit",
  108. "self", "type", "raise", "property", "to", "for", "with", "function", "procedure", "result",
  109. "pointer", "create", "new", "dispose", "label", "packed", "record", "char", "class",
  110. );
  111. // FPC methods that can't be overloaded
  112. var $reserved_methods = array("className");
  113. // Types which can not be altered by reserved keywords
  114. var $reserved_types = array("Pointer");
  115. // Objective-c types to convert
  116. var $replace_types = array( "id"=>"NSObjectRef", "void"=>"Pointer", "BOOL"=>"LongBool", "long"=>"LongInt", "int"=>"Integer",
  117. "unsigned long"=>"UInt32", "unsigned short"=>"UInt8", "void *"=>"Pointer", "unsigned int"=>"UInt16",
  118. "NSUInteger"=>"UInt32", "NSInteger"=>"SInt32", "Class"=>"Pobjc_class", "uint"=>"UInt16",
  119. "uint8_t"=>"UInt8", "signed int"=>"Integer", "const char"=>"PChar", "const void"=>"Pointer",
  120. "const uint8_t"=>"Pointer", "unsigned"=>"UInt8", "int32_t"=>"SInt32", "float"=>"Float32",
  121. "unsigned long long"=>"UInt64", "int64_t"=>"SInt64", "uint32_t"=>"UInt32", "uint16_t"=>"UInt16",
  122. "unsigned char"=>"char", "short"=>"SInt8", "double"=>"Float64", "long long"=>"SInt64",
  123. // macros
  124. "IBAction"=>"void",
  125. // special pointers
  126. "const id *"=>"NSObjectArrayOfObjectsPtr", "Protocol *"=>"ObjcProtocol", "NSObject *"=>"NSObjectRef",
  127. "const char *"=>"PChar", "const void *"=>"Pointer", "unsigned char *"=>"Pointer", "char *"=>"Pointer",
  128. "unsigned *"=>"Pointer",
  129. );
  130. // These "types" are hints to the Objective-C garbage collector
  131. var $garbage_collector_hints = array("__strong", "__weak");
  132. var $null_macros = array("IBOutlet", "IBAction");
  133. // External NSString macros. These should be moved into the frameworks array
  134. var $external_string_macros = "APPKIT_EXTERN|FOUNDATION_EXPORT|UIKIT_EXTERN|COREDATA_EXTERN";
  135. // Types which have known pointers declared in the headers
  136. var $pointer_types = array( // MacOSAll types
  137. "CGFloat"=>"psingle", "UInt32"=>"UInt32Ptr", "SInt32"=>"SInt32Ptr",
  138. // Cocoa types
  139. "BOOL"=>"pboolean",
  140. "unsigned char"=>"pchar",
  141. "unsigned short"=>"pcushort", "unsigned int"=>"pcuint", "uint"=>"pcuint", "signed int"=>"pcint",
  142. "float"=>"psingle", "double"=>"pdouble", "long long"=>"pclonglong","long"=>"pclong", "unsigned long"=>"pculong",
  143. "int"=>"pinteger","uint8_t"=>"pbyte","unsigned"=>"pbyte","unsigned long long"=>"pculonglong"
  144. );
  145. var $objc_object_array = "id; objParams: array of const"; // Type which represents a dynamic array of Objective-c objects (id)
  146. // Symbols to ignore
  147. var $ignore_symbol = array("NSApp");
  148. // Categories to ignore
  149. var $ignore_categories = array("NSCoderMethods", "NSDeprecatedKeyValueCoding", "NSDeprecated");
  150. // Methods to ignore
  151. var $ignore_methods = array( "retain", "release", "retainCount", "copyWithZone", "mutableCopyWithZone",
  152. "allocWithZone", "alloc", "copy", "mutableCopy", "self_", "autorelease", "awakeFromNib",
  153. "observationInfo",
  154. );
  155. // default protected keywords by class/category
  156. // these may be useful if super classes were not parsed before
  157. var $default_protected = array( "*"=>array("description", "classDescription"),
  158. "NSDeprecated"=>array("accessoryView"),
  159. "NSToolbarSupport"=>array("toolbar"),
  160. "DOMNode"=>array("version"),
  161. "WebView"=>array("frame"),
  162. "DOMImplementation"=>array("version"),
  163. );
  164. // Send methods that have a custom design
  165. var $custom_send_methods = array( "NSArray.arrayWithObjects", "NSArray.initWithObjects",
  166. "NSDictionary.dictionaryWithObjectsAndKeys", "NSDictionary.initWithObjectsAndKeys",
  167. "NSSet.setWithObjects", "NSSet.initWithObjects",
  168. );
  169. var $toll_free_bridge = array(
  170. "NSString"=>"CFStringRef", "NSArray"=>"CFArrayRef", "NSMutableString"=>"CFMutableStringRef",
  171. "NSData"=>"CFDataRef", "NSDictionary"=>"CFDictionaryRef", "NSSet"=>"CFSetRef",
  172. "NSMutableArray"=>"CFMutableArrayRef", "NSMutableCharacterSetRef"=>"CFMutableCharacterSetRef",
  173. "NSMutableData"=>"CFMutableDataRef", "NSMutableDictionary"=>"CFMutableDictionaryRef",
  174. "NSMutableSet"=>"CFMutableSetRef", "NSNumber"=>"CFNumberRef", "NSURL"=>"CFURLRef",
  175. "NSError"=>"CFErrorRef",
  176. /* The Cocoa versions of these API's are much better and not very common, should we replace them?
  177. "NSOutputStream"=>"CFWriteStreamRef", "NSPasteboard"=>"PasteboardRef"
  178. "NSInputStream"=>"CFReadStreamRef", "NSTimer"=>"CFRunLoopTimerRef",
  179. "NSTimeZone"=>"CFTimeZoneRef", "NSCharacterSet"=>"CFCharacterSetRef",
  180. "NSDate"=>"CFDateRef",
  181. */
  182. );
  183. // types that use objc_msgSend_stret on all architectures
  184. var $struct_types = array( "NSRect", "NSDecimal", "NSFastEnumerationState", "NSMapTableValueCallBacks",
  185. "NSHashTableCallBacks", "NSMapTableKeyCallBacks",
  186. // TEMPORARY PARSER HACKS
  187. "aeDesc_",
  188. );
  189. // structs that use objc_msgSend or objc_msgSend_stret depending on architecture
  190. // "On Mac OS X Intel/i386, records whose size is 1, 2, 4 or 8 bytes are returned using registers"
  191. var $struct_register_types = array( "NSRange", "NSPoint", "NSSize", "NSAffineTransformStruct" );
  192. // Functions that return types will invoke objc_msgSend_fpret
  193. // NOTE: we must also know the exact type so we can make the proper function pointer
  194. var $float_types = array( // C-types
  195. "float", "long double", "double",
  196. // Cocoa types
  197. "NSTimeInterval",
  198. // Pascal types
  199. "Float64", "Float32",
  200. // CarbonTypes
  201. "CGFloat",
  202. );
  203. var $skip_blocks = array( "^#if __LP64__ \|\| NS_BUILD_32_LIKE_64"=>"^#(else|endif)+",
  204. );
  205. var $macro_blocks = array( "^#if (__LP64__)"=>"\$ifdef cpu64",
  206. "^#if ![[:space:]]*(__LP64__)"=>"\$ifndef cpu64",
  207. "^#ifdef __BIG_ENDIAN__"=>"\$ifdef fpc_big_endian",
  208. //"^#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_[0-9]+_[0-9]+"=>"*",
  209. );
  210. // these categories should be placed into NSObject
  211. var $base_categories = array( "NSArchiverCallback", "NSClassDescriptionPrimitives", "NSCoderMethods", "NSComparisonMethods",
  212. "NSDelayedPerforming", "NSDeprecatedKeyValueCoding", "NSDeprecatedKeyValueObservingCustomization",
  213. "NSDistributedObjects", "NSErrorRecoveryAttempting", "NSKeyValueCoding", "NSPlaceholders",
  214. "NSKeyValueObserverRegistration", "NSKeyValueObserving", "NSKeyValueObservingCustomization",
  215. "NSKeyedArchiverObjectSubstitution", "NSKeyedUnarchiverObjectSubstitution", "NSDeprecatedMethods",
  216. "NSScriptKeyValueCoding", "NSThreadPerformAdditions", "NSServicesRequests", "NSKeyValueBindingCreation",
  217. "NSAccessibility", "NSAccessibilityAdditions",
  218. );
  219. // These really don't feel like they should be in NSObject, removing until we know where to put them.
  220. // Maybe a new class? NSCategories...
  221. // "NSURLClient", "NSScripting", "NSScriptClassDescription", "NSScriptObjectSpecifiers",
  222. // "NSScriptingComparisonMethods", "NSFontManagerResponderMethod", "NSMenuValidation",
  223. // "NSColorPanelResponderMethod", "NSFontPanelValidationAdditions", "NSToolbarItemValidation",
  224. // "NSDictionaryControllerKeyValuePair", "NSEditor",
  225. /**
  226. * COMMON REGULAR EXPRESIONS
  227. */
  228. var $regex_objc_method_params = "^(-|\+)[[:space:]]*\((.*)\)[[:space:]]*([a-zA-Z0-9]+):(.*);";
  229. var $regex_objc_method_no_params = "^(-|\+)[[:space:]]*\((.*)\)[[:space:]]*([a-zA-Z0-9]+);";
  230. var $regex_objc_category = "^@interface ([a-zA-Z]+)[[:space:]]*\(([a-zA-Z]+)\)";
  231. var $regex_objc_class = "^@interface ([a-zA-Z]+)[[:space:]]*:[[:space:]]*([a-zA-Z]+)[[:space:]]*(<(.*)>)*";
  232. var $regex_objc_class_no_super = "^@interface ([a-zA-Z]+)[[:space:]]*<(.*)>[[:space:]]*";
  233. var $regex_objc_protocol = "^@protocol ([a-zA-Z]+)";
  234. var $regex_procedure_type = "^[[:space:]]*(void|IBAction)+[[:space:]]*$";
  235. var $regex_scope_compiler_directive = "^\s*@(private|protected|public)(;*)+\s*$";
  236. var $regex_objc_property = "^@property\((.*)\)[[:space:]]*(.*);";
  237. /**
  238. * TEMPLATES
  239. */
  240. // Template for implemented function
  241. var $template_implemented_function = "function [CLASS].implemented_[NAME][PARAMS_HEADER]: [RETURN];
  242. begin
  243. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  244. Result := [RETURN](super_[NAME][PARAMS_BODY_WRAPPER]);
  245. {\$else}
  246. Result := [RETURN](super_[NAME][PARAMS_BODY]);
  247. {\$endif}
  248. end;";
  249. // Template for implemented procedure
  250. var $template_implemented_procedure = "procedure [CLASS].implemented_[NAME][PARAMS_HEADER];
  251. begin
  252. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  253. super_[NAME][PARAMS_BODY_WRAPPER];
  254. {\$else}
  255. super_[NAME][PARAMS_BODY];
  256. {\$endif}
  257. end;";
  258. // Template for constructor
  259. var $template_constructor = "constructor [CLASS][NAME][PARAMS_HEADER];
  260. type
  261. TmsgSendWrapper = function (param1: id; param2: SEL[PARAMS_PROC]): id; cdecl;
  262. var
  263. vmethod: TmsgSendWrapper;
  264. begin
  265. if SEL_[SELNAME] = nil then
  266. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  267. RegisterSubClass;
  268. allocbuf := objc_msgSend(ClassID, SEL_alloc, []);
  269. vmethod := TmsgSendWrapper(@objc_msgSend);
  270. Handle := vmethod(allocbuf, SEL_[SELNAME][PARAMS_LIST_WRAPPER]);
  271. retainCount := 1;
  272. AssignSelf(Handle);
  273. AddMethods;
  274. BindMethods;
  275. end;";
  276. // Template for constructor that does not allocate memory
  277. var $template_constructor_no_alloc = "constructor [CLASS][NAME][PARAMS_HEADER];
  278. type
  279. TmsgSendWrapper = function (param1: id; param2: SEL[PARAMS_PROC]): id; cdecl;
  280. var
  281. vmethod: TmsgSendWrapper;
  282. begin
  283. if SEL_[SELNAME] = nil then
  284. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  285. RegisterSubClass;
  286. vmethod := TmsgSendWrapper(@objc_msgSend);
  287. Handle := vmethod(ClassID, SEL_[SELNAME][PARAMS_LIST_WRAPPER]);
  288. AutoReleaseObject;
  289. AssignSelf(Handle);
  290. AddMethods;
  291. BindMethods;
  292. end;";
  293. // Template for function to send Objective-c message that returns an auto-generated/memory managed wrapper object.
  294. var $template_function_make_wrapper = "function [CLASS][NAME][PARAMS_HEADER]: [RETURN];
  295. type
  296. TmsgSendWrapper = function (param1: id; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
  297. var
  298. vmethod: TmsgSendWrapper;
  299. wrapper: [RETURN];
  300. begin
  301. vmethod := TmsgSendWrapper(@[MSG_SEND]);
  302. if SEL_[SELNAME] = nil then
  303. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  304. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  305. Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]));
  306. {\$else}
  307. Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]));
  308. {\$endif}
  309. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  310. wrapper := [RETURN](GetWrapper(Result));
  311. if wrapper = nil then
  312. Result := [RETURN]([RETURN].CreateWithHandle(Pobjc_object(Result)).deferObject)
  313. else
  314. Result := wrapper;
  315. {\$endif}
  316. end;";
  317. var $template_function_make_wrapper_no_params = "function [CLASS][NAME]: [RETURN];
  318. var
  319. wrapper: [RETURN];
  320. begin
  321. if SEL_[SELNAME] = nil then
  322. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  323. Result := [RETURN]([MSG_SEND]([OBJC_OBJECT], SEL_[SELNAME], []));
  324. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  325. wrapper := [RETURN](GetWrapper(Result));
  326. if wrapper = nil then
  327. Result := [RETURN]([RETURN].CreateWithHandle(Pobjc_object(Result)).deferObject)
  328. else
  329. Result := wrapper;
  330. {\$endif}
  331. end;";
  332. // Template for protocol function to send Objective-c message that returns an auto-generated/memory managed wrapper object.
  333. var $template_protocol_make_wrapper = "function [CLASS][NAME][PARAMS_HEADER]: [RETURN];
  334. type
  335. TmsgSendWrapper = function (param1: id; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
  336. var
  337. vmethod: TmsgSendWrapper;
  338. begin
  339. vmethod := TmsgSendWrapper(@[MSG_SEND]);
  340. if SEL_[SELNAME] = nil then
  341. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  342. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  343. Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]));
  344. {\$else}
  345. Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]));
  346. {\$endif}
  347. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  348. Result := [RETURN]([RETURN].CreateWithHandle(Pobjc_object(Result)).deferObject);
  349. {\$endif}
  350. end;";
  351. var $template_protocol_make_wrapper_no_params = "function [CLASS][NAME]: [RETURN];
  352. begin
  353. if SEL_[SELNAME] = nil then
  354. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  355. Result := [RETURN]([MSG_SEND]([OBJC_OBJECT], SEL_[SELNAME], []));
  356. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  357. Result := [RETURN]([RETURN].CreateWithHandle(Pobjc_object(Result)).deferObject);
  358. {\$endif}
  359. end;";
  360. // Template for function to send Objective-c message
  361. var $template_function_objc_send = "function [CLASS][NAME][PARAMS_HEADER]: [RETURN];
  362. type
  363. TmsgSendWrapper = function (param1: [TARGET_TYPE]; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
  364. var
  365. vmethod: TmsgSendWrapper;
  366. super: objc_super;
  367. begin
  368. vmethod := TmsgSendWrapper(@[MSG_SEND]);
  369. if SEL_[SELNAME] = nil then
  370. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  371. [GET_SUPER_CLASS]
  372. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  373. Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]));
  374. {\$else}
  375. Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]));
  376. {\$endif}
  377. end;";
  378. // Template for function to send Objective-c message (no params)
  379. var $template_function_objc_send_no_params = "function [CLASS][NAME]: [RETURN];
  380. var
  381. super: objc_super;
  382. begin
  383. if SEL_[SELNAME] = nil then
  384. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  385. [GET_SUPER_CLASS]
  386. Result := [RETURN]([MSG_SEND]([OBJC_OBJECT], SEL_[SELNAME], []));
  387. end;";
  388. // Template for function to send Objective-c message which returns a struct
  389. var $template_function_objc_send_struct = "function [CLASS][NAME][PARAMS_HEADER]: [RETURN];
  390. type
  391. TmsgSendWrapper = function (param1: [TARGET_TYPE]; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
  392. var
  393. vmethod: TmsgSendWrapper;
  394. super: objc_super;
  395. begin
  396. if SEL_[SELNAME] = nil then
  397. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  398. vmethod := TmsgSendWrapper(@[MSG_SEND]);
  399. [GET_SUPER_CLASS]
  400. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  401. Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]));
  402. {\$else}
  403. Result := [RETURN](vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]));
  404. {\$endif}
  405. end;";
  406. // Template for function to send Objective-c message which returns a struct
  407. var $template_function_objc_send_struct_cpu = "function [CLASS][NAME][PARAMS_HEADER]: [RETURN];
  408. type
  409. TmsgSendWrapper_reg = function (param1: [TARGET_TYPE]; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
  410. TmsgSendWrapper_stret = function (param1: [TARGET_TYPE]; param2: SEL[PARAMS_PROC]): [RETURN]; cdecl;
  411. var
  412. vmethod_reg: TmsgSendWrapper_reg;
  413. vmethod_stret: TmsgSendWrapper_stret;
  414. super: objc_super;
  415. begin
  416. if SEL_[SELNAME] = nil then
  417. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  418. [GET_SUPER_CLASS]
  419. {\$ifdef CPUi386}
  420. vmethod_reg := TmsgSendWrapper_reg(@[MSG_SEND_REGISTER]);
  421. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  422. Result := vmethod_reg([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]);
  423. {\$else}
  424. Result := vmethod_reg([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]);
  425. {\$endif}
  426. {\$else}
  427. vmethod_stret := TmsgSendWrapper_stret(@[MSG_SEND_STRET]);
  428. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  429. Result := [RETURN](vmethod_stret([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]));
  430. {\$else}
  431. Result := [RETURN](vmethod_stret([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]));
  432. {\$endif}
  433. {\$endif}
  434. end;";
  435. // Template for function to send Objective-c message (no params) which returns a struct
  436. var $template_function_objc_send_no_params_struct = "function [CLASS][NAME]: [RETURN];
  437. var
  438. super: objc_super;
  439. begin
  440. if SEL_[SELNAME] = nil then
  441. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  442. [GET_SUPER_CLASS]
  443. [MSG_SEND](@Result, [OBJC_OBJECT], SEL_[SELNAME], []);
  444. end;";
  445. // Template for function to send Objective-c message (no params) which returns CPU dependent struct
  446. var $template_function_objc_send_no_params_struct_cpu = "function [CLASS][NAME]: [RETURN];
  447. type
  448. TmsgSendWrapper = function (param1: [TARGET_TYPE]; param2: SEL): [RETURN]; cdecl;
  449. var
  450. vmethod: TmsgSendWrapper;
  451. super: objc_super;
  452. begin
  453. if SEL_[SELNAME] = nil then
  454. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  455. [GET_SUPER_CLASS]
  456. {\$ifdef CPUi386}
  457. vmethod := TmsgSendWrapper(@[MSG_SEND_REGISTER]);
  458. Result := vmethod([OBJC_OBJECT], SEL_[SELNAME] );
  459. {\$else}
  460. [MSG_SEND_STRET](@Result, [OBJC_OBJECT], SEL_[SELNAME], []);
  461. {\$endif}
  462. end;";
  463. // Template for procedure to send Objective-c message
  464. var $template_procedure_objc_send = "procedure [CLASS][NAME][PARAMS_HEADER];
  465. type
  466. TmsgSendWrapper = procedure (param1: [TARGET_TYPE]; param2: SEL[PARAMS_PROC]); cdecl;
  467. var
  468. vmethod: TmsgSendWrapper;
  469. super: objc_super;
  470. begin
  471. if SEL_[SELNAME] = nil then
  472. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  473. vmethod := TmsgSendWrapper(@[MSG_SEND]);
  474. [GET_SUPER_CLASS]
  475. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  476. vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST_WRAPPER]);
  477. {\$else}
  478. vmethod([OBJC_OBJECT], SEL_[SELNAME][PARAMS_LIST]);
  479. {\$endif}
  480. end;";
  481. // Template for procedure to send Objective-c message
  482. var $template_procedure_objc_send_no_params = "procedure [CLASS][NAME];
  483. var
  484. super: objc_super;
  485. begin
  486. if SEL_[SELNAME] = nil then
  487. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  488. [GET_SUPER_CLASS]
  489. [MSG_SEND]([OBJC_OBJECT], SEL_[SELNAME], []);
  490. end;";
  491. // Template for procedure to call implemented class method. This is the procedure which the Objectice-c methods are sent to
  492. var $template_procedure_objc_wrapper = "procedure [CLASS]_[NAME](_self: id; _cmd: SEL[PARAMS_HEADER]); cdecl;
  493. var
  494. this: [CLASS];
  495. [VARIABLES]
  496. begin
  497. this := [CLASS]([CLASS].GetSelf(_self));
  498. if this <> nil then
  499. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  500. begin
  501. [WRAPPERS_CREATE]
  502. this.implemented_[NAME][PARAMS_LIST_WRAPPER];
  503. [WRAPPERS_RELEASE]
  504. end;
  505. {\$else}
  506. this.implemented_[NAME][PARAMS_LIST];
  507. {\$endif}
  508. end;";
  509. // Template for procedure to call implemented class method. This is the procedure which the Objectice-c methods are sent to
  510. var $template_function_objc_wrapper = "function [CLASS]_[NAME](_self: id; _cmd: SEL[PARAMS_HEADER]): [RETURN]; cdecl;
  511. var
  512. this: [CLASS];
  513. [VARIABLES]
  514. begin
  515. this := [CLASS]([CLASS].GetSelf(_self));
  516. if this <> nil then
  517. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  518. begin
  519. [WRAPPERS_CREATE]
  520. Result := [RETURN](this.implemented_[NAME][PARAMS_LIST_WRAPPER]);
  521. [WRAPPERS_RELEASE]
  522. end;
  523. {\$else}
  524. Result := [RETURN](this.implemented_[NAME][PARAMS_LIST]);
  525. {\$endif}
  526. end;";
  527. // Template for method to override Objective-c method
  528. var $template_method_override = "procedure [CLASS].override_[NAME];
  529. begin
  530. AddMethod('[OBJC_METHOD]', '[TYPE_ENCODING]', Pointer(@[CLASS]_[NAME]));
  531. end;";
  532. // Template for method to override Objective-c method
  533. var $template_method_override_DEPRECATED = "procedure [CLASS].override_[NAME];
  534. begin
  535. OverrideMethod('[OBJC_METHOD]', Pointer(@[CLASS]_[NAME]));
  536. end;";
  537. // Template for method to add method to Objective-c runtime
  538. var $template_method_add_runtime = "procedure [CLASS].add_[NAME];
  539. begin
  540. AddMethod('[OBJC_METHOD]', '[TYPES]', Pointer(@[CLASS]_[NAME]));
  541. end;";
  542. // Template for implemented delegate procedure
  543. var $template_procedure_delegate = "procedure [CLASS].[NAME][PARAMS];
  544. begin
  545. end;";
  546. // Template for implemented delegate procedure
  547. var $template_function_delegate = "function [CLASS].[NAME][PARAMS]: [RETURN];
  548. begin
  549. end;";
  550. // Template for implemented delegate procedure
  551. var $template_procedure_delegate_objc = "procedure [CLASS]_[NAME][PARAMS_HEADER]; cdecl;
  552. var
  553. this: [CLASS];
  554. [VARIABLES]
  555. begin
  556. this := [CLASS]([CLASS].GetSelf(_self));
  557. if this <> nil then
  558. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  559. begin
  560. [WRAPPERS_CREATE]
  561. this.[NAME][PARAMS_LIST_WRAPPER];
  562. [WRAPPERS_RELEASE]
  563. end;
  564. {\$else}
  565. this.[NAME][PARAMS_LIST];
  566. {\$endif}
  567. end;";
  568. // Template for implemented delegate procedure
  569. var $template_function_delegate_objc = "function [CLASS]_[NAME][PARAMS_HEADER]: [RETURN]; cdecl;
  570. var
  571. this: [CLASS];
  572. [VARIABLES]
  573. begin
  574. this := [CLASS]([CLASS].GetSelf(_self));
  575. if this <> nil then
  576. {\$ifdef NSOBJECT_AUTO_WRAPPER}
  577. begin
  578. [WRAPPERS_CREATE]
  579. Result := [RETURN](this.[NAME][PARAMS_LIST_WRAPPER]);
  580. [WRAPPERS_RELEASE]
  581. end;
  582. {\$else}
  583. Result := [RETURN](this.[NAME][PARAMS_LIST]);
  584. {\$endif}
  585. end;";
  586. // Template for create override in delegate class
  587. var $template_delegate_create = "constructor [CLASS].Create;
  588. begin
  589. CreateClassDefinition(ClassName, 'NSObject');
  590. ClassID := objc_getClass('[CLASS]');
  591. allocbuf := objc_msgSend(ClassId, SEL_alloc, []);
  592. Handle := objc_msgSend(allocbuf, SEL_init, []);
  593. retainCount := 1;
  594. { Adds custom methods, if any }
  595. AddMethods;
  596. BindMethods;
  597. { Assign our wrapper instance }
  598. if Handle <> nil then
  599. AssignSelf(Handle);
  600. end;";
  601. // Template for constructor
  602. var $template_constructor_constarray = "constructor [CLASS][NAME][PARAMS_HEADER];
  603. type
  604. TmsgSendWrapper = function (param1: id; param2: SEL; param3: [CFTYPE]): id; cdecl;
  605. var
  606. vmethod: TmsgSendWrapper;
  607. paramList: [CFTYPE];
  608. i: integer;
  609. begin
  610. if SEL_[SELNAME] = nil then
  611. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  612. RegisterSubClass;
  613. [ALLOC_PARAM_LIST]
  614. allocbuf := objc_msgSend(ClassID, SEL_alloc, []);
  615. vmethod := TmsgSendWrapper(@objc_msgSend);
  616. Handle := vmethod(allocbuf, SEL_[SELNAME], paramList);
  617. retainCount := 1;
  618. AssignSelf(Handle);
  619. AddMethods;
  620. BindMethods;
  621. CFRelease(paramList);
  622. end;";
  623. // Template for constructor that does not allocate memory
  624. var $template_constructor_constarray_no_alloc = "constructor [CLASS][NAME][PARAMS_HEADER];
  625. type
  626. TmsgSendWrapper = function (param1: id; param2: SEL; param3: [CFTYPE]): id; cdecl;
  627. var
  628. vmethod: TmsgSendWrapper;
  629. paramList: [CFTYPE];
  630. i: integer;
  631. begin
  632. if SEL_[SELNAME] = nil then
  633. SEL_[SELNAME] := sel_registerName(PChar('[OBJC_METHOD]'));
  634. RegisterSubClass;
  635. [ALLOC_PARAM_LIST]
  636. vmethod := TmsgSendWrapper(@objc_msgSend);
  637. Handle := vmethod(ClassID, SEL_[SELNAME], paramList);
  638. AutoReleaseObject;
  639. AssignSelf(Handle);
  640. AddMethods;
  641. BindMethods;
  642. CFRelease(paramList);
  643. end;";
  644. // template to create param list for NSDictionary methods
  645. var $template_dictionary_param_list = "paramList := CFDictionaryCreateMutable(nil, 0, @kCFTypeDictionaryKeyCallBacks, @kCFTypeDictionaryValueCallBacks);
  646. i := High(firstObject);
  647. while i > 0 do
  648. begin
  649. CFDictionaryAddValue(paramList, firstObject[i].VPointer, firstObject[i - 1].VPointer);
  650. i := i - 2;
  651. end;";
  652. // template to create param list for NSArray methods
  653. var $template_array_param_list = "paramList := CFArrayCreateMutable(nil, 0, @kCFTypeArrayCallBacks);
  654. for i := 0 to High(firstObj) do
  655. CFArrayAppendValue(paramList, firstObj[i].VPointer);";
  656. // template to create param list for NSSet methods
  657. var $template_set_param_list = "paramList := CFSetCreateMutable(nil, 0, @kCFTypeSetCallBacks);
  658. for i := 0 to High(firstObj) do
  659. CFSetAddValue(paramList, firstObj[i].VPointer);";
  660. /**
  661. * UTILITIES
  662. */
  663. // Skips blocks in the current file being parsed
  664. function SkipBlock ($line) {
  665. if ($line != "") {
  666. foreach ($this->skip_blocks as $key => $value) {
  667. if (@ereg($key, $line)) $this->parser_skipping = true;
  668. if (@ereg($value, $line)) $this->parser_skipping = false;
  669. }
  670. }
  671. return $this->parser_skipping;
  672. }
  673. function IsKeywordReserved($keyword) {
  674. $keyword = strtolower($keyword);
  675. if (in_array($keyword, $this->reserved_keywords)) return true;
  676. }
  677. // Replace type with pointer equivalent
  678. function ReplacePointerType ($type) {
  679. $type = "Pointer {".$type."}";
  680. /*
  681. foreach ($this->pointer_types as $objc_type => $replace_type) {
  682. if ($objc_type == $type) {
  683. $type = $replace_type;
  684. break;
  685. }
  686. }
  687. */
  688. return $type;
  689. }
  690. // Makes a struct field into an inline array (or returns field un-changed)
  691. function MakeFieldInlineArray ($io_field, $line, $name, $type) {
  692. if (eregi("\[([0-9]+)\];", $line, $array_size)) {
  693. $length = (int)$array_size[1] - 1;
  694. if ($length > 0) {
  695. $io_field = " $name: array[0..$length] of $type;";
  696. }
  697. }
  698. return $io_field;
  699. }
  700. // Makes a type bitpacked (or returns type un-changed)
  701. function MakeFieldBitPacked ($ioType, $field, &$bitpacked) {
  702. $bitpacked = false;
  703. if (eregi(":([0-9]+);$", $field, $bitpack)) {
  704. $length = (int)$bitpack[1];
  705. if ($length > 1) {
  706. $ioType = "0..((1 shl $length)-1)";
  707. } else {
  708. $ioType = "0..$length";
  709. }
  710. $bitpacked = true;
  711. }
  712. return $ioType;
  713. }
  714. // Replace objc type with preferred type
  715. function ReplaceObjcType ($type) {
  716. foreach ($this->replace_types as $objc_type => $replace_type) {
  717. if ($objc_type == $type) {
  718. $type = $replace_type;
  719. break;
  720. }
  721. }
  722. return $type;
  723. }
  724. // Exchanges the preferred objc type with the real type
  725. function SwapObjcTypeWithReal ($type) {
  726. if ($type == $this->objc_id) $type = $this->objc_id_real;
  727. return $type;
  728. }
  729. // Replace garbage collector hints
  730. function ReplaceGarbageCollectorHints ($string, &$io_hint) {
  731. $io_hint = false;
  732. foreach ($this->garbage_collector_hints as $hint) {
  733. $out_string = str_ireplace($hint, "", $string);
  734. if ($out_string != $string) {
  735. $io_hint = $hint;
  736. $string = $out_string;
  737. }
  738. }
  739. return $string;
  740. }
  741. // Replace type of reference parameter with pointer
  742. function ReplaceReferenceParameterType ($type) {
  743. foreach ($this->pointer_types as $key => $value) {
  744. if ($key == $type) {
  745. $found = true;
  746. $type = $value;
  747. break;
  748. }
  749. }
  750. if (!$found) $type = $type."Pointer";
  751. return $type;
  752. }
  753. // Replace NS*** "toll free bridge" types with CoreFoundation type
  754. function ReplaceTollFreeBridgeType ($type) {
  755. foreach ($this->toll_free_bridge as $objc_type => $replace_type) {
  756. if ($objc_type == $type) {
  757. $type = istr_replace_word($type, $replace_type, $type);
  758. break;
  759. }
  760. }
  761. return $type;
  762. }
  763. // Replace all NS*** classes in a string with the preffered generic type $this->objc_id
  764. function ReplaceNSTypes ($string) {
  765. foreach ($this->cocoa_classes as $class) {
  766. $string = istr_replace_word($class, $this->objc_id, $string);
  767. }
  768. return $string;
  769. }
  770. // Replace all NS*** classes in a string with id
  771. function ReplaceNSTypesWithReal ($string) {
  772. foreach ($this->cocoa_classes as $class) {
  773. $string = istr_replace_word($class, $this->objc_id_real, $string);
  774. }
  775. return $string;
  776. }
  777. // Replace all NS*** classes in a string with their reference equivalent (i.e NSStringRef = id)
  778. function ReplaceNSTypesWithRef ($string) {
  779. foreach ($this->cocoa_classes as $class) {
  780. $string = istr_replace_word($class, $class."Ref", $string);
  781. }
  782. return $string;
  783. }
  784. // Copies the name from an Objective-C method definition
  785. function CopyObjcMethodName ($method) {
  786. // cut out comments first
  787. $method = eregi_replace("(/\*.*\*/)", "", $method);
  788. $method = eregi_replace("//.*$", "", $method);
  789. $method = trim($method, " ");
  790. $params = explode(":", $method);
  791. $name = "";
  792. if (count($params) > 1) {
  793. foreach ($params as $value) {
  794. $value = trim($value, " ");
  795. if (eregi("([a-zA-Z0-9_]+)$", $value, $captures)) $name .= $captures[1].":";
  796. }
  797. } else {
  798. if (eregi("([a-zA-Z0-9_]+)[[:space:]]*(;)*$", $method, $captures)) $name = $captures[1];
  799. }
  800. return $name;
  801. }
  802. // Converts a function pointer to Pascal function
  803. function ConvertFunctionPointerToPascal ($result, $param_string) {
  804. if ($result != "") {
  805. $params = explode(",", $param_string);
  806. $function = "function (";
  807. $count = 0;
  808. foreach ($params as $param) {
  809. $count ++;
  810. $param = trim($param, " ");
  811. $param = $this->ReplaceObjcType($param);
  812. $param = $this->SwapObjcTypeWithReal($param);
  813. $param = trim($param, "*");
  814. $function .= "param$count: $param; ";
  815. }
  816. $function = rtrim($function, "; ");
  817. $function .= "): $result; cdecl;";
  818. }
  819. //print("$function\n");
  820. return $function;
  821. }
  822. // Converts a C parameter string to Pascal
  823. function ConvertCParamsPascal ($string) {
  824. $params = explode(",", $string);
  825. $param_string = "";
  826. foreach ($params as $param) {
  827. $param = istr_replace_word("const", "", $param);
  828. $param = trim($param, " ");
  829. $pair = explode(" ", $param);
  830. $name = $pair[1];
  831. $type = $pair[0];
  832. $type = $this->ReplaceObjcType($type);
  833. $type = $this->SwapObjcTypeWithReal($type);
  834. $type = $this->ReplaceTollFreeBridgeType($type);
  835. $type = $this->ReplaceNSTypesWithRef($type);
  836. if (($name[0] == "*") && ($name[1] == "*")) {
  837. $name = trim($name, "*");
  838. $type = $this->ReplacePointerType($type);
  839. } elseif ($name[0] == "*") {
  840. $name = trim($name, "*");
  841. $name = $name."Pointer";
  842. //$name = "var $name";
  843. $name = trim($name, " ");
  844. } else {
  845. $name = trim($name, "*");
  846. }
  847. // Remove array brackets (NSUInteger[])p
  848. if (eregi("\[[0-9]*\]", $name)) {
  849. $name = "$name";
  850. $type = "Pointer {array of $type}";
  851. $name = eregi_replace("\[[0-9]*\]", "", $name);
  852. }
  853. if ($this->IsKeywordReserved($name)) $name .= "_";
  854. // multiple parameters
  855. if ($type == "...") {
  856. $param_string .= "varargs: array of const";
  857. break;
  858. }
  859. $param_string .= "$name: $type; ";
  860. }
  861. $param_string = trim($param_string, "; ");
  862. return $param_string;
  863. }
  864. // Remove OS X versions macros from a line
  865. // NOTE: These should be re-inlcuded in Pascal
  866. function RemoveOSVersionMacros ($line) {
  867. $line = eregi_replace("[[:space:]]*AVAILABLE_MAC_OS_X_VERSION_[0-9]+_[0-9]+_AND_LATER[[:space:]]*", "", $line);
  868. return $line;
  869. }
  870. // Removes all comments from a line
  871. function RemoveComments ($line) {
  872. // remove single-line comments
  873. $line = eregi_replace("[[:space:]]+//(.*)", "", $line);
  874. // remove multi-line comments /* ... */
  875. $line = eregi_replace("/\*.*\*/", "", $line);
  876. return $line;
  877. }
  878. // Performs additional formatting on Objective-c type i.e. (out NSObject **)
  879. function FormatObjcType ($type, &$modifiers) {
  880. $modifiers = "";
  881. // toss out all const identifiers
  882. $type = istr_replace_word("const", "", $type);
  883. // replace inout paramaters
  884. $type = istr_replace_word("inout", "", $type);
  885. $type = istr_replace_word("out", "", $type);
  886. $type_clean = trim($type, "* ");
  887. // Replace types before cleaning
  888. $type = $this->ReplaceObjcType($type);
  889. // Remove protocol which type conforms to (id <NSURLHandleClient>)
  890. $type = eregi_replace("<.*>", "", $type);
  891. // Remove array brackets (NSUInteger[])p
  892. $type = eregi_replace("\[[0-9]*\]", "", $type);
  893. // var params to non-object types (NSRange *)
  894. if (ereg("([a-zA-Z0-9_]+)[[:space:]]*[*]+$", $type, $captures)) {
  895. if ((!in_array($captures[1], $this->cocoa_classes)) && ($captures[1] != "id")) {
  896. $type = $this->ReplaceReferenceParameterType($type_clean); //"$type_clean$this->pointer_type_suffx";
  897. //$modifiers = "var ";
  898. }
  899. }
  900. // Handle NS*** pointers (NSError **)
  901. if (ereg("(NS[a-zA-Z0-9_]+)[[:space:]]*\*\*$", $type, $captures)) {
  902. if (in_array($captures[1], $this->cocoa_classes)) {
  903. $type = "$type_clean$this->class_pointer_suffix";
  904. //$modifiers = "var ";
  905. }
  906. }
  907. // clean the type
  908. $type = trim($type, "* ");
  909. //print("$type\n");
  910. return $type;
  911. }
  912. // Performs additional formatting on Objective-c parameter types
  913. function FormatObjcParams ($string) {
  914. $params = explode(":", $string);
  915. $string = "";
  916. if (count($params) > 0) {
  917. foreach ($params as $value) {
  918. if (ereg("\((.*)\)", $value, $captures)) {
  919. $new_value = $this->ReplaceObjcType($captures[1]);
  920. if ($new_value != $captures[1]) $value = ereg_replace("\((.*)\)", "($new_value)", $value);
  921. $string .= ":$value";
  922. }
  923. }
  924. }
  925. $string = ltrim($string, ":");
  926. //print("$string\n");
  927. return $string;
  928. }
  929. // Converts an Objective-c parameter string to Pascal
  930. function ConvertObjcParamsToPascal ($string, $protected_keywords, &$variable_arguments) {
  931. $params = explode(":", $string);
  932. $list = array();
  933. $list["pairs"] = array();
  934. $param_list = array();
  935. $variable_arguments = false;
  936. if (count($params) > 0) {
  937. //print_r($params);
  938. foreach ($params as $value) {
  939. $value = trim($value);
  940. $valid = false;
  941. $modifiers = "";
  942. // function pointer (callback)
  943. if (eregi("\(([a-zA-Z0-9_]+)[[:space:]]\((.*)\)\((.*)\)\)([a-zA-Z0-9_]+)", $value, $captures)) {
  944. $name = $captures[4];
  945. $type = $this->current_header["name_clean"].ucwords($name);
  946. // attempt to build a function pointer from the parameter and append the class type
  947. if ($this->current_header) {
  948. $function_pointer = $this->ConvertFunctionPointerToPascal($captures[1], $captures[3]);
  949. if (!@in_array($function_pointer, $this->current_header["types"]["callbacks"])) {
  950. $count = 0;
  951. while (@array_key_exists($type, $this->current_header["types"]["callbacks"])) {
  952. $count ++;
  953. $type = "$type$count";
  954. }
  955. // append the new type to the the current class
  956. $this->current_header["types"]["callbacks"][$type] = $function_pointer;
  957. } else {
  958. // Use the name of the existing callback of matching type
  959. $type = array_search($function_pointer, $this->current_header["types"]["callbacks"]);
  960. }
  961. }
  962. $valid = true;
  963. } elseif (eregi("\(([a-zA-Z_]+).*\)([a-zA-Z_]+).*\.\.\.", $value, $captures)) { // variable arguments
  964. $name = $captures[2];
  965. $type = $captures[1];
  966. $variable_arguments = true;
  967. $valid = true;
  968. } elseif (eregi("\((.*)\)[[:space:]]*([a-zA-Z_]+)", $value, $captures)) { // standard parameter
  969. // pointers params to non-object types (NSRange *)
  970. if (ereg("[a-zA-Z0-9_]+Ptr$", $captures[2])) {
  971. $captures[1] = trim($captures[1], "* ");
  972. $captures[1] = $this->ReplaceObjcType($captures[1]);
  973. $type = $captures[1].$this->class_pointer_suffix;//$this->ReplacePointerType($captures[1]);
  974. $name = $captures[2];
  975. } else {
  976. $type = $this->FormatObjcType($captures[1], $modifiers);
  977. $name = $captures[2];
  978. }
  979. $valid = true;
  980. }
  981. if ($valid) {
  982. // protect reserved keywords
  983. if ($this->IsKeywordReserved($name)) $name .= "_";
  984. if (!in_array($type, $this->reserved_types)) {
  985. if ($this->IsKeywordReserved($type)) $type .= "_";
  986. }
  987. if (@in_array($name, $protected_keywords)) $name .= "_";
  988. if (@in_array($type, $protected_keywords)) $type .= "_";
  989. // replace objc types
  990. $type = $this->ReplaceObjcType($type);
  991. $type = $this->ReplaceTollFreeBridgeType($type);
  992. // make sure we label duplicate params, which are allowed in Objective-C
  993. while (in_array($name, $param_list)) {
  994. $count ++;
  995. $name = "$name$count";
  996. }
  997. // id is always a wrapper
  998. if (($this->objects_are_wrappers) && ($type == $this->objc_id)) {
  999. $name_list = "$type(GetHandle($name))";
  1000. } else {
  1001. $name_list = $name;
  1002. }
  1003. // add modifiers to the name if there are any
  1004. $name_with_modifiers = $modifiers.$name;
  1005. // create pair array
  1006. $pair["name"] = $name;
  1007. $pair["type"] = $type;
  1008. // append list
  1009. $list["pairs"][] = $pair;
  1010. $list["string_with_modifiers"] .= "$name_with_modifiers: $type; ";
  1011. $list["string"] .= "$name: $type; ";
  1012. $list["list"] .= "$name_list, ";
  1013. $param_list[] = $name;
  1014. }
  1015. }
  1016. }
  1017. // clean up the strings
  1018. $list["string"] = trim($list["string"], "; ");
  1019. $list["string_with_modifiers"] = trim($list["string_with_modifiers"], "; ");
  1020. $list["list"] = trim($list["list"], ", ");
  1021. return $list;
  1022. }
  1023. // Converts an Objective-c method name to Pascal
  1024. function ConvertObjcMethodName ($method) {
  1025. $params = explode(":", $method);
  1026. $name = "";
  1027. if (count($params) > 1) {
  1028. foreach ($params as $value) {
  1029. if (eregi("([a-zA-Z0-9]+)$", $value, $captures)) $name .= $captures[1]."_";
  1030. }
  1031. } else {
  1032. if (eregi("([a-zA-Z0-9]+)(;)*$", $params[0], $captures)) $name .= $captures[1]."_";
  1033. }
  1034. // clean it up
  1035. if (!$this->trailing_underscore) $name = trim($name, "_");
  1036. $name = $this->ReplaceObjcType($name);
  1037. return $name;
  1038. }
  1039. // Converts an Objective-C method to Pascal format
  1040. function ConvertObjcMethodToPascal ($class, $source, $parts, $protected_keywords, $has_params) {
  1041. // replace "hinted" params comment with hinted type
  1042. if ($this->replace_hinted_params) {
  1043. // param string
  1044. if (eregi("(/\*[[:space:]]*(.*)[[:space:]]*\*/)", $parts[4], $captures)) {
  1045. // ??? change the parameter to the hinted type
  1046. //$parts[4] = eregi_replace("(/\*.*\*/)", $captures[2], $parts[4]);
  1047. //$parts[4] = trim($parts[4], " ");
  1048. }
  1049. // return type
  1050. if (eregi("(/\*[[:space:]]*(.*)[[:space:]]*\*/)", $parts[2], $captures)) $parts[2] = $captures[2];
  1051. //print_r($parts);
  1052. } else { // remmove comments from params and return type
  1053. $parts[4] = eregi_replace("(/\*.*\*/)", "", $parts[4]);
  1054. $parts[4] = trim($parts[4], " ");
  1055. $parts[2] = eregi_replace("(/\*.*\*/)", "", $parts[2]);
  1056. $parts[2] = trim($parts[2], " ");
  1057. }
  1058. $return_type_clean = $parts[2];
  1059. // perform preformatting before attempting to protect keywords
  1060. $parts[2] = $this->FormatObjcType($parts[2], $modifiers);
  1061. $parts[4] = $this->FormatObjcParams($parts[4]);
  1062. // protect keywords in the parameter and return type
  1063. if (count($protected_keywords) > 0) {
  1064. foreach ($protected_keywords as $keyword) {
  1065. $parts[4] = istr_replace_word($keyword, $keyword."_", $parts[4]);
  1066. $parts[2] = istr_replace_word($keyword, $keyword."_", $parts[2]);
  1067. }
  1068. }
  1069. if ($has_params) {
  1070. $name = $this->ConvertObjcMethodName($source);
  1071. // merge default protected keywords for the class/category
  1072. if ($this->default_protected["*"]) $protected_keywords = array_merge($this->default_protected["*"], $protected_keywords);
  1073. if ($this->default_protected[$class]) $protected_keywords = array_merge($this->default_protected[$class], $protected_keywords);
  1074. $param_array = $this->ConvertObjcParamsToPascal($parts[4], $protected_keywords, $variable_arguments);
  1075. $params = "(".$param_array["string"].")";
  1076. $params_with_modifiers = "(".$param_array["string_with_modifiers"].")";
  1077. } else {
  1078. $params = "";
  1079. $params_with_modifiers = "";
  1080. $name = $parts[3];
  1081. $param_array = null;
  1082. }
  1083. //print("$params_with_modifiers\n");
  1084. // protect method name from keywords
  1085. if ($this->IsKeywordReserved($name)) $name .= "_";
  1086. // clean return type
  1087. $return_type = trim($parts[2], "* ");
  1088. $return_type = $this->ReplaceObjcType($return_type);
  1089. $return_type = $this->ReplaceTollFreeBridgeType($return_type);
  1090. $virtual = "";
  1091. $class_prefix = "";
  1092. // determine the type based on return value
  1093. if (ereg($this->regex_procedure_type, $return_type_clean)) {
  1094. $kind = "procedure";
  1095. } else {
  1096. $kind = "function";
  1097. // make sure Objective-c objects that are returned from fuctions are not NSObject (and thus auto-wrapped)
  1098. if ($return_type == $this->objc_id) $return_type = $this->objc_id_real;
  1099. // method name starts with "init or alloc"
  1100. if ((ereg("^(init|alloc)+[^ialization]", $name)) && ($parts[1] == "-")) {
  1101. $struct["alloc"] = true;
  1102. $kind = "constructor";
  1103. $virtual = " virtual;";
  1104. }
  1105. // Class methods with the words: With, By or From in the name
  1106. if ((ereg("^([a-zA-Z]+)(With|By|From)+", $name, $captures)) && ($parts[1] == "+")) $kind = "constructor";
  1107. // Class methods which return "id" are constructors
  1108. if (($parts[1] == "+") && ($return_type == $this->objc_id_real)) $kind = "constructor";
  1109. // method result is the class name
  1110. if ($return_type == $class) $kind = "constructor";
  1111. }
  1112. // determine if this is a class method
  1113. if (($kind != "constructor") && ($parts[1] == "+")) $class_prefix = "class ";
  1114. // Determine if the method needs a particular modifier
  1115. // ??? THIS IS NOT COMPILING???
  1116. //if (ereg($this->objc_object_array, $params)) $modifier = " cdecl;";
  1117. // Replace SEL with the string equivalent
  1118. if ($this->register_selectors) {
  1119. $params_with_modifiers = str_replace_word("SEL", $this->sel_string, $params_with_modifiers);
  1120. }
  1121. // make method templates
  1122. if ($kind != "function") {
  1123. $method = "$class_prefix$kind $name$params_with_modifiers;$modifier$virtual";
  1124. $method_template = "[KIND] [PREFIX]$name"."[PARAMS];$modifier";
  1125. } else {
  1126. $method = $class_prefix."function $name$params_with_modifiers: $return_type;$modifier$virtual";
  1127. $method_template = "[KIND] [PREFIX]$name"."[PARAMS]: [RETURN];$modifier";
  1128. $method_template_function = "function [PREFIX]$name"."[PARAMS]: [RETURN];$modifier";
  1129. }
  1130. $method_template_procedure = "procedure [PREFIX]$name"."[PARAMS];$modifier";
  1131. $method_template_function = "function [PREFIX]$name"."[PARAMS]: [RETURN];$modifier";
  1132. // ??? DEBUGGING
  1133. //print("$method\n");
  1134. // build structure
  1135. $struct["def"] = $method;
  1136. $struct["template"] = $method_template;
  1137. $struct["template_function"] = $method_template_function;
  1138. $struct["template_procedure"] = $method_template_procedure;
  1139. $struct["objc_method"] = $this->CopyObjcMethodName($source);
  1140. $struct["class_prefix"] = $class_prefix;
  1141. //$struct["def_objc"] = eregi("(.*);", $source, $captures[1]);
  1142. if ($return_type == "void") $return_type = "";
  1143. $struct["return"] = $return_type;
  1144. if (in_array($return_type, $this->cocoa_classes)) $struct["returns_wrapper"] = true;
  1145. $struct["param_string_clean"] = trim($params, "()");
  1146. $struct["param_string_clean_with_modifiers"] = trim($params_with_modifiers, "()");
  1147. $struct["param_string"] = $params;
  1148. $struct["param_string_with_modifiers"] = $params_with_modifiers;
  1149. $struct["param_array"] = $param_array["pairs"];
  1150. $struct["param_list"] = $param_array["list"];
  1151. $struct["class"] = $class;
  1152. $struct["name"] = $name;
  1153. $struct["kind"] = $kind;
  1154. if ($struct["param_array"] != null) $struct["has_params"] = true;
  1155. // determine if the method can be overridden
  1156. // (!eregi("^(set|get|is)+", $name))
  1157. if ($kind != "constructor") $struct["can_override"] = true;
  1158. /*
  1159. TEMPORARY! we don't know how to handle super methods that have have floating point values
  1160. */
  1161. if (in_array($struct["return"], $this->float_types)) {
  1162. $struct["can_override"] = false;
  1163. print(" # WARNING: method $name can't override because the return type is float\n");
  1164. $this->warning_count ++;
  1165. }
  1166. // FPC bug work around
  1167. if (strlen($name) > $this->maximum_method_length) {
  1168. $struct["can_override"] = false;
  1169. print(" # WARNING: method $name can't override because the name is too long\n");
  1170. $this->warning_count ++;
  1171. }
  1172. return $struct;
  1173. }
  1174. // Print string to output file
  1175. function PrintOutput ($indent, $string) {
  1176. for ($i=0; $i < $indent; $i++) {
  1177. $indent_string .= " ";
  1178. }
  1179. if (($this->output) && (!$this->show)) fwrite($this->output, "$indent_string$string\n");
  1180. if ($this->show) print("$indent_string$string\n");
  1181. }
  1182. // Returns the message sending template for a method structure
  1183. function GetMsgSendTemplate ($method, $super) {
  1184. if ($method["kind"] == "function") {
  1185. if ($method["has_params"]) {
  1186. $template = $this->template_function_objc_send;
  1187. } else {
  1188. $template = $this->template_function_objc_send_no_params;
  1189. }
  1190. } else {
  1191. if ($method["has_params"]) {
  1192. $template = $this->template_procedure_objc_send;
  1193. } else {
  1194. $template = $this->template_procedure_objc_send_no_params;
  1195. }
  1196. }
  1197. // method returns a NS*** class wrapper. Now, super methods can't return wrappers
  1198. if (!$super) {
  1199. if (($method["kind"] == "function") && (in_array($method["return"], $this->cocoa_classes))) {
  1200. if ($method["has_params"]) {
  1201. $template = $this->template_function_make_wrapper;
  1202. } else {
  1203. $template = $this->template_function_make_wrapper_no_params;
  1204. }
  1205. }
  1206. }
  1207. // method returns a struct
  1208. if (($method["kind"] == "function") && (in_array($method["return"], $this->struct_types))) {
  1209. if ($method["has_params"]) {
  1210. $template = $this->template_function_objc_send_struct;
  1211. } else {
  1212. $template = $this->template_function_objc_send_no_params_struct;
  1213. }
  1214. }
  1215. // method returns an architecture dependent struct
  1216. if (($method["kind"] == "function") && (in_array($method["return"], $this->struct_register_types))) {
  1217. if ($method["has_params"]) {
  1218. $template = $this->template_function_objc_send_struct_cpu;
  1219. } else {
  1220. $template = $this->template_function_objc_send_no_params_struct_cpu;
  1221. }
  1222. }
  1223. // method is a constructor
  1224. if ($method["kind"] == "constructor") {
  1225. $template = $this->template_constructor_no_alloc;
  1226. if ($method["alloc"]) $template = $this->template_constructor;
  1227. }
  1228. return $template;
  1229. }
  1230. // Returns a class hierarchy array
  1231. function GetClassHierarchy ($class, &$hierarchy) {
  1232. if (!$hierarchy) $hierarchy = array();
  1233. $hierarchy[] = $class["name"];
  1234. if ($class["super_class"]) {
  1235. $hierarchy[] = $this->GetClassHierarchy($class["super_class"], $hierarchy);
  1236. } else {
  1237. $hierarchy[] = "NSObject";
  1238. }
  1239. return $class["name"];
  1240. }
  1241. // returns if a keyword is protected in a class hierarchy
  1242. function IsKeywordProtected ($keyword, $in_class) {
  1243. $keywords = $this->GetClassHierarchy($in_class, $hierarchy);
  1244. foreach ($hierarchy as $key) {
  1245. if (@in_array($keyword, $keywords)) { //$this->dump["master"][$key]["protected_keywords"]
  1246. return true;
  1247. }
  1248. }
  1249. }
  1250. // Returns all protected keywords in a class hierarchy
  1251. function GetProtectedKeywords ($in_class) {
  1252. $this->GetClassHierarchy($in_class, $hierarchy);
  1253. $keywords = array();
  1254. foreach ($hierarchy as $class) {
  1255. if ($this->dump["master"][$class]["protected_keywords"]) {
  1256. foreach ($this->dump["master"][$class]["protected_keywords"] as $keyword) $keywords[] = $keyword;
  1257. }
  1258. }
  1259. return $keywords;
  1260. }
  1261. // Returns header a category should be moved to
  1262. function FindCategoryHeader ($category) {
  1263. foreach ($this->dump as $name => $header) {
  1264. if ((@array_key_exists($category, $header["classes"])) && ($category != "NSObject")) {
  1265. return $name;
  1266. }
  1267. }
  1268. }
  1269. // Adds a method structure to a class and performs checks for overloaded methods
  1270. function AddMethodToClass (&$method, &$class) {
  1271. // ignore methods
  1272. if (in_array($method["name"], $this->ignore_methods)) return false;
  1273. if (@!in_array($method["name"], $class["declared_methods"])) {
  1274. $class["all"][$method["name"]] = $method;
  1275. $class["protected_keywords"][] = $method["name"];
  1276. $class["declared_methods"][] = $method["name"];
  1277. $this->dump["all_methods"][$class["name"]][] = $method["objc_method"];
  1278. if ($this->show_added_messages) print(" @ Added ".$method["name"]." to ".$class["name"]."\n");
  1279. $this->method_count ++;
  1280. return true;
  1281. } else {
  1282. print(" ! ".$method["def"]." already exists in ".$class["name"]." defined as ".$class["all"][$method["name"]]["def"]."\n");
  1283. }
  1284. }
  1285. // Adds a typedef to the header and handles organization to prevent order conflicts
  1286. function AddTypeDef (&$header, $typedef) {
  1287. $header["types"]["typedef"][] = $typedef;
  1288. }
  1289. // Returns a paramater list string with options to modify
  1290. function MakeParamList ($param_array, $use_handle, $cast_handle, $direct, $register_selector) {
  1291. $params = "";
  1292. foreach ($param_array as $pair) {
  1293. // register selector parameters
  1294. if (($register_selector) && ($pair["type"] == "SEL")) {
  1295. $params .= "sel_registerName(".$pair["name"]."), ";
  1296. continue;
  1297. }
  1298. // use the object handle for NSObject descendants
  1299. if ($use_handle) {
  1300. if (in_array($pair["type"], $this->cocoa_classes)) {
  1301. // cast the param to the original class type
  1302. if ($cast_handle) {
  1303. if ($direct == ACCESS_HANDLE_DIRECT) {
  1304. $params .= $pair["type"]."(".$pair["name"].".Handle), ";
  1305. } else {
  1306. $params .= $pair["type"]."(GetHandle(".$pair["name"].")), ";
  1307. }
  1308. } else {
  1309. if ($direct == ACCESS_HANDLE_DIRECT) {
  1310. $params .= $pair["name"].".Handle, ";
  1311. } else {
  1312. $params .= "GetHandle(".$pair["name"]."), ";
  1313. }
  1314. }
  1315. } else {
  1316. if (($this->objects_are_wrappers) && ($pair["type"] == $this->objc_id)) { // id is always a wrapper
  1317. if ($direct == ACCESS_HANDLE_DIRECT) {
  1318. $params .= $pair["type"]."(".$pair["name"].".Handle), ";
  1319. } else {
  1320. $params .= $pair["type"]."(GetHandle(".$pair["name"].")), ";
  1321. }
  1322. } else {
  1323. $params .= $pair["name"].", ";
  1324. }
  1325. }
  1326. } else { // append without modification
  1327. $params .= $pair["name"].", ";
  1328. }
  1329. }
  1330. return trim($params, ", ");
  1331. }
  1332. // Returns a list of paramameter variables with NS*** class types cast to "id" or the original class
  1333. function MakeObjcTypeParamList ($param_array, $objc_type) {
  1334. $params = "";
  1335. foreach ($param_array as $pair) {
  1336. if (in_array($pair["type"], $this->cocoa_classes)) {
  1337. if ($objc_type) {
  1338. $params .= "$this->objc_id(".$pair["name"]."), ";
  1339. } else {
  1340. $params .= $pair["type"]."(".$pair["name"]."), ";
  1341. }
  1342. } else {
  1343. $params .= $pair["name"].", ";
  1344. }
  1345. }
  1346. return trim($params, ", ");
  1347. }
  1348. /**
  1349. * PRINTING METHODS
  1350. */
  1351. // Prints implemented methods
  1352. function PrintImplementedMethods ($class) {
  1353. // print implemented methods
  1354. $this->PrintOutput(0, "");
  1355. $this->PrintOutput(0, "{ Implemented methods }");
  1356. foreach ($class["all"] as $method) {
  1357. if ($method["can_override"]) {
  1358. if ($method["kind"] == "function") {
  1359. $template = $this->template_implemented_function;
  1360. } else {
  1361. $template = $this->template_implemented_procedure;
  1362. }
  1363. $template = str_replace("[CLASS]", $class["name"], $template);
  1364. $template = str_replace("[NAME]", $method["name"], $template);
  1365. $method["return"] = $this->ReplaceNSTypesWithRef($method["return"]);
  1366. $template = str_replace("[RETURN]", $method["return"], $template);
  1367. $template = str_replace("[PARAMS_HEADER]", $method["param_string_with_modifiers"], $template);
  1368. // build parameter list
  1369. if ($method["has_params"]) {
  1370. // auto-generate wrappers
  1371. $params = "(";
  1372. $params .= $this->MakeParamList($method["param_array"], USE_HANDLE, CAST_HANDLE, ACCESS_HANDLE_FUNCTION, DONT_REGISTER_SEL);
  1373. $params .= ")";
  1374. $template = str_replace("[PARAMS_BODY_WRAPPER]", $params, $template);
  1375. // standard params
  1376. $params = "(";
  1377. $params .= $this->MakeObjcTypeParamList($method["param_array"], true);
  1378. $params .= ")";
  1379. $template = str_replace("[PARAMS_BODY]", $params, $template);
  1380. } else {
  1381. $template = str_replace("[PARAMS_BODY]", "", $template);
  1382. $template = str_replace("[PARAMS_BODY_WRAPPER]", "", $template);
  1383. }
  1384. $this->PrintOutput(0, "");
  1385. $this->PrintOutput(0, $template);
  1386. }
  1387. }
  1388. }
  1389. // Prints Objective-C wrapper procedures
  1390. function PrintObjcWrapperProcedures ($class) {
  1391. // print implemented methods
  1392. $this->PrintOutput(0, "");
  1393. $this->PrintOutput(0, "{ Objective-c wrapper procedures }");
  1394. foreach ($class["all"] as $method) {
  1395. if ($method["can_override"]) {
  1396. if ($method["kind"] == "function") {
  1397. $template = $this->template_function_objc_wrapper;
  1398. } else {
  1399. $template = $this->template_procedure_objc_wrapper;
  1400. }
  1401. $template = str_replace("[CLASS]", $class["name"], $template);
  1402. $template = str_replace("[NAME]", $method["name"], $template);
  1403. $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
  1404. $method["return"] = $this->ReplaceNSTypesWithRef($method["return"]);
  1405. $template = str_replace("[RETURN]", $method["return"], $template);
  1406. if ($method["has_params"]) {
  1407. $method["param_string_clean"] = $this->ReplaceNSTypes($method["param_string_clean"]);
  1408. // Make sure we always the id type in objc wrappers
  1409. $params_header = $this->ReplaceNSTypesWithRef($method["param_string_clean_with_modifiers"]);
  1410. $template = str_replace("[PARAMS_HEADER]", "; $params_header", $template);
  1411. // auto-generate wrappers
  1412. $wrappers_variables = "";
  1413. $wrappers_create = "";
  1414. $wrappers_release = "";
  1415. $variable_list = "";
  1416. foreach ($method["param_array"] as $pair) {
  1417. if (in_array($pair["type"], $this->cocoa_classes)) {
  1418. $wrappers_variables .= "object_".$pair["name"].": ".$pair["type"]."\n;";
  1419. $wrappers_create .= "object_".$pair["name"]." := ".$pair["type"].".CreateWithHandle(".$pair["name"].");\n";
  1420. $wrappers_release .= "object_".$pair["name"].".release;\n";
  1421. $variable_list .= "object_".$pair["name"].", ";
  1422. } else {
  1423. $variable_list .= $pair["name"].", ";
  1424. }
  1425. }
  1426. $variable_list = trim($variable_list, ", ");
  1427. $template = str_replace("[VARIABLES]", $wrappers_variables, $template);
  1428. $template = str_replace("[WRAPPERS_CREATE]", $wrappers_create, $template);
  1429. $template = str_replace("[WRAPPERS_RELEASE]", $wrappers_release, $template);
  1430. $template = str_replace("[PARAMS_LIST_WRAPPER]", "($variable_list)", $template);
  1431. $params = $this->MakeObjcTypeParamList($method["param_array"], false);
  1432. $template = str_replace("[PARAMS_LIST]", "($params)", $template);
  1433. } else {
  1434. $template = str_replace("[PARAMS_HEADER]", "", $template);
  1435. $template = str_replace("[PARAMS_LIST]", "", $template);
  1436. $template = str_replace("[PARAMS_LIST_WRAPPER]", "", $template);
  1437. $template = str_replace("[VARIABLES]", "", $template);
  1438. $template = str_replace("[WRAPPERS_CREATE]", "", $template);
  1439. $template = str_replace("[WRAPPERS_RELEASE]", "", $template);
  1440. }
  1441. $this->PrintOutput(0, "");
  1442. $this->PrintOutput(0, $template);
  1443. }
  1444. }
  1445. }
  1446. // Prints send message objects with a custom implementation
  1447. function PrintCustomSendMessageMethods ($class, $method) {
  1448. // NSArray
  1449. if ($class["name"] == "NSArray") {
  1450. if ($method["name"] == "arrayWithObjects") $template = $this->template_constructor_constarray_no_alloc;
  1451. if ($method["name"] == "initWithObjects") $template = $this->template_constructor_constarray;
  1452. $template = str_replace("[CFTYPE]", "CFArrayRef", $template);
  1453. $template = str_replace("[ALLOC_PARAM_LIST]", $this->template_array_param_list, $template);
  1454. if ($method["name"] == "arrayWithObjects") $template = str_replace("[OBJC_METHOD]", "arrayWithArray:", $template);
  1455. if ($method["name"] == "initWithObjects") $template = str_replace("[OBJC_METHOD]", "initWithArray:", $template);
  1456. }
  1457. // NSDictionary
  1458. if ($class["name"] == "NSDictionary") {
  1459. if ($method["name"] == "dictionaryWithObjectsAndKeys") $template = $this->template_constructor_constarray_no_alloc;
  1460. if ($method["name"] == "initWithObjectsAndKeys") $template = $this->template_constructor_constarray;
  1461. $template = str_replace("[CFTYPE]", "CFDictionaryRef", $template);
  1462. $template = str_replace("[ALLOC_PARAM_LIST]", $this->template_dictionary_param_list, $template);
  1463. if ($method["name"] == "dictionaryWithObjectsAndKeys") $template = str_replace("[OBJC_METHOD]", "dictionaryWithDictionary:", $template);
  1464. if ($method["name"] == "initWithObjectsAndKeys") $template = str_replace("[OBJC_METHOD]", "initWithDictionary:", $template);
  1465. }
  1466. // NSSet
  1467. if ($class["name"] == "NSSet") {
  1468. if ($method["name"] == "setWithObjects") $template = $this->template_constructor_constarray_no_alloc;
  1469. if ($method["name"] == "initWithObjects") $template = $this->template_constructor_constarray;
  1470. $template = str_replace("[CFTYPE]", "CFSetRef", $template);
  1471. $template = str_replace("[ALLOC_PARAM_LIST]", $this->template_set_param_list, $template);
  1472. if ($method["name"] == "setWithObjects") $template = str_replace("[OBJC_METHOD]", "setWithSet:", $template);
  1473. if ($method["name"] == "initWithObjects") $template = str_replace("[OBJC_METHOD]", "initWithSet:", $template);
  1474. }
  1475. $template = str_replace("[PARAMS_HEADER]", $method["param_string_with_modifiers"], $template);
  1476. $template = str_replace("[CLASS]", $class["name"].".", $template);
  1477. $template = str_replace("[NAME]", $method["name"], $template);
  1478. $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
  1479. $this->PrintOutput(0, "");
  1480. $this->PrintOutput(0, $template);
  1481. }
  1482. // Prints send message objects
  1483. function PrintSendMessageMethods ($class) {
  1484. $this->PrintOutput(0, "");
  1485. $this->PrintOutput(0, "{ Objective-c send message methods }");
  1486. foreach ($class["all"] as $method) {
  1487. // handle custom methods
  1488. if (in_array($class["name"].".".$method["name"], $this->custom_send_methods)) {
  1489. $this->PrintCustomSendMessageMethods($class, $method);
  1490. continue;
  1491. }
  1492. $template = $this->GetMsgSendTemplate($method, false);
  1493. $template = $method["class_prefix"].$template;
  1494. $template = str_replace("[CLASS]", $class["name"].".", $template);
  1495. $template = str_replace("[NAME]", $method["name"], $template);
  1496. $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
  1497. $template = str_replace("[RETURN]", $method["return"], $template);
  1498. // Replace SEL with the string equivalent so it can be registered inside the wrapper
  1499. if ($this->register_selectors) {
  1500. $params_header = str_replace_word("SEL", $this->sel_string, $method["param_string_with_modifiers"]);
  1501. $register = REGISTER_SEL;
  1502. } else {
  1503. $params_header = $method["param_string_with_modifiers"];
  1504. $register = DONT_REGISTER_SEL;
  1505. }
  1506. $template = str_replace("[PARAMS_HEADER]", $params_header, $template);
  1507. if ($method["has_params"]) {
  1508. $template = str_replace("[PARAMS_PROC]", "; ".$method["param_string_clean_with_modifiers"], $template);
  1509. $params_wrapper = $this->MakeParamList($method["param_array"], USE_HANDLE, CAST_HANDLE, ACCESS_HANDLE_FUNCTION, $register);
  1510. $params_list = $this->MakeParamList($method["param_array"], DONT_USE_HANDLE, DONT_CAST_HANDLE, ACCESS_HANDLE_FUNCTION, $register);
  1511. $template = str_replace("[PARAMS_LIST_WRAPPER]", ", ".$params_wrapper, $template);
  1512. $template = str_replace("[PARAMS_LIST]", ", ".$params_list, $template);
  1513. } else {
  1514. $template = str_replace("[PARAMS_PROC]", "", $template);
  1515. $template = str_replace("[PARAMS_LIST]", "", $template);
  1516. $template = str_replace("[PARAMS_LIST_WRAPPER]", "", $template);
  1517. }
  1518. $template = str_replace("[TARGET_TYPE]", $this->objc_id_real, $template);
  1519. $template = str_replace("[OBJC_METHOD]", $method["objc_method"], $template);
  1520. $template = str_replace("[GET_SUPER_CLASS]", "", $template);
  1521. // decide reference to objc object by method type
  1522. if ($method["class_prefix"] == "") {
  1523. $template = str_replace("[OBJC_OBJECT]", "Handle", $template);
  1524. } else {
  1525. $template = str_replace("[OBJC_OBJECT]", "getClass", $template);
  1526. }
  1527. $template = str_replace("[MSG_SEND_STRET]", "objc_msgSend_stret", $template);
  1528. $template = str_replace("[MSG_SEND_REGISTER]", "objc_msgSend", $template);
  1529. if (in_array($method["return"], $this->struct_types)) { // structure
  1530. $template = str_replace("[MSG_SEND]", "objc_msgSend_stret", $template);
  1531. } elseif (in_array($method["return"], $this->float_types)) { // floating point
  1532. $template = str_replace("[MSG_SEND]", "objc_msgSend_fpret", $template);
  1533. } else { // simple type
  1534. $template = str_replace("[MSG_SEND]", "objc_msgSend", $template);
  1535. }
  1536. $this->PrintOutput(0, "");
  1537. $this->PrintOutput(0, $template);
  1538. }
  1539. }
  1540. // Prints override methods
  1541. function PrintOverrideMethods ($class) {
  1542. $this->PrintOutput(0, "");
  1543. $this->PrintOutput(0, "{ Override methods }");
  1544. foreach ($class["all"] as $method) {
  1545. if ($method["can_override"]) {
  1546. $template = $this->template_method_override;
  1547. $template = str_replace("[CLASS]", $class["name"], $template);
  1548. $template = str_replace("[NAME]", $method["name"], $template);
  1549. $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
  1550. $template = str_replace("[OBJC_METHOD]", $method["objc_method"], $template);
  1551. $template = str_replace("[TYPE_ENCODING]", $this->type_encodings[$class["name"]][$method["objc_method"]], $template);
  1552. $this->PrintOutput(0, "");
  1553. $this->PrintOutput(0, $template);
  1554. }
  1555. }
  1556. }
  1557. // Prints implemented methods that contain sending code
  1558. function PrintImplementedSuperMethods ($class) {
  1559. $this->PrintOutput(0, "");
  1560. $this->PrintOutput(0, "{ Implemented methods }");
  1561. foreach ($class["all"] as $method) {
  1562. if ($method["can_override"]) {
  1563. $template = $this->GetMsgSendTemplate($method, true);
  1564. $template = str_replace("[CLASS]", $class["name"].".", $template);
  1565. $template = str_replace("[NAME]", "implemented_".$method["name"], $template);
  1566. $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
  1567. $method["return"] = $this->ReplaceNSTypesWithRef($method["return"]);
  1568. $template = str_replace("[RETURN]", $method["return"], $template);
  1569. // Replace SEL with the string equivalent so it can be registered inside the wrapper
  1570. if ($this->register_selectors) {
  1571. $params_header = str_replace_word("SEL", $this->sel_string, $method["param_string_with_modifiers"]);
  1572. $register = REGISTER_SEL;
  1573. } else {
  1574. $params_header = $method["param_string_with_modifiers"];
  1575. $register = DONT_REGISTER_SEL;
  1576. }
  1577. $template = str_replace("[PARAMS_HEADER]", $params_header, $template);
  1578. if ($method["has_params"]) {
  1579. $template = str_replace("[PARAMS_PROC]", "; ".$method["param_string_clean_with_modifiers"], $template);
  1580. $params_wrapper = $this->MakeParamList($method["param_array"], USE_HANDLE, CAST_HANDLE, ACCESS_HANDLE_FUNCTION, $register);
  1581. $params_list = $this->MakeParamList($method["param_array"], DONT_USE_HANDLE, DONT_CAST_HANDLE, ACCESS_HANDLE_FUNCTION, $register);
  1582. $template = str_replace("[PARAMS_LIST_WRAPPER]", ", ".$params_wrapper, $template);
  1583. $template = str_replace("[PARAMS_LIST]", ", ".$params_list, $template);
  1584. } else {
  1585. $template = str_replace("[PARAMS_PROC]", "", $template);
  1586. $template = str_replace("[PARAMS_LIST]", "", $template);
  1587. }
  1588. $template = str_replace("[TARGET_TYPE]", "Pobjc_super", $template);
  1589. $template = str_replace("[OBJC_METHOD]", $method["objc_method"], $template);
  1590. $template = str_replace("[OBJC_OBJECT]", "@super", $template);
  1591. $template = str_replace("[GET_SUPER_CLASS]", "super := getSuperClass;", $template);
  1592. $template = str_replace("[MSG_SEND_STRET]", "objc_msgSendSuper_stret", $template);
  1593. $template = str_replace("[MSG_SEND_REGISTER]", "objc_msgSendSuper", $template);
  1594. if (in_array($method["return"], $this->struct_types)) {
  1595. $template = str_replace("[MSG_SEND]", "objc_msgSendSuper_stret", $template);
  1596. } else {
  1597. $template = str_replace("[MSG_SEND]", "objc_msgSendSuper", $template);
  1598. }
  1599. $this->PrintOutput(0, "");
  1600. $this->PrintOutput(0, $template);
  1601. }
  1602. }
  1603. }
  1604. // Prints super methods
  1605. function PrintSuperMethods ($class) {
  1606. $this->PrintOutput(0, "");
  1607. $this->PrintOutput(0, "{ Super methods }");
  1608. foreach ($class["all"] as $method) {
  1609. if ($method["can_override"]) {
  1610. $template = $this->GetMsgSendTemplate($method, true);
  1611. $template = str_replace("[CLASS]", $class["name"].".", $template);
  1612. $template = str_replace("[NAME]", "super_".$method["name"], $template);
  1613. $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
  1614. $method["return"] = $this->ReplaceNSTypesWithRef($method["return"]);
  1615. $template = str_replace("[RETURN]", $method["return"], $template);
  1616. //$method["param_string"] = $this->ReplaceNSTypesWithReal($method["param_string"]);
  1617. //$method["param_string_clean"] = $this->ReplaceNSTypesWithReal($method["param_string_clean"]);
  1618. $template = str_replace("[PARAMS_HEADER]", $method["param_string_with_modifiers"], $template);
  1619. $template = str_replace("[PARAMS_PROC]", "; ".$method["param_string_clean"], $template);
  1620. $template = str_replace("[PARAMS_LIST_WRAPPER]", ", ".$method["param_list"], $template);
  1621. $template = str_replace("[PARAMS_LIST]", ", ".$method["param_list"], $template);
  1622. $template = str_replace("[TARGET_TYPE]", "Pobjc_super", $template);
  1623. $template = str_replace("[OBJC_METHOD]", $method["objc_method"], $template);
  1624. $template = str_replace("[OBJC_OBJECT]", "@super", $template);
  1625. $template = str_replace("[GET_SUPER_CLASS]", "", $template);
  1626. if (in_array($method["return"], $this->struct_types)) {
  1627. $template = str_replace("[MSG_SEND]", "objc_msgSendSuper_stret", $template);
  1628. } else {
  1629. $template = str_replace("[MSG_SEND]", "objc_msgSendSuper", $template);
  1630. }
  1631. $this->PrintOutput(0, "");
  1632. $this->PrintOutput(0, $template);
  1633. }
  1634. }
  1635. }
  1636. function PrintProtocolDeclaration ($protocol, $method) {
  1637. $template = $method["template"];
  1638. $template = str_replace("[PREFIX]", $protocol["name"]."_", $template);
  1639. if ($method["param_array"] == 0) {
  1640. $param = "sourceObject: NSObjectRef";
  1641. } else {
  1642. $param = "sourceObject: NSObjectRef; ";
  1643. }
  1644. $template = str_replace("[PARAMS]", "($param".$method["param_string_clean_with_modifiers"].")", $template);
  1645. $template = str_replace("[KIND]", $method["kind"], $template);
  1646. $template = str_replace("[RETURN]", $method["return"], $template);
  1647. $this->PrintOutput(0, $template);
  1648. }
  1649. // Prints all the protocols in the header
  1650. function PrintHeaderProtocols ($header, $implemented) {
  1651. if (!$header["protocols"]) return;
  1652. foreach ($header["protocols"] as $protocol) {
  1653. if ($implemented) {
  1654. if (!$protocol["methods"]) continue;
  1655. foreach ($protocol["methods"] as $name => $method) {
  1656. if ($method["kind"] != "constructor") {
  1657. //$this->PrintProtocolDeclaration($protocol, $method);
  1658. $template = $this->GetMsgSendTemplate($method, false);
  1659. // choose the protocol version
  1660. if ($template == $this->template_function_make_wrapper) $template = $this->template_protocol_make_wrapper;
  1661. if ($template == $this->template_function_make_wrapper_no_params) $template = $this->template_protocol_make_wrapper_no_params;
  1662. $template = str_replace("[CLASS]", $protocol["name"]."_", $template);
  1663. if ($method["param_array"] == 0) {
  1664. // add header params token to accommodate our extra parameter
  1665. $template = str_replace("[NAME]", $method["name"]."[PARAMS_HEADER]", $template);
  1666. } else {
  1667. $template = str_replace("[NAME]", $method["name"], $template);
  1668. }
  1669. $template = str_replace("[SELNAME]", str_replace(":", "_", $method["objc_method"]), $template);
  1670. $template = str_replace("[RETURN]", $method["return"], $template);
  1671. if ($method["param_array"] == 0) {
  1672. $source_param = "sourceObject: NSObjectRef";
  1673. } else {
  1674. $source_param = "sourceObject: NSObjectRef; ";
  1675. }
  1676. // Replace SEL with the string equivalent so it can be registered inside the wrapper
  1677. if ($this->register_selectors) {
  1678. $params_header = str_replace_word("SEL", $this->sel_string, $method["param_string_clean_with_modifiers"]);
  1679. $register = REGISTER_SEL;
  1680. } else {
  1681. $params_header = $method["param_string_clean_with_modifiers"];
  1682. $register = DONT_REGISTER_SEL;
  1683. }
  1684. $template = str_replace("[PARAMS_HEADER]", "($source_param$params_header)", $template);
  1685. if ($method["has_params"]) {
  1686. $template = str_replace("[PARAMS_PROC]", "; ".$method["param_string_clean"], $template);
  1687. $params_wrapper = $this->MakeParamList($method["param_array"], USE_HANDLE, CAST_HANDLE, ACCESS_HANDLE_DIRECT, $register);
  1688. $params_list = $this->MakeParamList($method["param_array"], DONT_USE_HANDLE, DONT_CAST_HANDLE, ACCESS_HANDLE_DIRECT, $register);
  1689. $template = str_replace("[PARAMS_LIST_WRAPPER]", ", ".$params_wrapper, $template);
  1690. $template = str_replace("[PARAMS_LIST]", ", ".$params_list, $template);
  1691. } else {
  1692. $template = str_replace("[PARAMS_PROC]", "", $template);
  1693. $template = str_replace("[PARAMS_LIST]", "", $template);
  1694. }
  1695. $template = str_replace("[TARGET_TYPE]", $this->objc_id_real, $template);
  1696. $template = str_replace("[OBJC_METHOD]", $method["objc_method"], $template);
  1697. $template = str_replace("[GET_SUPER_CLASS]", "", $template);
  1698. $template = str_replace("[MSG_SEND_STRET]", "objc_msgSend_stret", $template);
  1699. $template = str_replace("[MSG_SEND_REGISTER]", "objc_msgSend", $template);
  1700. // use the source object as the the target
  1701. $template = str_replace("[OBJC_OBJECT]", "sourceObject", $template);
  1702. if (in_array($method["return"], $this->struct_types)) { // structure
  1703. $template = str_replace("[MSG_SEND]", "objc_msgSend_stret", $template);
  1704. } elseif (in_array($method["return"], $this->float_types)) { // floating point
  1705. $template = str_replace("[MSG_SEND]", "objc_msgSend_fpret", $template);
  1706. } else { // simple type
  1707. $template = str_replace("[MSG_SEND]", "objc_msgSend", $template);
  1708. }
  1709. $this->PrintOutput(0, "");
  1710. $this->PrintOutput(0, $template);
  1711. }
  1712. }
  1713. } else {
  1714. if ($protocol["methods"]) {
  1715. $this->PrintOutput(0, "");
  1716. $this->PrintOutput(0, "{ Protocol: ".$protocol["name"]." }");
  1717. foreach ($protocol["methods"] as $name => $method) {
  1718. if ($method["kind"] != "constructor") {
  1719. $this->PrintProtocolDeclaration($protocol, $method);
  1720. }
  1721. }
  1722. }
  1723. }
  1724. }
  1725. }
  1726. function PrintSelectorVariables ($class) {
  1727. // class has no methods, bail!
  1728. if (!$class["methods"]) return;
  1729. $this->PrintOutput(0,"var");
  1730. foreach ($class["all"] as $method) {
  1731. $sel_name = str_replace(":", "_", $method["objc_method"]);
  1732. $this->PrintOutput(1, "SEL_$sel_name: SEL;");
  1733. }
  1734. }
  1735. // Prints a classes implementation in Pascal format to a file handle
  1736. function PrintClassImplementation ($class) {
  1737. // class has no methods, bail!
  1738. if (!$class["methods"]) return;
  1739. $name = $class["name"];
  1740. $this->PrintOutput(0,"");
  1741. $this->PrintOutput(0, "{ Selectors for $name }");
  1742. $this->PrintSelectorVariables($class);
  1743. $this->PrintOutput(0,"");
  1744. $this->PrintOutput(0, "{ Implementation for $name }");
  1745. // Global accessor object
  1746. $this->PrintOutput(0,"");
  1747. $this->PrintOutput(0,"var");
  1748. $this->PrintOutput(1, "__".$class["name"].": ".$class["name"].";");
  1749. // getClass method
  1750. $this->PrintOutput(0,"");
  1751. $this->PrintOutput(0,"class function $name.getClass: $this->objc_id_real;");
  1752. $this->PrintOutput(0,"begin");
  1753. $this->PrintOutput(1,"Result := objc_getClass('$name');");
  1754. $this->PrintOutput(0,"end;");
  1755. // withObject static accessor
  1756. $this->PrintOutput(0,"");
  1757. $this->PrintOutput(0, "class function $name.withObject (inObject: Pointer): $name;");
  1758. $this->PrintOutput(0,"begin");
  1759. $this->PrintOutput(1,"if __$name = nil then");
  1760. $this->PrintOutput(2,"__$name := $name.Create;");
  1761. $this->PrintOutput(1,"__$name.Handle := inObject;");
  1762. $this->PrintOutput(1,"result := __$name;");
  1763. $this->PrintOutput(0,"end;");
  1764. $this->PrintImplementedSuperMethods($class);
  1765. // DEPRECTAED IN FAVOR OF IMPLEMENTED SUPER METHODS
  1766. //$this->PrintImplementedMethods($class);
  1767. //$this->PrintSuperMethods($class);
  1768. $this->PrintObjcWrapperProcedures($class);
  1769. $this->PrintOverrideMethods($class);
  1770. $this->PrintSendMessageMethods($class);
  1771. }
  1772. // Prints a calls in Pascal format to a file handle
  1773. public function PrintClass ($class) {
  1774. // class has no methods, bail!
  1775. if (!$class["methods"]) return;
  1776. // the delegate class is the super class of NSObject
  1777. if ($class["name"] == "NSObject") $class["super"] = $this->master_delegate_class;
  1778. $this->PrintOutput(0, "");
  1779. $this->PrintOutput(0, "{ ".$class["name"]." }");
  1780. $this->PrintOutput(1, $class["name"]." = class(".$class["super"].")");
  1781. $this->PrintOutput(1, "public");
  1782. // getClass override
  1783. $this->PrintOutput(2, "class function getClass: $this->objc_id_real; override;");
  1784. // static wrapper accessor
  1785. $class_name = $class["name"];
  1786. $this->PrintOutput(2, "class function withObject (inObject: Pointer): $class_name;");
  1787. // print class-level methods
  1788. $this->PrintOutput(0, "");
  1789. $this->PrintOutput(2, "{ Class Methods }");
  1790. foreach ($class["methods"] as $method) {
  1791. $this->PrintOutput(2, $method["def"]);
  1792. }
  1793. // print category-level methods
  1794. if (count($class["categories"]) > 0) {
  1795. foreach ($class["categories"] as $name => $category) {
  1796. $this->PrintOutput(0, "");
  1797. $this->PrintOutput(2, "{ Category: $name }");
  1798. if ($category["methods"]) {
  1799. foreach ($category["methods"] as $method) {
  1800. $this->PrintOutput(2, $method["def"]);
  1801. }
  1802. }
  1803. }
  1804. }
  1805. // print implemented methods
  1806. $this->PrintOutput(0, "");
  1807. $this->PrintOutput(1, "protected");
  1808. $this->PrintOutput(2, "{ Implemented Methods }");
  1809. foreach ($class["all"] as $method) {
  1810. if ($method["can_override"]) {
  1811. $template = $method["template"];
  1812. $template = str_replace("[PREFIX]", "implemented_", $template);
  1813. $template = str_replace("[PARAMS]", $method["param_string_with_modifiers"], $template);
  1814. $template = str_replace("[KIND]", $method["kind"], $template);
  1815. // implemented methods always return id instead of wrappers
  1816. $method["return"] = $this->ReplaceNSTypesWithRef($method["return"]);
  1817. $template = str_replace("[RETURN]", $method["return"], $template);
  1818. $this->PrintOutput(2, $template." virtual;");
  1819. }
  1820. }
  1821. // print override methods
  1822. $this->PrintOutput(0, "");
  1823. $this->PrintOutput(2, "{ Override Methods }");
  1824. foreach ($class["all"] as $method) {
  1825. if ($method["can_override"]) {
  1826. $template = $method["template_procedure"];
  1827. $template = str_replace("[PREFIX]", "override_", $template);
  1828. $template = str_replace("[PARAMS]", "", $template);
  1829. $template = str_replace("[RETURN]", "", $template);
  1830. $this->PrintOutput(2, $template);
  1831. }
  1832. }
  1833. // print super methods
  1834. /* DEPRECTAED IN FAVOR OF IMPLEMENTED SUPER METHODS
  1835. $this->PrintOutput(0, "");
  1836. $this->PrintOutput(2, "{ Super Methods }");
  1837. foreach ($class["all"] as $method) {
  1838. if ($method["can_override"]) {
  1839. $template = $method["template"];
  1840. $template = str_replace("[PREFIX]", "super_", $template);
  1841. $template = str_replace("[PARAMS]", $method["param_string_with_modifiers"], $template);
  1842. $template = str_replace("[KIND]", $method["kind"], $template);
  1843. $template = str_replace("[RETURN]", $this->ReplaceNSTypesWithRef($method["return"]), $template);
  1844. $this->PrintOutput(2, $template);
  1845. }
  1846. }
  1847. */
  1848. $this->PrintOutput(1, "end;");
  1849. }
  1850. function PrintDelegateReference ($valid_categories) {
  1851. ksort($this->delegate_methods);
  1852. $this->PrintOutput(0, "unit $this->master_delegate_file;");
  1853. $this->PrintOutput(0, "interface");
  1854. $this->PrintOutput(0, "uses");
  1855. $this->PrintOutput(1, "ctypes, objc, MacOSAll");
  1856. $this->PrintOutput(0, "type");
  1857. $this->PrintOutput(1, "$this->master_delegate_class = class");
  1858. $this->PrintOutput(1, "public");
  1859. // implemented methods
  1860. foreach ($this->delegate_methods as $category => $selectors) {
  1861. if (in_array($category, $this->ignore_categories)) continue;
  1862. // make sure the category is valid
  1863. $valid = false;
  1864. foreach ($valid_categories as $pattern) {
  1865. if (eregi($pattern, $category)) {
  1866. $valid = true;
  1867. break;
  1868. }
  1869. }
  1870. if (!$valid) continue;
  1871. $this->PrintOutput(2, "");
  1872. $this->PrintOutput(2, "{ $category }");
  1873. foreach ($selectors as $selector) {
  1874. // FPC long name bug work-around
  1875. if (strlen($selector["name_pascal"]) > $this->maximum_method_length) continue;
  1876. if ($selector["kind"] == "procedure") {
  1877. $this->PrintOutput(2, $selector["kind"]." ".$selector["name_pascal"].$selector["param_string"].";");
  1878. } else {
  1879. $this->PrintOutput(2, $selector["kind"]." ".$selector["name_pascal"].$selector["param_string"].": ".$selector["method"]["return"].";");
  1880. }
  1881. }
  1882. }
  1883. $this->PrintOutput(1, "end;");
  1884. }
  1885. function PrintDelegateClass ($valid_categories) {
  1886. ksort($this->delegate_methods);
  1887. $this->PrintOutput(0, "{\$ifdef FORWARD}");
  1888. $this->PrintOutput(1, "$this->master_delegate_class = class;");
  1889. $this->PrintOutput(0, "{\$endif}");
  1890. $this->PrintOutput(0, "{\$ifdef CLASSES}");
  1891. $macro = strtoupper($this->master_delegate_class);
  1892. $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_C}");
  1893. $this->PrintOutput(0, "{\$define $macro"."_PAS_C}");
  1894. $this->PrintOutput(1, "$this->master_delegate_class = class(NSObjectCore)");
  1895. $this->PrintOutput(1, "public");
  1896. //$this->PrintOutput(2, "constructor Create; override;");
  1897. // implemented methods
  1898. foreach ($this->delegate_methods as $category => $selectors) {
  1899. if (in_array($category, $this->ignore_categories)) continue;
  1900. // make sure the category is valid
  1901. $valid = false;
  1902. foreach ($valid_categories as $pattern) {
  1903. if (eregi($pattern, $category)) {
  1904. $valid = true;
  1905. break;
  1906. }
  1907. }
  1908. if (!$valid) continue;
  1909. $this->PrintOutput(2, "");
  1910. $this->PrintOutput(2, "{ $category }");
  1911. foreach ($selectors as $selector) {
  1912. // FPC long name bug work-around
  1913. if (strlen($selector["name_pascal"]) > $this->maximum_method_length) continue;
  1914. if ($selector["kind"] == "procedure") {
  1915. $this->PrintOutput(2, $selector["kind"]." ".$selector["name_pascal"].$selector["param_string"]."; virtual;");
  1916. } else {
  1917. $this->PrintOutput(2, $selector["kind"]." ".$selector["name_pascal"].$selector["param_string"].": ".$selector["method"]["return"]."; virtual;");
  1918. }
  1919. }
  1920. }
  1921. // add methods
  1922. $this->PrintOutput(2, "");
  1923. $this->PrintOutput(2, "{ Adding methods }");
  1924. foreach ($this->delegate_methods as $category => $selectors) {
  1925. if (in_array($category, $this->ignore_categories)) continue;
  1926. // make sure the category is valid
  1927. $valid = false;
  1928. foreach ($valid_categories as $pattern) {
  1929. if (eregi($pattern, $category)) {
  1930. $valid = true;
  1931. break;
  1932. }
  1933. }
  1934. if (!$valid) continue;
  1935. foreach ($selectors as $selector) {
  1936. // FPC long name bug work-around
  1937. if (strlen("add_".$selector["name_pascal"]) > $this->maximum_method_length) continue;
  1938. $this->PrintOutput(2, "procedure add_".$selector["name_pascal"].";");
  1939. }
  1940. }
  1941. $this->PrintOutput(1, "end;");
  1942. $this->PrintOutput(0, "{\$endif}");
  1943. $this->PrintOutput(0, "{\$endif}");
  1944. $this->PrintOutput(0, "{\$ifdef IMPLEMENTATION}");
  1945. // create constructor method
  1946. /*
  1947. $this->PrintOutput(0, "");
  1948. $template = str_replace("[CLASS]", $this->master_delegate_class, $this->template_delegate_create);
  1949. $this->PrintOutput(0, $template);
  1950. */
  1951. // print implemented methods
  1952. foreach ($this->delegate_methods as $category => $selectors) {
  1953. if (in_array($category, $this->ignore_categories)) continue;
  1954. // make sure the category is valid
  1955. $valid = false;
  1956. foreach ($valid_categories as $pattern) {
  1957. if (eregi($pattern, $category)) {
  1958. $valid = true;
  1959. break;
  1960. }
  1961. }
  1962. if (!$valid) continue;
  1963. // place-holder methods
  1964. foreach ($selectors as $selector) {
  1965. // FPC long name bug work-around
  1966. if (strlen($selector["name_pascal"]) > $this->maximum_method_length) continue;
  1967. if ($selector["kind"] == "procedure") {
  1968. $this->PrintOutput(0, $selector["kind"]." ".$this->master_delegate_class.".".$selector["name_pascal"].$selector["param_string"].";");
  1969. } else {
  1970. $this->PrintOutput(0, $selector["kind"]." ".$this->master_delegate_class.".".$selector["name_pascal"].$selector["param_string"].": ".$selector["method"]["return"].";");
  1971. }
  1972. $this->PrintOutput(0, "begin");
  1973. $this->PrintOutput(0, "end;");
  1974. $this->PrintOutput(0, "");
  1975. }
  1976. // objc wrappers
  1977. foreach ($selectors as $selector) {
  1978. // FPC long name bug work-around
  1979. if (strlen($selector["name_pascal"]) > $this->maximum_method_length) continue;
  1980. if ($selector["kind"] == "function") {
  1981. $template = $this->template_function_delegate_objc;
  1982. } else {
  1983. $template = $this->template_procedure_delegate_objc;
  1984. }
  1985. $template = str_replace("[CLASS]", $this->master_delegate_class, $template);
  1986. $template = str_replace("[NAME]", $selector["name_pascal"], $template);
  1987. $selector["method"]["return"] = $this->ReplaceNSTypes($selector["method"]["return"]);
  1988. $template = str_replace("[RETURN]", $selector["method"]["return"], $template);
  1989. if ($selector["method"]["has_params"]) {
  1990. $selector["method"]["param_string_clean"] = $this->ReplaceNSTypesWithRef($selector["method"]["param_string_clean"]);
  1991. $template = str_replace("[PARAMS_HEADER]", " (_self: $this->objc_id_real; _cmd: SEL; ".$selector["method"]["param_string_clean"].")", $template);
  1992. // auto-generate wrappers
  1993. $wrappers_variables = "";
  1994. $wrappers_create = "";
  1995. $wrappers_release = "";
  1996. $variable_list = "";
  1997. foreach ($selector["method"]["param_array"] as $pair) {
  1998. if (in_array($pair["type"], $this->cocoa_classes)) {
  1999. $wrappers_variables .= "object_".$pair["name"].": ".$pair["type"].";\n";
  2000. $wrappers_create .= "object_".$pair["name"]." := ".$pair["type"].".CreateWithHandle(".$pair["name"].");\n";
  2001. $wrappers_release .= "object_".$pair["name"].".release;\n";
  2002. $variable_list .= "object_".$pair["name"].", ";
  2003. } else {
  2004. $variable_list .= $pair["name"].", ";
  2005. }
  2006. }
  2007. $variable_list = trim($variable_list, ", ");
  2008. $template = str_replace("[VARIABLES]", $wrappers_variables, $template);
  2009. $template = str_replace("[WRAPPERS_CREATE]", $wrappers_create, $template);
  2010. $template = str_replace("[WRAPPERS_RELEASE]", $wrappers_release, $template);
  2011. $template = str_replace("[PARAMS_LIST_WRAPPER]", "($variable_list)", $template);
  2012. $params = $this->MakeObjcTypeParamList($selector["method"]["param_array"], false);
  2013. $template = str_replace("[PARAMS_LIST]", "($params)", $template);
  2014. } else {
  2015. $template = str_replace("[PARAMS_HEADER]", "(_self: $this->objc_id_real; _cmd: SEL)", $template);
  2016. $template = str_replace("[PARAMS_LIST]", "", $template);
  2017. $template = str_replace("[PARAMS_LIST_WRAPPER]", "", $template);
  2018. $template = str_replace("[VARIABLES]", "", $template);
  2019. $template = str_replace("[WRAPPERS_CREATE]", "", $template);
  2020. $template = str_replace("[WRAPPERS_RELEASE]", "", $template);
  2021. }
  2022. $this->PrintOutput(0, "");
  2023. $this->PrintOutput(0, $template);
  2024. }
  2025. // add methods
  2026. foreach ($selectors as $selector) {
  2027. // FPC long name bug work-around
  2028. if (strlen($selector["name_pascal"]) > $this->maximum_method_length) continue;
  2029. $template = $this->template_method_add_runtime;
  2030. $template = str_replace("[CLASS]", $this->master_delegate_class, $template);
  2031. $template = str_replace("[NAME]", $selector["name_pascal"], $template);
  2032. $template = str_replace("[TYPES]", $selector["types"], $template);
  2033. $template = str_replace("[OBJC_METHOD]", $selector["name"], $template);
  2034. $this->PrintOutput(0, "");
  2035. $this->PrintOutput(0, $template);
  2036. }
  2037. }
  2038. $this->PrintOutput(0, "");
  2039. $this->PrintOutput(0, "{\$endif}");
  2040. print("* Printed delegate class to "."$this->root$this->out/foundation/$this->master_delegate_file.inc\n");
  2041. }
  2042. // Prints all externally defined symbols
  2043. function PrintExternalSymbols ($header) {
  2044. if (!$this->dump[$header["name"]]["types"]) return;
  2045. foreach ($this->dump[$header["name"]]["types"] as $key => $type_array) {
  2046. // External string constants
  2047. if ($key == "string_constant") {
  2048. $this->PrintOutput(0, "");
  2049. $this->PrintOutput(0, "{ External string constants }");
  2050. $this->PrintOutput(0, "var");
  2051. foreach ($type_array as $type) $this->PrintOutput(1, $type);
  2052. }
  2053. if ($key == "external_symbol") {
  2054. $this->PrintOutput(0, "");
  2055. $this->PrintOutput(0, "{ External symbols }");
  2056. $this->PrintOutput(0, "var");
  2057. foreach ($type_array as $type) $this->PrintOutput(1, $type);
  2058. }
  2059. }
  2060. }
  2061. // Prints all types in the header
  2062. function PrintTypes ($header) {
  2063. if (!$this->dump[$header["name"]]["types"]) return;
  2064. foreach ($this->dump[$header["name"]]["types"] as $key => $type_array) {
  2065. // External defines
  2066. if ($key == "defines") {
  2067. $this->PrintOutput(0, "");
  2068. $this->PrintOutput(0, "{ Defines }");
  2069. $this->PrintOutput(0, "const");
  2070. foreach ($type_array as $type) $this->PrintOutput(1, $type);
  2071. }
  2072. // External CFString constants
  2073. /*
  2074. if ($key == "string_constant") {
  2075. $this->PrintOutput(0, "");
  2076. $this->PrintOutput(0, "{ External string constants }");
  2077. $this->PrintOutput(0, "var");
  2078. foreach ($type_array as $type) $this->PrintOutput(1, $type);
  2079. }
  2080. */
  2081. // Named Enumerations
  2082. /*
  2083. if ($key == "named_enums") {
  2084. $this->PrintOutput(0, "");
  2085. $this->PrintOutput(0, "{ Sets }");
  2086. foreach ($type_array as $type) {
  2087. $this->PrintOutput(0, "");
  2088. $this->PrintOutput(0, "type");
  2089. $this->PrintOutput(1, $type);
  2090. }
  2091. }
  2092. */
  2093. // Enumerations
  2094. if ($key == "enums") {
  2095. $this->PrintOutput(0, "");
  2096. $this->PrintOutput(0, "{ Constants }");
  2097. foreach ($type_array as $block) {
  2098. $this->PrintOutput(0, "");
  2099. $this->PrintOutput(0, "const");
  2100. foreach ($block as $type) $this->PrintOutput(1, $type);
  2101. }
  2102. }
  2103. // Typedefs
  2104. if (($key == "typedef") || ($key == "named_enums")) {
  2105. $this->PrintOutput(0, "");
  2106. $this->PrintOutput(0, "{ Types }");
  2107. $this->PrintOutput(0, "type");
  2108. foreach ($type_array as $type) $this->PrintOutput(1, $type);
  2109. }
  2110. // CallBacks
  2111. if ($key == "callbacks") {
  2112. $this->PrintOutput(0, "");
  2113. $this->PrintOutput(0, "{ Callbacks }");
  2114. $this->PrintOutput(0, "type");
  2115. foreach ($type_array as $name => $type) $this->PrintOutput(1, "$name = $type");
  2116. }
  2117. }
  2118. }
  2119. // Prints all records in the header
  2120. function PrintRecords ($header) {
  2121. if (!$this->dump[$header["name"]]["types"]) return;
  2122. foreach ($this->dump[$header["name"]]["types"] as $key => $type_array) {
  2123. // Structures
  2124. if ($key == "structs") {
  2125. $this->PrintOutput(0, "");
  2126. $this->PrintOutput(0, "{ Records }");
  2127. foreach ($type_array as $type) {
  2128. $this->PrintOutput(0, "type");
  2129. $this->PrintOutput(1, $type);
  2130. }
  2131. }
  2132. }
  2133. }
  2134. // Prints all callbacks in the header
  2135. function PrintCallBacks ($header) {
  2136. if (!$this->dump[$header["name"]]["types"]) return;
  2137. foreach ($this->dump[$header["name"]]["types"] as $key => $type_array) {
  2138. if ($key == "callbacks") {
  2139. $this->PrintOutput(0, "");
  2140. $this->PrintOutput(0, "{ Callbacks }");
  2141. $this->PrintOutput(0, "type");
  2142. foreach ($type_array as $name => $type) $this->PrintOutput(1, "$name = $type");
  2143. }
  2144. }
  2145. }
  2146. // Prints all external functions in the header
  2147. function PrintFunctions ($header) {
  2148. if (!$this->dump[$header["name"]]["types"]) return;
  2149. foreach ($this->dump[$header["name"]]["types"] as $key => $type_array) {
  2150. if ($key == "functions") {
  2151. $this->PrintOutput(0, "");
  2152. $this->PrintOutput(0, "{ Functions }");
  2153. foreach ($type_array as $type) $this->PrintOutput(0, $type);
  2154. }
  2155. }
  2156. }
  2157. // Prints all classes from the header in reference format (not for compiling)
  2158. function PrintHeaderReference ($header, $path) {
  2159. $this->output = fopen($path, "w+");
  2160. //$this->PrintOutput(0, "{ ".ucfirst($header["framework"]).".framework ".$header["name"]." }");
  2161. $this->PrintOutput(0, "unit ".$header["name_clean"].";");
  2162. $this->PrintOutput(0, "interface");
  2163. $this->PrintOutput(0, "uses");
  2164. $this->PrintOutput(1, "ctypes, objc, MacOSAll;");
  2165. if ($header["classes"]) {
  2166. foreach ($header["classes"] as $class) {
  2167. $this->PrintOutput(0, "");
  2168. $this->PrintOutput(0, "type");
  2169. $this->PrintOutput(1, $class["name"]."Ref = ".$this->objc_id_real.";");
  2170. $this->PrintOutput(1, $class["name"]."Pointer = Pointer;");
  2171. }
  2172. }
  2173. // types
  2174. $this->PrintTypes($header);
  2175. $this->PrintRecords($header);
  2176. $this->PrintFunctions($header);
  2177. $this->PrintExternalSymbols($header);
  2178. if ($header["classes"]) {
  2179. foreach ($header["classes"] as $class) {
  2180. if (in_array($class["name"], $this->cocoa_classes)) {
  2181. $this->PrintOutput(0, "");
  2182. $this->PrintOutput(0, "type");
  2183. $this->PrintOutput(1, $class["name"]." = object(".$class["super"].")");
  2184. // print class-level methods
  2185. if (count($class["methods"]) > 0) {
  2186. $this->PrintOutput(0, "");
  2187. foreach ($class["methods"] as $method) {
  2188. $this->PrintOutput(2, $method["def"]);
  2189. }
  2190. }
  2191. // print category-level methods
  2192. if (count($class["categories"]) > 0) {
  2193. foreach ($class["categories"] as $name => $category) {
  2194. $this->PrintOutput(0, "");
  2195. $this->PrintOutput(2, "{ Category: $name }");
  2196. if ($category["methods"]) {
  2197. foreach ($category["methods"] as $method) {
  2198. $this->PrintOutput(2, $method["def"]);
  2199. }
  2200. }
  2201. }
  2202. }
  2203. $this->PrintOutput(1, "end;");
  2204. }
  2205. }
  2206. }
  2207. // print procedural protocols
  2208. if ($header["protocols"]) {
  2209. foreach ($header["protocols"] as $protocol) {
  2210. if ($protocol["methods"]) {
  2211. $this->PrintOutput(0, "");
  2212. $this->PrintOutput(0, "{ Protocol: ".$protocol["name"]." }");
  2213. foreach ($protocol["methods"] as $name => $method) {
  2214. if ($method["kind"] != "constructor") {
  2215. $this->PrintProtocolDeclaration($protocol, $method);
  2216. }
  2217. }
  2218. }
  2219. }
  2220. }
  2221. $this->PrintOutput(0, "");
  2222. $this->PrintOutput(0, "implementation");
  2223. $this->PrintOutput(0, "end.");
  2224. }
  2225. // Prints all classes from the header
  2226. public function PrintHeader ($header) {
  2227. global $version;
  2228. $this->output = fopen($header["path"], "w+");
  2229. $this->PrintOutput(0, "{ Parsed from ".ucfirst($header["framework"]).".framework ".$header["name"]." }");
  2230. $date = date("D M j G:i:s T Y");
  2231. $this->PrintOutput(0, "{ Version $version - $date }");
  2232. $this->PrintOutput(0, "");
  2233. $macro = strtoupper(substr($header["name"], 0, (strripos($header["name"], "."))));
  2234. if ($header["classes"]) {
  2235. $this->PrintOutput(0, "{\$ifdef HEADER}");
  2236. $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_H}");
  2237. $this->PrintOutput(0, "{\$define $macro"."_PAS_H}");
  2238. foreach ($header["classes"] as $class) {
  2239. $this->PrintOutput(0, "type");
  2240. // Make a id "reference" to each class which is an object but reveals the name of the class
  2241. if ($class["name"]."Ref" == $this->objc_id_real) {
  2242. $ref = $this->objc_id_base; // replace duplicates with the "base id"
  2243. } else {
  2244. $ref = $this->objc_id_real;
  2245. }
  2246. $this->PrintOutput(1, $class["name"]."Ref = ".$ref.";");
  2247. // Make a pointer to each class
  2248. $this->PrintOutput(1, $class["name"]."Pointer = Pointer;");
  2249. }
  2250. $this->PrintOutput(0, "");
  2251. $this->PrintOutput(0, "{\$endif}");
  2252. $this->PrintOutput(0, "{\$endif}");
  2253. }
  2254. $this->PrintOutput(0, "");
  2255. $this->PrintOutput(0, "{\$ifdef TYPES}");
  2256. $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_T}");
  2257. $this->PrintOutput(0, "{\$define $macro"."_PAS_T}");
  2258. $this->PrintTypes($header);
  2259. $this->PrintOutput(0, "");
  2260. $this->PrintOutput(0, "{\$endif}");
  2261. $this->PrintOutput(0, "{\$endif}");
  2262. $this->PrintOutput(0, "");
  2263. $this->PrintOutput(0, "{\$ifdef RECORDS}");
  2264. $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_R}");
  2265. $this->PrintOutput(0, "{\$define $macro"."_PAS_R}");
  2266. $this->PrintRecords($header);
  2267. $this->PrintOutput(0, "");
  2268. $this->PrintOutput(0, "{\$endif}");
  2269. $this->PrintOutput(0, "{\$endif}");
  2270. $this->PrintOutput(0, "");
  2271. $this->PrintOutput(0, "{\$ifdef FUNCTIONS}");
  2272. $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_F}");
  2273. $this->PrintOutput(0, "{\$define $macro"."_PAS_F}");
  2274. $this->PrintFunctions($header);
  2275. $this->PrintOutput(0, "");
  2276. $this->PrintOutput(0, "{\$endif}");
  2277. $this->PrintOutput(0, "{\$endif}");
  2278. $this->PrintOutput(0, "");
  2279. $this->PrintOutput(0, "{\$ifdef CALLBACKS}");
  2280. $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_F}");
  2281. $this->PrintOutput(0, "{\$define $macro"."_PAS_F}");
  2282. $this->PrintCallBacks($header);
  2283. $this->PrintOutput(0, "");
  2284. $this->PrintOutput(0, "{\$endif}");
  2285. $this->PrintOutput(0, "{\$endif}");
  2286. $this->PrintOutput(0, "");
  2287. $this->PrintOutput(0, "{\$ifdef EXTERNAL_SYMBOLS}");
  2288. $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_T}");
  2289. $this->PrintOutput(0, "{\$define $macro"."_PAS_T}");
  2290. $this->PrintExternalSymbols($header);
  2291. $this->PrintOutput(0, "");
  2292. $this->PrintOutput(0, "{\$endif}");
  2293. $this->PrintOutput(0, "{\$endif}");
  2294. if ($header["classes"]) {
  2295. $this->PrintOutput(0, "");
  2296. $this->PrintOutput(0, "{\$ifdef FORWARD}");
  2297. foreach ($header["classes"] as $class) {
  2298. // if the class contains methods make a forward declaration, otherwise a dummy class to NSObject
  2299. if (count($class["all"]) > 0) {
  2300. $this->PrintOutput(1, $class["name"]." = class;");
  2301. } else {
  2302. $this->PrintOutput(1, $class["name"]." = NSObject;");
  2303. }
  2304. }
  2305. $this->PrintOutput(0, "");
  2306. $this->PrintOutput(0, "{\$endif}");
  2307. }
  2308. if ($header["classes"]) {
  2309. $this->PrintOutput(0, "");
  2310. $this->PrintOutput(0, "{\$ifdef CLASSES}");
  2311. $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_C}");
  2312. $this->PrintOutput(0, "{\$define $macro"."_PAS_C}");
  2313. foreach ($header["classes"] as $class) {
  2314. if (in_array($class["name"], $this->cocoa_classes)) {
  2315. $this->PrintClass($class);
  2316. //print(" - Printed class ".$class["name"]."\n");
  2317. }
  2318. }
  2319. $this->PrintOutput(0, "");
  2320. $this->PrintOutput(0, "{\$endif}");
  2321. $this->PrintOutput(0, "{\$endif}");
  2322. }
  2323. $this->PrintOutput(0, "");
  2324. $this->PrintOutput(0, "{\$ifdef PROTOCOLS}");
  2325. $this->PrintOutput(0, "{\$ifndef $macro"."_PAS_P}");
  2326. $this->PrintOutput(0, "{\$define $macro"."_PAS_P}");
  2327. $this->PrintHeaderProtocols($header, false);
  2328. $this->PrintOutput(0, "");
  2329. $this->PrintOutput(0, "{\$endif}");
  2330. $this->PrintOutput(0, "{\$endif}");
  2331. $this->PrintOutput(0, "");
  2332. $this->PrintOutput(0, "{\$ifdef IMPLEMENTATION}");
  2333. $this->PrintHeaderProtocols($header, true);
  2334. if ($header["classes"]) {
  2335. foreach ($header["classes"] as $class) {
  2336. if (in_array($class["name"], $this->cocoa_classes)) {
  2337. $this->PrintClassImplementation($class);
  2338. }
  2339. }
  2340. }
  2341. $this->PrintOutput(0, "{\$endif}");
  2342. }
  2343. // Prints all headers parsed
  2344. function PrintAllHeaders ($output_path, $ignore_output, $only_files, $print_header_references) {
  2345. foreach ($this->dump as $file => $header) {
  2346. if (eregi("^[a-zA-Z]+\.h", $file)) {
  2347. // ignore these files
  2348. if (@in_array($header["path_partial"], $ignore_output)) continue;
  2349. // only parse these files
  2350. if ((@count($only_files) > 0) && (@!in_array($header["name"], $only_files))) continue;
  2351. $name_clean = substr($file, 0, (strripos($file, ".")));
  2352. // assign output path
  2353. if ($output_path != "") $header["path"] = $output_path."/".$name_clean.".inc";
  2354. $this->PrintHeader($header);
  2355. if ($print_header_references) $this->PrintHeaderReference($header, $this->root.$this->out."/reference/".$name_clean.".pas");
  2356. print("* Printed $name_clean.h to ".$header["path"]."\n");
  2357. }
  2358. }
  2359. }
  2360. /**
  2361. * PARSING METHODS
  2362. */
  2363. // Insert macro blocks to replace c-style blocks
  2364. function InsertMacroBlocks ($line, &$in_macro_block) {
  2365. // only insert if we are in a block already.
  2366. // NOTE: this does not handle nesting!
  2367. if ($in_macro_block) {
  2368. // macro else statment
  2369. if (eregi("#else", $line)) {
  2370. return "{\$else}";
  2371. }
  2372. // macro endif statment
  2373. if (eregi("#endif", $line)) {
  2374. $in_macro_block = false;
  2375. return "{\$endif}";
  2376. }
  2377. }
  2378. foreach ($this->macro_blocks as $key => $value) {
  2379. if (eregi($key, $line, $captures)) {
  2380. $in_macro_block = true;
  2381. // replace the c-macro with a Pascal version
  2382. if ($value == "*") {
  2383. $captures[0] = trim($captures[0], "#");
  2384. return "{\$".$captures[0]."}";
  2385. } else {
  2386. return "{".$value."}";
  2387. }
  2388. }
  2389. }
  2390. }
  2391. function ParseInstanceVariables ($line, &$struct) {
  2392. $field = null;
  2393. $field_bitpacked = false;
  2394. //print("$line\n");
  2395. // insert macros
  2396. if ($macro = $this->InsertMacroBlocks($line, $this->inside_macro_block)) {
  2397. if ($struct["valid"]) {
  2398. $struct["fields"][] = $macro;
  2399. return null;
  2400. } else {
  2401. return $macro;
  2402. }
  2403. }
  2404. // got struct
  2405. if (eregi("^[[:space:]]*struct.*{", $line)) {
  2406. $struct["valid"] = true;
  2407. return null;
  2408. }
  2409. if (eregi("^[[:space:]]*}[[:space:]]*([a-zA-Z_0-9]+);", $line, $captures)) {
  2410. $struct["name"] = "_".trim($captures[1], " ");
  2411. //print_r($struct);
  2412. return "struct";
  2413. }
  2414. // set field prefix to protect scope
  2415. if (!$struct["valid"]) $field_prefix = "_";
  2416. // remove null-defined macros:
  2417. $line = str_ireplace($this->null_macros, "", $line);
  2418. // replace garbage collector hints in the field
  2419. $line = $this->ReplaceGarbageCollectorHints($line, $garbage_collector_hint);
  2420. if (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_* ]+).*;", $line, $captures)) { // double-word single
  2421. $name = trim($captures[3], "* ");
  2422. $name = str_replace(" ", "", $name);
  2423. $name = str_replace(" ", "", $name);
  2424. if (eregi("^[[:space:]]*struct", $captures[1])) {
  2425. $type = $captures[2];
  2426. } else {
  2427. $type = $captures[1]." ".$captures[2];
  2428. }
  2429. $type = $this->ReplaceObjcType($type);
  2430. $type = $this->SwapObjcTypeWithReal($type);
  2431. $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
  2432. if ($this->IsKeywordReserved($name)) $name .= "_";
  2433. if ($captures[3][0] == "*") $this->ReplacePointerType($type);
  2434. $field = "$field_prefix$name: $type;";
  2435. $field = $this->MakeFieldInlineArray($field, $line, $name, $type);
  2436. $field = eregi_replace("<.*>", "", $field);
  2437. } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_* ]+)(.*);", $line, $captures)) { // double-word type list
  2438. $name = trim($captures[2], "* ");
  2439. $name = str_replace(" ", "", $name);
  2440. $name = str_replace(" ", "", $name);
  2441. $type = $this->ReplaceObjcType($captures[1]);
  2442. $type = $this->SwapObjcTypeWithReal($type);
  2443. $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
  2444. if ($this->IsKeywordReserved($name)) $name .= "_";
  2445. if ($captures[2][0] == "*") $this->ReplacePointerType($type);
  2446. $field = "$field_prefix$name: $type;";
  2447. $field = $this->MakeFieldInlineArray($field, $line, $name, $type);
  2448. $field = eregi_replace("<.*>", "", $field);
  2449. } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_*]+)(.*);", $line, $captures)) { // single word type list
  2450. $name = trim($captures[2], "* ");
  2451. $name = str_replace(" ", "", $name);
  2452. $name = str_replace(" ", "", $name);
  2453. $type = $this->ReplaceObjcType($captures[1]);
  2454. $type = $this->SwapObjcTypeWithReal($type);
  2455. $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
  2456. if ($this->IsKeywordReserved($name)) $name .= "_";
  2457. if ($captures[2][0] == "*") $this->ReplacePointerType($type);
  2458. $type = trim($type, "*");
  2459. $field = "$field_prefix$name: $type;";
  2460. $field = $this->MakeFieldInlineArray($field, $line, $name, $type);
  2461. $field = eregi_replace("<.*>", "", $field);
  2462. }
  2463. // mark the field as having a garbage collector field
  2464. if ($garbage_collector_hint) $field = "$field {garbage collector: $garbage_collector_hint }";
  2465. // return field
  2466. if ($struct["valid"]) {
  2467. if ($field_bitpacked) $struct["bitpacked"] = true;
  2468. $struct["fields"][] = $field;
  2469. } else {
  2470. return $field;
  2471. }
  2472. }
  2473. // Parses a struct field into a list
  2474. function ParseStructList ($input, $name, $type) {
  2475. $field = "";
  2476. $list = explode(",", $input);
  2477. if (count($list) > 1) {
  2478. $field = " ";
  2479. foreach ($list as $key) {
  2480. $key = trim($key, " ");
  2481. $field .= "$key, ";
  2482. }
  2483. $field = rtrim($field, ", ");
  2484. $field .= ": $type;\n";
  2485. } else {
  2486. $field = " $name: $type;\n";
  2487. }
  2488. return $field;
  2489. }
  2490. // Parse external symbols, enums and typedef's from the header
  2491. function ParseHeaderTypes ($file) {
  2492. $contents = ReadTextFile($file);
  2493. $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
  2494. $field_bitpacked = false;
  2495. $lines = explode("\n", $contents);
  2496. foreach ($lines as $line) {
  2497. // skip blocks
  2498. if ($this->SkipBlock($line)) continue;
  2499. // garbage collector hints
  2500. $line = $this->ReplaceGarbageCollectorHints($line, $garbage_collector_hint);
  2501. // remove macros
  2502. $line = $this->RemoveOSVersionMacros($line);
  2503. // remove comments
  2504. $line = $this->RemoveComments($line);
  2505. $line = trim($line, " ");
  2506. if ($got_struct) {
  2507. // insert macros
  2508. if ($macro = $this->InsertMacroBlocks($line, $this->inside_macro_block)) $struct_fields .= "$macro\n";
  2509. // collect fields
  2510. if (eregi("^[[:space:]]*([a-zA-Z0-9_*]+)[[:space:]]*[*]*\((.*)\)\((.*)\);", $line, $captures)) { // function pointer (callback)
  2511. //continue;
  2512. $name = trim($captures[2], "*");
  2513. $result = $this->ReplaceNSTypesWithReal($captures[1]);
  2514. $result = $this->ReplaceObjcType($result);
  2515. $result = ": ".$this->SwapObjcTypeWithReal($result);
  2516. if ($this->IsKeywordReserved($name)) $name .= "_";
  2517. if ($captures[1] == "void") {
  2518. $kind = "procedure";
  2519. $result = "";
  2520. } else {
  2521. $kind = "function";
  2522. }
  2523. // ??? convert params to Pascal
  2524. //$method = $this->ConvertFunctionPointerToPascal($result, $captures[3]);
  2525. //$params = $method["param_string_clean"];
  2526. $params = "context: Pointer {bad params!!}";
  2527. $struct_fields .= " $name: $kind ($params)$result; cdecl;\n";
  2528. //print("$name: $kind ($params)$result; cdecl;\n");
  2529. } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_* ]+)(.*);", $line, $captures)) { // double-word single
  2530. $name = trim($captures[3], "* ");
  2531. $name = str_replace(" ", "", $name);
  2532. $name = str_replace(" ", "", $name);
  2533. $type = $captures[1]." ".$captures[2];
  2534. $type = $this->ReplaceObjcType($type);
  2535. $type = $this->SwapObjcTypeWithReal($type);
  2536. $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
  2537. if ($this->IsKeywordReserved($name)) $name .= "_";
  2538. if ($captures[3][0] == "*") $this->ReplacePointerType($type);
  2539. //$struct_fields .= " $name: $type;\n";
  2540. $struct_fields .= $this->ParseStructList($captures[3]+$captures[4], $name, $type);
  2541. } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_* ]+)(.*);", $line, $captures)) { // double-word type list
  2542. $name = trim($captures[2], "* ");
  2543. $name = str_replace(" ", "", $name);
  2544. $name = str_replace(" ", "", $name);
  2545. $type = $this->ReplaceObjcType($captures[1]);
  2546. $type = $this->SwapObjcTypeWithReal($type);
  2547. $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
  2548. if ($this->IsKeywordReserved($name)) $name .= "_";
  2549. if ($captures[2][0] == "*") $this->ReplacePointerType($type);
  2550. $struct_fields .= $this->ParseStructList("$captures[2]$captures[3]", $name, $type);
  2551. } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_* ]+)(.*);", $line, $captures)) { // single word type list
  2552. $name = trim($captures[2], "* ");
  2553. $captures[1] = str_replace(" ", "", $captures[1]);
  2554. $captures[1] = str_replace(" ", "", $captures[1]);
  2555. $type = $this->ReplaceObjcType($captures[1]);
  2556. $type = $this->SwapObjcTypeWithReal($type);
  2557. $type = $this->MakeFieldBitPacked($type, $line, $field_bitpacked);
  2558. if ($this->IsKeywordReserved($name)) $name .= "_";
  2559. if ($captures[2][0] == "*") $this->ReplacePointerType($type);
  2560. //$struct_fields .= " $name: $type;\n";
  2561. $struct_fields .= $this->ParseStructList($captures[2], $name, $type);
  2562. }
  2563. // got end of struct
  2564. if (ereg("^}[[:space:]]*([a-zA-Z_0-9]+);", $line, $captures)) {
  2565. if ($struct_name == "") {
  2566. $struct_name = $captures[1];
  2567. $make_pointer = true;
  2568. } else {
  2569. $struct_type = $captures[1];
  2570. }
  2571. if ($field_bitpacked) {
  2572. $struct = "$struct_name = $this->bitpacked_record_keyword\n";
  2573. } else {
  2574. $struct = "$struct_name = $this->record_keyword\n";
  2575. }
  2576. $struct .= $struct_fields;
  2577. $struct .= " end;\n";
  2578. if (($struct_type) && ($struct_name != $struct_type)) {
  2579. $struct .= "$struct_type = $struct_name;\n";
  2580. // SEE NOTE BELOW
  2581. //$struct .= $struct_type."Pointer = ^$struct_type;\n";
  2582. $make_pointer = false;
  2583. }
  2584. // make an extra pointer for us since Pascal may need it
  2585. // NOTE: remove this until we can protect against duplicate types
  2586. //if ($make_pointer) $struct .= $struct_name."Pointer = ^$struct_name;\n";
  2587. $this->dump[$file_name]["types"]["structs"][] = $struct;
  2588. $this->dump["global_structs"][] = $struct_name;
  2589. $got_struct = false;
  2590. $field_bitpacked = false;
  2591. }
  2592. }
  2593. // got struct
  2594. if (ereg("^typedef struct(.*){", $line, $captures)) {
  2595. $struct_name = trim($captures[1], " ");
  2596. $struct_type = null;
  2597. $struct_fields = "";
  2598. $make_pointer = false;
  2599. $got_struct = true;
  2600. }
  2601. // integer #define
  2602. if (ereg("#define[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([0-9.]+)", $line, $captures)) {
  2603. $this->dump[$file_name]["types"]["defines"][] = $captures[1]." = ".$captures[2].";";
  2604. }
  2605. // parse enum fields
  2606. if (($got_enum) || ($got_named_enum)) {
  2607. //print($line."\n");
  2608. // insert macros
  2609. //if ($macro = $this->InsertMacroBlocks($line, $this->inside_macro_block)) $this->dump[$file_name]["types"]["enums"][$block_count][] = $macro;
  2610. if (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*=[[:space:]]*([a-zA-Z_]+)[,]*[[:space:]]*$", $line, $captures)) { // string value
  2611. $captures[2] = trim($captures[2], ", ");
  2612. $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$captures[2].";";
  2613. } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*=[[:space:]]*([0-9-]+)[,]*[[:space:]]*$", $line, $captures)) { // integer value
  2614. $captures[2] = trim($captures[2], ", ");
  2615. $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$captures[2].";";
  2616. } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*=[[:space:]]*([0-9]+[xX]+[a-fA-F0-9]+)", $line, $captures)) { // hexadecimal value
  2617. $captures[2] = trim($captures[2], ", ");
  2618. $captures[2] = eregi_replace("^0x", "$", $captures[2]);
  2619. $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$captures[2].";";
  2620. } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*=[[:space:]]*([0-9]+[[:space:]]*<<[[:space:]]*[0-9]+)", $line, $captures)) { // << shl value, no ()
  2621. $captures[2] = str_replace("<<", " shl ", $captures[2]);
  2622. $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$captures[2].";";
  2623. } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*=[[:space:]]*\(([0-9]+[[:space:]]*<<[[:space:]]*[0-9]+)\)", $line, $captures)) { // << shl value
  2624. $captures[2] = trim($captures[2], ", ");
  2625. $captures[2] = str_replace("<<", " shl ", $captures[2]);
  2626. $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$captures[2].";";
  2627. } elseif (ereg("^[[:space:]]*([a-zA-Z0-9_]+)[[:space:]]*[,}]*[[:space:]]*$", $line, $captures)) { // non-value
  2628. // omit lines which started nested structures.
  2629. // bad practice but the single-line regex parser can't handle them
  2630. if (!eregi("[=|]+", $line)) {
  2631. $captures[1] = trim($captures[1], ", ");
  2632. $this->dump[$file_name]["types"]["enums"][$block_count][] = $captures[1]." = ".$auto_increment.";";
  2633. $auto_increment ++;
  2634. }
  2635. }
  2636. // found the end
  2637. if (ereg("^};", $line)) $got_enum = false;
  2638. }
  2639. // ==== got enum ===
  2640. if (ereg("^enum {", $line)) {
  2641. $got_enum = true;
  2642. $block_count ++;
  2643. $auto_increment = 0;
  2644. }
  2645. // terminate named enum
  2646. if ($got_named_enum) {
  2647. if (ereg("^}[[:space:]]*([a-zA-Z0-9_]+);", $line, $captures)) {
  2648. $got_named_enum = false;
  2649. $named_enum = trim($named_enum, ", \n");
  2650. $this->dump[$file_name]["types"]["named_enums"][] = "$captures[1] = culong;";
  2651. $this->dump["global_types"][$captures[1]] = $captures[1];
  2652. }
  2653. }
  2654. // ==== got named enum ===
  2655. if (ereg("^typedef enum {", $line)) {
  2656. $got_named_enum = true;
  2657. $named_enum = "";
  2658. $auto_increment = 0;
  2659. $block_count ++;
  2660. }
  2661. // ==== external string constant ===
  2662. if (eregi("^($this->external_string_macros)+[[:space:]]+NSString[[:space:]]+\*[[:space:]]*(const)*[[:space:]]*([a-zA-Z_]+);", $line, $captures)) {
  2663. $name = $captures[3];
  2664. if (in_array($name, $this->ignore_symbol)) continue;
  2665. $this->dump[$file_name]["types"]["string_constant"][] = "$name: $this->string_macro; external name '_$name';";
  2666. }
  2667. // ==== external symbol ===
  2668. if (eregi("^($this->external_string_macros)+[[:space:]]+([a-zA-Z_ ]+)[[:space:]]+([a-zA-Z_]+);", $line, $captures)) {
  2669. $name = $captures[3];
  2670. $type = $captures[2];
  2671. // ignore symbols
  2672. if (in_array($name, $this->ignore_symbol)) continue;
  2673. $type = istr_replace_word("const", "", $type);
  2674. $type = trim($type, " ");
  2675. $this->dump[$file_name]["types"]["external_symbol"][] = "$name: $type; external name '_$name';";
  2676. }
  2677. // ==== external procedures ===
  2678. if (ereg("^($this->external_string_macros)+[[:space:]]+(.*)[[:space:]]+(\*)*([a-zA-Z0-9_]+)\((.*)\)", $line, $captures)) {
  2679. $result = $this->ConvertReturnType($captures[2]);
  2680. $name = $captures[4];
  2681. $params = "";
  2682. $captures[2] = trim($captures[2], " ");
  2683. $captures[5] = trim($captures[5], " ");
  2684. // ignore symbols
  2685. if (in_array($name, $this->ignore_symbol)) continue;
  2686. if ($captures[5] != "void") $params = "(".$this->ConvertCParamsPascal($captures[5]).")";
  2687. if ($captures[2] == "void") {
  2688. $this->dump[$file_name]["types"]["functions"][] = "procedure $name$params; cdecl; external name '$name';";
  2689. } else {
  2690. $this->dump[$file_name]["types"]["functions"][] = "function $name$params: $result; cdecl; external name '$name';";
  2691. }
  2692. }
  2693. // ==== got typedef ===
  2694. if (ereg("^typedef[[:space:]]+struct[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_]+);", $line, $captures)) { // defined struct type
  2695. $real_type = $captures[1];
  2696. $struct_type = $captures[1];
  2697. $new_type = $captures[2];
  2698. $this->AddTypeDef($this->dump[$file_name], "$struct_type = Pointer;");
  2699. $struct_type = $this->ReplaceObjcType($struct_type);
  2700. $struct_type = $this->SwapObjcTypeWithReal($struct_type);
  2701. $this->AddTypeDef($this->dump[$file_name], "$new_type = $struct_type;");
  2702. $this->dump["global_types"][$struct_type] = "Pointer";
  2703. $this->dump["global_types"][$new_type] = $real_type;
  2704. } elseif (ereg("^typedef[[:space:]]+struct[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_*]+);", $line, $captures)) { // pointer to struct
  2705. $real_type = $captures[1];
  2706. $clean_name = trim($captures[2], "*");
  2707. $pointer_type = $captures[1];
  2708. // ??? maybe check to see if this type exists like NSRect *NSRect is NSRectPointer which exists
  2709. $pointer_type = "Pointer";
  2710. //$captures[2] = $this->FormatObjcType($captures[2], $modifiers);
  2711. //$this->dump[$file_name]["types"]["typedef"][] = "$pointer_type = Pointer;";
  2712. $this->AddTypeDef($this->dump[$file_name], "$clean_name = $pointer_type;");
  2713. //$this->dump["global_types"][$pointer_type] = "Pointer";
  2714. $this->dump["global_types"][$clean_name] = $real_type;
  2715. } elseif (ereg("^typedef[[:space:]]+(const)*[[:space:]]*struct[[:space:]]+([a-zA-Z0-9_*]+)[[:space:]]+([a-zA-Z0-9_]+);", $line, $captures)) { // struct type (complex)
  2716. $real_type = $captures[1];
  2717. $captures[2] = $this->FormatObjcType($captures[2], $modifiers);
  2718. $this->AddTypeDef($this->dump[$file_name], $captures[3]." = ".$captures[2].";");
  2719. $this->dump["global_types"][$captures[3]] = $real_type;
  2720. } elseif (ereg("^typedef[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_*]+);", $line, $captures)) { // single-word type
  2721. $real_type = $captures[1];
  2722. // type is a pointer
  2723. if ($captures[2][0] == "*") {
  2724. $captures[2] = trim($captures[2], "*");
  2725. $captures[1] = $this->ReplaceObjcType($captures[1]);
  2726. $captures[1] = $this->SwapObjcTypeWithReal($captures[1]);
  2727. $this->AddTypeDef($this->dump[$file_name], $captures[2]." = ^".$captures[1].";");
  2728. $this->dump["global_types"][$captures[2]] = $real_type;
  2729. } else {
  2730. $captures[2] = trim($captures[2], "*");
  2731. $captures[1] = $this->ReplaceObjcType($captures[1]);
  2732. $captures[1] = $this->SwapObjcTypeWithReal($captures[1]);
  2733. $this->AddTypeDef($this->dump[$file_name],$captures[2]." = ".$captures[1].";");
  2734. $this->dump["global_types"][$captures[2]] = $real_type;
  2735. }
  2736. } elseif (ereg("^typedef[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_]+)[[:space:]]+([a-zA-Z0-9_*]+);", $line, $captures)) { // double-word type
  2737. $real_type = $captures[1];
  2738. $captures[3] = trim($captures[3], "*");
  2739. $long_type = $captures[1]." ".$captures[2];
  2740. $long_type = $this->ReplaceObjcType($long_type);
  2741. $long_type = $this->SwapObjcTypeWithReal($long_type);
  2742. $this->AddTypeDef($this->dump[$file_name], $captures[3]." = $long_type;");
  2743. $this->dump["global_types"][$captures[3]] = $real_type;
  2744. }
  2745. }
  2746. //print_r($this->dump[$file_name]["types"]);
  2747. }
  2748. // Parse all protocols in a header
  2749. function ParseHeaderProtocols ($file) {
  2750. $contents = ReadTextFile($file);
  2751. $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
  2752. $lines = explode("\n", $contents);
  2753. foreach ($lines as $line) {
  2754. // parse protocol
  2755. if ($got_protocol) {
  2756. // remove comments
  2757. $line = $this->RemoveComments($line);
  2758. // found property
  2759. if (eregi($this->regex_objc_property, $line, $captures)) {
  2760. $property = $this->ParseClassProperty($current_protocol, $captures);
  2761. if ($property["setter"]) {
  2762. $this->current_header["protocols"][$current_protocol]["methods"][$method["objc_method"]] = $property["setter"];
  2763. }
  2764. if ($property["getter"]) {
  2765. $this->current_header["protocols"][$current_protocol]["methods"][$method["objc_method"]] = $property["getter"];
  2766. }
  2767. continue;
  2768. }
  2769. // found method
  2770. $method = null;
  2771. if (eregi($this->regex_objc_method_params, $line, $captures)) {
  2772. $method = $this->ConvertObjcMethodToPascal($current_protocol, $line, $captures, array(), true);
  2773. } elseif (eregi($this->regex_objc_method_no_params, $line, $captures)) {
  2774. $method = $this->ConvertObjcMethodToPascal($current_protocol, $line, $captures, array(), false);
  2775. }
  2776. // append to classes
  2777. if (($method) && (!in_array($current_protocol, $this->ignore_categories)) && (!in_array($method["name"], $this->ignore_methods)) ) {
  2778. $this->current_header["protocols"][$current_protocol]["methods"][$method["objc_method"]] = $method;
  2779. }
  2780. // found the end
  2781. if (ereg("^@end", $line)) $got_protocol = false;
  2782. }
  2783. // got protocol
  2784. if ((eregi($this->regex_objc_protocol, $line, $captures)) && (!eregi(".*;$", $line))) {
  2785. $got_protocol = true;
  2786. $current_protocol = $captures[1];
  2787. print("+ Protocol $current_protocol\n");
  2788. $this->current_header["protocols"][$current_protocol]["name"] = $captures[1];
  2789. }
  2790. }
  2791. //print_r($this->current_class);
  2792. }
  2793. // Parse all categories in a header
  2794. function ParseHeaderCategories ($file) {
  2795. $contents = ReadTextFile($file);
  2796. $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
  2797. $lines = explode("\n", $contents);
  2798. foreach ($lines as $line) {
  2799. // parse category
  2800. if ($got_category) {
  2801. // remove comments
  2802. $line = $this->RemoveComments($line);
  2803. // found property
  2804. if (eregi($this->regex_objc_property, $line, $captures)) {
  2805. $property = $this->ParseClassProperty($current_category, $captures);
  2806. if ($property["setter"]) {
  2807. if ($this->AddMethodToClass($property["setter"], $this->current_class)) {
  2808. $this->dump[$category_owner]["classes"][$current_class]["categories"][$current_category]["methods"][] = $property["setter"];
  2809. }
  2810. }
  2811. if ($property["getter"]) {
  2812. if ($this->AddMethodToClass($property["getter"], $this->current_class)) {
  2813. $this->dump[$category_owner]["classes"][$current_class]["categories"][$current_category]["methods"][] = $property["getter"];
  2814. }
  2815. }
  2816. continue;
  2817. }
  2818. // found method
  2819. $method = null;
  2820. if (eregi($this->regex_objc_method_params, $line, $captures)) {
  2821. $method = $this->ConvertObjcMethodToPascal($current_category, $line, $captures, $this->GetProtectedKeywords($this->current_class), true);
  2822. } elseif (eregi($this->regex_objc_method_no_params, $line, $captures)) {
  2823. $method = $this->ConvertObjcMethodToPascal($current_category, $line, $captures, $this->GetProtectedKeywords($this->current_class), false);
  2824. }
  2825. // append to classes
  2826. if (($method) && (!in_array($method["name"], $this->ignore_categories))) {
  2827. if ($current_class) {
  2828. if ($this->AddMethodToClass($method, $this->current_class)) {
  2829. $this->dump[$category_owner]["classes"][$current_class]["categories"][$current_category]["methods"][] = $method;
  2830. }
  2831. } else {
  2832. // add base categories to NSObject
  2833. if (in_array($current_category, $this->base_categories)) {
  2834. if ($this->AddMethodToClass($method, $this->dump["NSObject.h"]["classes"]["NSObject"])) {
  2835. $this->dump["NSObject.h"]["classes"]["NSObject"]["categories"][$current_category]["methods"][] = $method;
  2836. }
  2837. }
  2838. $this->dump["categories"][$current_category]["methods"][$method["objc_method"]] = $method;
  2839. }
  2840. }
  2841. // found the end
  2842. if (ereg("^@end", $line)) $got_category = false;
  2843. }
  2844. // got category
  2845. if (eregi($this->regex_objc_category, $line, $captures)) {
  2846. // ??? if the current header is NSObject, then we DO want to accept these categories, they are NOT delegates this time...
  2847. // append category to it's super class
  2848. $category_owner = $this->FindCategoryHeader($captures[1]);
  2849. if (($category_owner) && ($captures[1] != "NSObject")) {
  2850. $got_category = true;
  2851. $current_category = $captures[2];
  2852. $current_class = $captures[1];
  2853. $this->current_class = &$this->dump[$category_owner]["classes"][$current_class];
  2854. $this->dump[$category_owner]["classes"][$current_class]["categories"][$current_category]["name"] = $captures[2];
  2855. $this->dump[$category_owner]["classes"][$current_class]["categories"][$current_category]["super"] = $captures[1];
  2856. print(" -> Category $current_category belongs to $current_class in $category_owner\n");
  2857. } else {
  2858. if ($captures[1] == "NSObject") {
  2859. print(" + Category ".$captures[2]."->".$captures[1]." belongs to NSObject\n");
  2860. $got_category = true;
  2861. } else {
  2862. $this->warning_count ++;
  2863. print("# WARNING: Category ".$captures[2]." (".$captures[1].") has no header\n");
  2864. $got_category = false;
  2865. }
  2866. $current_category = $captures[2];
  2867. $current_class = null;
  2868. $this->dump["categories"][$current_category]["name"] = $captures[2];
  2869. $this->dump["categories"][$current_category]["super"] = $captures[1];
  2870. }
  2871. }
  2872. }
  2873. //print_r($this->current_class);
  2874. }
  2875. // Parse all "pre-defined" category methods in a header
  2876. function PreparseCategoryMethods ($file) {
  2877. $contents = ReadTextFile($file);
  2878. $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
  2879. $lines = explode("\n", $contents);
  2880. foreach ($lines as $line) {
  2881. // parse category
  2882. if ($got_category) {
  2883. // found method
  2884. $method = null;
  2885. if (eregi($this->regex_objc_method_params, $line, $captures)) {
  2886. $method = $this->ConvertObjcMethodToPascal($current_category, $line, $captures, array(), true);
  2887. } elseif (eregi($this->regex_objc_method_no_params, $line, $captures)) {
  2888. $method = $this->ConvertObjcMethodToPascal($current_category, $line, $captures, array(), false);
  2889. }
  2890. // append to classes
  2891. if (($method) && ($current_class)) {
  2892. $this->dump[$category_owner]["category_methods"][] = $method["name"];
  2893. //print($method["name"]."\n");
  2894. }
  2895. // found the end
  2896. if (ereg("^@end", $line)) $got_category = false;
  2897. }
  2898. // got category
  2899. if (eregi($this->regex_objc_category, $line, $captures)) {
  2900. $category_owner = $this->FindCategoryHeader($captures[1]);
  2901. if ($category_owner) {
  2902. $got_category = true;
  2903. $current_category = $captures[2];
  2904. $current_class = $captures[1];
  2905. } else {
  2906. $current_class = null;
  2907. }
  2908. }
  2909. }
  2910. return $this->dump[$category_owner]["category_methods"];
  2911. }
  2912. // Preparses a class for protected keywords
  2913. function PreparseClass ($lines, $line_count) {
  2914. $protected_keywords = array();
  2915. for ($i=$line_count; $i < count($lines); $i++) {
  2916. $line = $lines[$i - 1];
  2917. // found method
  2918. if (eregi($this->regex_objc_method_params, $line, $captures)) {
  2919. $method = $this->ConvertObjcMethodToPascal($current, $line, $captures, $protected_keywords, true);
  2920. $this->current_class["protected_keywords"][] = $method["name"];
  2921. } elseif (eregi($this->regex_objc_method_no_params, $line, $captures)) {
  2922. $method = $this->ConvertObjcMethodToPascal($current, $line, $captures, $protected_keywords, false);
  2923. $this->current_class["protected_keywords"][] = $method["name"];
  2924. }
  2925. // class ended
  2926. if (ereg("^@end", $line)) return $protected_keywords;
  2927. }
  2928. }
  2929. // Gets the preferred property name from attributes
  2930. function GetPropertyName ($kind, $params, &$name) {
  2931. foreach ($params as $value) {
  2932. $pair = explode("=", $value);
  2933. if ($pair[0] == $kind) {
  2934. $name = $pair[1];
  2935. return true;
  2936. break;
  2937. }
  2938. }
  2939. }
  2940. // Convert a method return type to Pascal
  2941. function ConvertReturnType ($type) {
  2942. $type = trim($type, " ");
  2943. $type = $this->ReplaceObjcType($type);
  2944. // if the type was not converted remove the * and process further
  2945. $type = trim($type, "* ");
  2946. $type = $this->ReplaceObjcType($type);
  2947. // format the return type again to make sure it's clean
  2948. $type = $this->FormatObjcType($type, $null_modifier);
  2949. return $type;
  2950. }
  2951. // Parse a property into accessor methods
  2952. function ParseClassProperty ($class, $parts) {
  2953. $property["parameters"] = explode(",", $parts[1]);
  2954. $method = array();
  2955. // property name
  2956. if (eregi("([a-zA-Z0-9]+)$", $parts[2], $captures)) $property["name"] = ucwords($captures[1]);
  2957. // property type
  2958. $type = istr_replace_word($captures[1], "", $parts[2]);
  2959. $type = $this->ConvertReturnType($type);
  2960. // setter
  2961. if (!in_array("readonly", $property["parameters"])) {
  2962. $method["setter"] = array();
  2963. $name = $property["name"];
  2964. if (!$this->GetPropertyName("setter", $property["parameters"], $name)) {
  2965. $name = "set$name";
  2966. }
  2967. // protect method name from keywords
  2968. if ($this->IsKeywordReserved($name)) $name .= "_";
  2969. $method["setter"]["def"] = "procedure $name (newValue: $type);";
  2970. $method["setter"]["objc_method"] = "$name:";
  2971. $method["setter"]["class"] = $class;
  2972. $method["setter"]["name"] = $name;
  2973. $method["setter"]["kind"] = "procedure";
  2974. }
  2975. // getter
  2976. $method["getter"] = array();
  2977. $name = $property["name"];
  2978. if (!$this->GetPropertyName("getter", $property["parameters"], $name)) {
  2979. $name = strtolower(substr($name, 0, 1)) . substr($name, 1);
  2980. }
  2981. // protect method name from keywords
  2982. if ($this->IsKeywordReserved($name)) $name .= "_";
  2983. $method["getter"]["def"] = "function $name: $type;";
  2984. $method["getter"]["objc_method"] = $name;
  2985. $method["getter"]["class"] = $class;
  2986. $method["getter"]["name"] = $name;
  2987. $method["getter"]["kind"] = "function";
  2988. return $method;
  2989. }
  2990. // Main entry to parse a header
  2991. function ParseHeaderClasses ($file) {
  2992. $contents = ReadTextFile($file);
  2993. $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
  2994. $line_count = 0;
  2995. $lines = explode("\n", $contents);
  2996. foreach ($lines as $line) {
  2997. $line_count++;
  2998. // remove external class macros
  2999. $line = eregi_replace("^[A-Z0-9]+_EXTERN_CLASS[[:space:]]+", "", $line);
  3000. // parse instance vars
  3001. if ($got_instance_vars) {
  3002. // scope compiler directive
  3003. if (eregi($this->regex_scope_compiler_directive, $line, $captures)) {
  3004. $this->instance_var_scope = $captures[1];
  3005. continue;
  3006. }
  3007. // remove comments
  3008. $line = $this->RemoveComments($line);
  3009. // parse instance variables
  3010. $result = $this->ParseInstanceVariables($line, $struct);
  3011. // parse structures
  3012. if ($result == "struct") {
  3013. //print_r($struct);
  3014. //$this->dump[$file_name]["classes"][$current]["ivars"][] = $struct["name"].": $current"."_".$struct["name"].";";
  3015. $this->dump[$file_name]["classes"][$current]["ivars_structs"][] = $struct;
  3016. // print inline-record type
  3017. if ($struct["bitpacked"]) {
  3018. $this->dump[$file_name]["classes"][$current]["ivars"][] = $struct["name"].": ".$this->bitpacked_record_keyword;
  3019. } else {
  3020. $this->dump[$file_name]["classes"][$current]["ivars"][] = $struct["name"].": ".$this->record_keyword;
  3021. }
  3022. // print fields
  3023. if ($struct["fields"]) {
  3024. foreach ($struct["fields"] as $field) $this->dump[$file_name]["classes"][$current]["ivars"][] = " ".$field;
  3025. }
  3026. $this->dump[$file_name]["classes"][$current]["ivars"][] = " end;";
  3027. $struct = null;
  3028. } elseif($result != null) {
  3029. //print($result);
  3030. $this->dump[$file_name]["classes"][$current]["ivars"][] = $result;
  3031. }
  3032. // instance var section terminated.
  3033. if (eregi("^\s*}\s*$", $line)) {
  3034. $struct = null;
  3035. $got_instance_vars = false;
  3036. $this->instance_var_scope = null;
  3037. }
  3038. } elseif ($got_class) { // parse the class
  3039. // the instance variable section started after the class line and no other ivar's were parsed yet
  3040. if (!$this->dump[$file_name]["classes"][$current]["ivars"]) {
  3041. if (eregi("{\s*$", $line)) {
  3042. $got_instance_vars = true;
  3043. continue;
  3044. }
  3045. }
  3046. // remove comments
  3047. $line = $this->RemoveComments($line);
  3048. // found property
  3049. if (eregi($this->regex_objc_property, $line, $captures)) {
  3050. $property = $this->ParseClassProperty($current, $captures);
  3051. if ($property["setter"]) {
  3052. if ($this->AddMethodToClass($property["setter"], $this->dump[$file_name]["classes"][$current])) {
  3053. $this->dump[$file_name]["classes"][$current]["methods"][] = $property["setter"];
  3054. }
  3055. }
  3056. if ($property["getter"]) {
  3057. if ($this->AddMethodToClass($property["getter"], $this->dump[$file_name]["classes"][$current])) {
  3058. $this->dump[$file_name]["classes"][$current]["methods"][] = $property["getter"];
  3059. }
  3060. }
  3061. continue;
  3062. }
  3063. // found method
  3064. if (eregi($this->regex_objc_method_params, $line, $captures)) {
  3065. $method = $this->ConvertObjcMethodToPascal($current, $line, $captures, $this->GetProtectedKeywords($this->current_class), true);
  3066. if ($this->AddMethodToClass($method, $this->dump[$file_name]["classes"][$current])) {
  3067. $this->dump[$file_name]["classes"][$current]["methods"][] = $method;
  3068. }
  3069. } elseif (eregi($this->regex_objc_method_no_params, $line, $captures)) {
  3070. $method = $this->ConvertObjcMethodToPascal($current, $line, $captures, $this->GetProtectedKeywords($this->current_class), false);
  3071. if ($this->AddMethodToClass($method, $this->dump[$file_name]["classes"][$current])) {
  3072. $this->dump[$file_name]["classes"][$current]["methods"][] = $method;
  3073. }
  3074. }
  3075. // found the end
  3076. if (ereg("^@end", $line)) $got_class = false;
  3077. }
  3078. // ==== got class ====
  3079. if ((eregi($this->regex_objc_class, $line, $captures)) || (eregi($this->regex_objc_class_no_super, $line, $captures))) {
  3080. $current = $captures[1];
  3081. $got_class = true;
  3082. // check for instance variable section
  3083. if (eregi("{\s*$", $line)) $got_instance_vars = true;
  3084. // get the protocol which the class conforms to
  3085. if (eregi($this->regex_objc_class, $line, $captures)) {
  3086. if ($captures[3]) $this->dump[$file_name]["classes"][$current]["conforms"] = $captures[3];
  3087. } else {
  3088. if ($captures[2]) $this->dump[$file_name]["classes"][$current]["conforms"] = $captures[2];
  3089. }
  3090. // clean up the conforms string
  3091. if ($this->dump[$file_name]["classes"][$current]["conforms"]) {
  3092. $conform_protocols = explode(",", $this->dump[$file_name]["classes"][$current]["conforms"]);
  3093. foreach ($conform_protocols as $protocol) {
  3094. $protocol = trim($protocol, "<> ");
  3095. $protocol_clean .= $protocol."$this->protocol_suffix, ";
  3096. }
  3097. $protocol_clean = trim($protocol_clean, ", ");
  3098. $this->dump[$file_name]["classes"][$current]["conforms"] = $protocol_clean;
  3099. $protocol_clean = "";
  3100. }
  3101. $this->dump[$file_name]["classes"][$current]["name"] = $captures[1];
  3102. $this->dump[$file_name]["classes"][$current]["super"] = $captures[2];
  3103. $this->dump[$file_name]["classes"][$current]["super_class"] = &$this->dump["master"][$captures[2]];
  3104. $this->dump[$file_name]["classes"][$current]["file_name"] = $file_name;
  3105. $this->dump[$file_name]["classes"][$current]["file_clean"] = substr($file_name, 0, (strripos($file_name, ".")));
  3106. $this->dump[$file_name]["classes"][$current]["protected_keywords"] = array();
  3107. $this->dump[$file_name]["classes"][$current]["declared_methods"] = array();
  3108. $this->dump[$file_name]["category_methods"] = array();
  3109. $this->current_class = &$this->dump[$file_name]["classes"][$current];
  3110. // append master class listing
  3111. $this->dump["master"][$current] = &$this->dump[$file_name]["classes"][$current];
  3112. // preparse for protected keywords
  3113. $this->PreparseClass($lines, $line_count);
  3114. // preparse for category methods that may present naming conflicts
  3115. $category_methods = $this->PreparseCategoryMethods($file);
  3116. // add category methods to protected keywords
  3117. if ($category_methods) $this->current_class["protected_keywords"] = array_merge($this->current_class["protected_keywords"], $category_methods);
  3118. // print class hierarchy
  3119. if ($this->show_class_hierarchy) {
  3120. $this->GetClassHierarchy($this->current_class, $hierarchy);
  3121. $hierarchy_string = "";
  3122. foreach ($hierarchy as $value) {
  3123. $hierarchy_string .= "$value->";
  3124. }
  3125. $hierarchy_string = trim($hierarchy_string, "->");
  3126. print(" - $current: $hierarchy_string\n");
  3127. }
  3128. $this->class_count ++;
  3129. //print_r($this->dump[$file_name]["classes"][$current]);
  3130. }
  3131. }
  3132. //print_r($this->dump[$file_name]["classes"][$current]);
  3133. }
  3134. // Parse categories which depend on another header
  3135. function ParseHeaderDependents ($file) {
  3136. $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
  3137. $this->ParseHeaderCategories($file);
  3138. print("+ Parsed $file_name for dependents\n");
  3139. }
  3140. // Main entry to parse a header
  3141. function ParseHeader ($file) {
  3142. $file_name = substr($file, (strripos($file, "/")) + 1, strlen($file));
  3143. $name_clean = substr($file_name, 0, (strripos($file_name, ".")));
  3144. // get framework we're parsing from
  3145. if (eregi("/([a-zA-Z]+)\.framework/", $file, $captures)) $this->framework = strtolower($captures[1]);
  3146. // get the output path
  3147. $this->dump[$file_name]["path"] = "$this->root$this->out/$this->framework/$name_clean.inc";
  3148. $this->dump[$file_name]["path_partial"] = "$this->framework/$name_clean.inc";
  3149. $this->dump[$file_name]["framework"] = $this->framework;
  3150. $this->dump[$file_name]["name"] = $file_name;
  3151. $this->dump[$file_name]["name_clean"] = $name_clean;
  3152. $this->current_header = &$this->dump[$file_name];
  3153. $this->ParseHeaderProtocols($file);
  3154. $this->ParseHeaderClasses($file);
  3155. $this->ParseHeaderTypes($file);
  3156. print("+ Parsed $file_name\n");
  3157. }
  3158. // Parse all AppKit and Foundation framework headers
  3159. function ParseCocoaFrameworks ($ignore_files, $parse_only) {
  3160. foreach ($this->frameworks as $framework_name => $framework_info) {
  3161. // framework is disabled
  3162. if ($framework_info["enabled"] != 1) continue;
  3163. if ($this->out != "/") {
  3164. $path = $this->root.$this->out."/".$framework_info["root"];
  3165. } else {
  3166. $path = $this->root.$framework_info["root"];
  3167. }
  3168. $contents = ReadTextFile($path);
  3169. $lines = explode("\n", $contents);
  3170. foreach ($lines as $line) {
  3171. if (eregi($framework_info["include_pattern"], $line, $captures)) {
  3172. $header = $captures[1].".h";
  3173. $path = $framework_info["headers"]."/$header";
  3174. // main header
  3175. if ($parse_only) {
  3176. if (@in_array($header, $parse_only)) $this->ParseHeader($path);
  3177. } elseif (@!in_array($header, $ignore_files)) {
  3178. $this->ParseHeader($path);
  3179. }
  3180. // header dependents
  3181. if ($parse_only) {
  3182. if (@in_array($header, $parse_only)) $this->ParseHeaderDependents($path);
  3183. } elseif (@!in_array($header, $ignore_files)) {
  3184. $this->ParseHeaderDependents($path);
  3185. }
  3186. }
  3187. }
  3188. }
  3189. // diagnostics
  3190. print("\n• Parsed $this->method_count methods in $this->class_count classes.\n\n");
  3191. if ($this->warning_count > 0) print("• $this->warning_count warnings were encountered.\n\n");
  3192. }
  3193. // Parse headers in a system framework
  3194. function ParseFramework ($ignore_files, $parse_only) {
  3195. }
  3196. // Parses XML file generated by GEN_BRIDGE_METADATA -f /System/Library/Frameworks/AppKit.framework/
  3197. function ParseBridgeSupportXML ($file, $categories) {
  3198. $contents = ReadTextFile($file);
  3199. $lines = explode("\n", $contents);
  3200. foreach ($lines as $line) {
  3201. if ($got_informal_protocol) {
  3202. if (eregi("<method type='(.*)' selector='(.*)'/>", $line, $captures)) {
  3203. $set["name"] = $captures[2];
  3204. $set["name_pascal"] = str_replace(":", "_", $set["name"]);
  3205. $set["name_pascal"] = rtrim($set["name_pascal"], "_");
  3206. $set["types"] = $captures[1];
  3207. $set["param_string"] = $categories[$informal_protocol]["methods"][$captures[2]]["param_string"];
  3208. $set["method"] = &$categories[$informal_protocol]["methods"][$captures[2]];
  3209. if ($captures[1][0] == "v") {
  3210. $set["kind"] = "procedure";
  3211. } else {
  3212. $set["kind"] = "function";
  3213. }
  3214. // add the selector if the name isn't reserved for Pascal
  3215. if ((!in_array($set["name_pascal"], $this->reserved_keywords)) && (!in_array($set["name_pascal"], $this->reserved_methods))) {
  3216. $this->delegate_methods[$informal_protocol][] = $set;
  3217. $this->delegate_method_names[] = $set["name_pascal"];
  3218. }
  3219. }
  3220. // end tag
  3221. if ($line == "</informal_protocol>") $got_informal_protocol = false;
  3222. }
  3223. // got informal_protocol
  3224. if (eregi("<informal_protocol name='(.*)'>", $line, $captures)) {
  3225. $informal_protocol = $captures[1];
  3226. //print("\"$informal_protocol\", ");
  3227. $got_informal_protocol = true;
  3228. }
  3229. }
  3230. print("+ Parsed bridge support XMl file at $file\n");
  3231. //print_r($this->delegate_methods);
  3232. }
  3233. // Parse all classes/categories (non-delegate) from the header
  3234. function ParseAllHeaderClasses ($file) {
  3235. $contents = ReadTextFile($file);
  3236. $lines = explode("\n", $contents);
  3237. foreach ($lines as $line) {
  3238. // remove external class macros
  3239. $line = eregi_replace("^[A-Z0-9]+_EXTERN_CLASS[[:space:]]+", "", $line);
  3240. // classes
  3241. if (eregi($this->regex_objc_class, $line, $captures)) $this->cocoa_classes[] = $captures[1];
  3242. if (eregi($this->regex_objc_class_no_super, $line, $captures)) $this->cocoa_classes[] = $captures[1];
  3243. // categories
  3244. if (eregi($this->regex_objc_category, $line, $captures)) {
  3245. $this->cocoa_categories[] = $captures[1];
  3246. }
  3247. }
  3248. }
  3249. // Build array of all known Cocoa classes in frameworks
  3250. function BuildCocoaClasses () {
  3251. foreach ($this->frameworks as $framework_name => $framework_info) {
  3252. // framework is disabled
  3253. if ($framework_info["enabled"] != 1) continue;
  3254. $handle = opendir($framework_info["headers"]);
  3255. while (($file = readdir($handle)) !== false) {
  3256. if (eregi($framework_info["header_pattern"], $file)) {
  3257. $this->ParseAllHeaderClasses($framework_info["headers"]."/$file");
  3258. }
  3259. }
  3260. closedir($handle);
  3261. }
  3262. }
  3263. function ProcessFile ($file, $print) {
  3264. $this->ParseHeader($file);
  3265. $this->ParseHeaderDependents($file);
  3266. if ($print) $this->PrintAllHeaders("", null, null, false);
  3267. }
  3268. function ParseDelegateClasses () {
  3269. foreach ($this->frameworks as $framework_name => $framework_info) {
  3270. // framework is disabled
  3271. if ($framework_info["enabled"] != 1) continue;
  3272. $this->ParseBridgeSupportXML("$this->root".$framework_info["bridge"], $this->dump["categories"]);
  3273. }
  3274. // These are expressions which match valid class names or the names themself
  3275. $delegate_categories = array( "(Delegation|Delegate|Notification|DataSource|Handler)+",
  3276. "NSDraggingDestination", "NSDistantObjectRequestMethods", "NSDraggingSource",
  3277. "NSEditorRegistration", "NSFileManagerFileOperationAdditions", "NSPasteboardOwner",
  3278. );
  3279. $this->output = fopen("$this->root$this->out/foundation/$this->master_delegate_file.inc", "w+");
  3280. $this->PrintDelegateClass($delegate_categories);
  3281. fclose($this->output);
  3282. $this->output = fopen("$this->root$this->out/$this->master_delegate_file.pas", "w+");
  3283. $this->PrintDelegateReference($delegate_categories);
  3284. fclose($this->output);
  3285. }
  3286. function LoadTypeEncodings ($name) {
  3287. $contents = ReadTextFile("$this->root/$name");
  3288. $lines = explode("\n", $contents);
  3289. foreach ($lines as $line) {
  3290. $row = explode("|", $line);
  3291. $this->type_encodings[$row[0]][$row[1]] = $row[2];
  3292. }
  3293. //print_r($this->type_encodings);
  3294. }
  3295. // Prints out code to generate type encodings with GenerateTypeEncodings.p
  3296. // Paste the output of the function into GenerateTypeEncodings.p, run the program and save the output into a text file
  3297. // which is loaded into this script.
  3298. function PrintTypeEncodingGlue () {
  3299. $count = 0;
  3300. $block = true;
  3301. $block_count = 1;
  3302. $limit = 2000;
  3303. foreach ($this->dump["all_methods"] as $class => $method) {
  3304. foreach ($method as $name) {
  3305. if ($count == 0) {
  3306. print("\n");
  3307. print("procedure PrintGlue$block_count;\n");
  3308. print("begin\n");
  3309. $block_count ++;
  3310. }
  3311. $count ++;
  3312. print("aMethod := class_getInstanceMethod(objc_getClass('$class'), sel_registerName(PChar('$name')));\n");
  3313. print("if aMethod <> nil then\n");
  3314. print("writeln('$class|$name|', method_getTypeEncoding(aMethod));\n");
  3315. if ($count == $limit) {
  3316. print("end;\n");
  3317. $count = 0;
  3318. }
  3319. }
  3320. }
  3321. if ($count < $limit) {
  3322. print("end;\n");
  3323. $block_count --;
  3324. }
  3325. print("\n========= IMPLEMENTATION =========\n");
  3326. for ($i=1; $i < $block_count + 1; $i++) {
  3327. print("PrintGlue$i;\n");
  3328. }
  3329. }
  3330. function __construct ($directory, $out_directory, $frameworks, $show) {
  3331. $this->root = $directory;
  3332. $this->out = $out_directory;
  3333. $this->show = $show;
  3334. if ($frameworks) {
  3335. foreach ($frameworks as $name) {
  3336. $this->frameworks[$name]["enabled"] = true;
  3337. }
  3338. }
  3339. $this->BuildCocoaClasses();
  3340. //$this->LoadTypeEncodings("TypeEncodingsAll.txt");
  3341. }
  3342. }
  3343. ?>