Method.pm 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package Logos::Generator::MobileSubstrate::Method;
  2. use strict;
  3. use parent qw(Logos::Generator::Base::Method);
  4. sub _originalMethodPointerDeclaration {
  5. my $self = shift;
  6. my $method = shift;
  7. if(!$method->isNew) {
  8. my $build = "static ";
  9. my $classargtype = $self->selfTypeForMethod($method);
  10. my $name = "(*".$self->originalFunctionName($method).")(".$classargtype.", SEL";
  11. my $argtypelist = join(", ", @{$method->argtypes});
  12. $name .= ", ".$argtypelist if $argtypelist;
  13. $name .= ")";
  14. $build .= Logos::Method::declarationForTypeWithName($self->returnTypeForMethod($method), $name);
  15. $build .= $self->functionAttributesForMethod($method);
  16. return $build;
  17. }
  18. return undef;
  19. }
  20. sub _methodPrototype {
  21. my $self = shift;
  22. my $method = shift;
  23. my $includeArgNames = 0 || shift;
  24. my $build = "static ";
  25. my $classargtype = $self->selfTypeForMethod($method);
  26. my $arglist = "";
  27. if($includeArgNames == 1) {
  28. map $arglist .= ", ".Logos::Method::declarationForTypeWithName($method->argtypes->[$_], $method->argnames->[$_]), (0..$method->numArgs - 1);
  29. } else {
  30. my $typelist = join(", ", @{$method->argtypes});
  31. $arglist = ", ".$typelist if $typelist;
  32. }
  33. my $name = $self->newFunctionName($method)."(".$classargtype.($includeArgNames?" self":"").", SEL".($includeArgNames?" _cmd":"").$arglist.")";
  34. $build .= Logos::Method::declarationForTypeWithName($self->returnTypeForMethod($method), $name);
  35. $build .= $self->functionAttributesForMethod($method);
  36. return $build;
  37. }
  38. sub definition {
  39. my $self = shift;
  40. my $method = shift;
  41. my $build = "";
  42. $build .= $self->_methodPrototype($method, 1);
  43. return $build;
  44. }
  45. sub originalCall {
  46. my $self = shift;
  47. my $method = shift;
  48. my $customargs = shift;
  49. return "" if $method->isNew;
  50. my $build = $self->originalFunctionName($method)."(self, _cmd";
  51. if(defined $customargs && $customargs ne "") {
  52. $build .= ", ".$customargs;
  53. } elsif($method->numArgs > 0) {
  54. $build .= ", ".join(", ",@{$method->argnames});
  55. }
  56. $build .= ")";
  57. return $build;
  58. }
  59. sub declarations {
  60. my $self = shift;
  61. my $method = shift;
  62. my $build = "";
  63. my $orig = $self->_originalMethodPointerDeclaration($method);
  64. $build .= $orig."; " if $orig;
  65. $build .= $self->_methodPrototype($method)."; ";
  66. return $build;
  67. }
  68. sub initializers {
  69. my $self = shift;
  70. my $method = shift;
  71. my $cgen = Logos::Generator::for($method->class);
  72. my $classvar = ($method->scope eq "+" ? $cgen->metaVariable : $cgen->variable);
  73. if(!$method->isNew) {
  74. my $r = "";
  75. $r .= "if (".$classvar.") {";
  76. $r .= "if (class_getInstanceMethod(".$classvar.", ".$self->selectorRef($method->selector).")) {";
  77. $r .= "MSHookMessageEx(".$classvar.", ".$self->selectorRef($method->selector).", (IMP)&".$self->newFunctionName($method).", (IMP*)&".$self->originalFunctionName($method).");";
  78. $r .= "} else {";
  79. $r .= "HBLogError(@\"logos: message not found [%s %s]\", \"".$method->class->name."\", \"".$method->selector."\");";
  80. $r .= "}";
  81. $r .= "} else {";
  82. $r .= "HBLogError(@\"logos: nil class %s\", \"".$method->class->name."\");";
  83. $r .= "}";
  84. } else {
  85. my $r = "";
  86. $r .= "{ ";
  87. if(!$method->type) {
  88. $r .= "char _typeEncoding[1024]; unsigned int i = 0; ";
  89. for ($method->return, "id", "SEL", @{$method->argtypes}) {
  90. my $typeEncoding = Logos::Method::typeEncodingForArgType($_);
  91. if(defined $typeEncoding) {
  92. my @typeEncodingBits = split(//, $typeEncoding);
  93. my $i = 0;
  94. for my $char (@typeEncodingBits) {
  95. $r .= "_typeEncoding[i".($i > 0 ? " + $i" : "")."] = '$char'; ";
  96. $i++;
  97. }
  98. $r .= "i += ".(scalar @typeEncodingBits)."; ";
  99. } else {
  100. $r .= "memcpy(_typeEncoding + i, \@encode($_), strlen(\@encode($_))); i += strlen(\@encode($_)); ";
  101. }
  102. }
  103. $r .= "_typeEncoding[i] = '\\0'; ";
  104. } else {
  105. $r .= "const char *_typeEncoding = \"".$method->type."\"; ";
  106. }
  107. $r .= "class_addMethod(".$classvar.", ".$self->selectorRef($method->selector).", (IMP)&".$self->newFunctionName($method).", _typeEncoding); ";
  108. $r .= "}";
  109. return $r;
  110. }
  111. }
  112. 1;