drv_proxy_gen.pl 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #!/usr/bin/perl
  2. #
  3. # mbsync - mailbox synchronizer
  4. # Copyright (C) 2017 Oswald Buddenhagen <ossi@users.sf.net>
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. # As a special exception, mbsync may be linked with the OpenSSL library,
  20. # despite that library's more restrictive license.
  21. #
  22. use strict;
  23. use warnings;
  24. die("Usage: $0 driver.h drv_proxy.c drv_proxy.inc\n")
  25. if ($#ARGV != 2);
  26. my ($in_header, $in_source, $out_source) = @ARGV;
  27. my %templates;
  28. my %defines;
  29. my %excluded;
  30. my %special;
  31. open(my $ins, $in_source) or die("Cannot open $in_source: $!\n");
  32. my $template;
  33. my $define;
  34. my $conts;
  35. while (<$ins>) {
  36. if ($template) {
  37. if (/^\/\/\# END$/) {
  38. $templates{$template} = $conts;
  39. $template = undef;
  40. } else {
  41. $conts .= $_;
  42. }
  43. } elsif ($define) {
  44. if (/^\/\/\# END$/) {
  45. $defines{$define} = $conts;
  46. $define = undef;
  47. } else {
  48. $conts .= $_;
  49. }
  50. } else {
  51. if (/^\/\/\# TEMPLATE (\w+)$/) {
  52. $template = $1;
  53. $conts = "";
  54. } elsif (/^\/\/\# DEFINE (\w+)$/) {
  55. $define = $1;
  56. $conts = "";
  57. } elsif (/^\/\/\# DEFINE (\w+) (.*)$/) {
  58. $defines{$1} = $2;
  59. } elsif (/^\/\/\# UNDEFINE (\w+)$/) {
  60. $defines{$1} = "";
  61. } elsif (/^\/\/\# EXCLUDE (\w+)$/) {
  62. $excluded{$1} = 1;
  63. } elsif (/^\/\/\# SPECIAL (\w+)$/) {
  64. $special{$1} = 1;
  65. }
  66. }
  67. }
  68. close($ins);
  69. open(my $inh, $in_header) or die("Cannot open $in_header: $!\n");
  70. my $sts = 0;
  71. my $cont = "";
  72. while (<$inh>) {
  73. if ($sts == 0) {
  74. if (/^struct driver \{$/) {
  75. $sts = 1;
  76. }
  77. } elsif ($sts == 1) {
  78. if (/^\};$/) {
  79. $sts = 0;
  80. } else {
  81. $cont .= $_;
  82. }
  83. }
  84. }
  85. close($inh);
  86. $cont =~ s,\n, ,g;
  87. $cont =~ s,/\*.*?\*/, ,g;
  88. $cont =~ s,\h+, ,g;
  89. my @ptypes = map { s,^ ,,r } split(/;/, $cont);
  90. pop @ptypes; # last one is empty
  91. my @cmd_table;
  92. sub make_args($)
  93. {
  94. $_ = shift;
  95. s/(?:^|(?<=, ))(?:const )?\w+ \*?//g;
  96. return $_;
  97. }
  98. sub type_to_format($)
  99. {
  100. $_ = shift;
  101. s/xint /\%\#x/g;
  102. s/int /\%d/g;
  103. s/const char \*/\%s/g;
  104. return $_;
  105. }
  106. sub make_format($)
  107. {
  108. $_ = type_to_format(shift);
  109. s/, (\%\#?.)(\w+)/, $2=$1/g;
  110. return $_;
  111. }
  112. open(my $outh, ">".$out_source) or die("Cannot create $out_source: $!\n");
  113. for (@ptypes) {
  114. /^([\w* ]+)\(\*(\w+)\)\( (.*) \)$/ or die("Cannot parse prototype '$_'\n");
  115. my ($cmd_type, $cmd_name, $cmd_args) = ($1, $2, $3);
  116. if (defined($excluded{$cmd_name})) {
  117. push @cmd_table, "0";
  118. next;
  119. }
  120. push @cmd_table, "proxy_$cmd_name";
  121. next if (defined($special{$cmd_name}));
  122. my %replace;
  123. $replace{'name'} = $cmd_name;
  124. $replace{'type'} = $cmd_type;
  125. $cmd_args =~ s/^store_t \*ctx// or die("Arguments '$cmd_args' don't start with 'store_t *ctx'\n");
  126. if ($cmd_type eq "void " && $cmd_args =~ s/, void \(\*cb\)\( (.*)void \*aux \), void \*aux$//) {
  127. my $cmd_cb_args = $1;
  128. $replace{'decl_cb_args'} = $cmd_cb_args;
  129. $replace{'pass_cb_args'} = make_args($cmd_cb_args);
  130. my $cmd_print_cb_args = $cmd_cb_args =~ s/(.*), $/, $1/r;
  131. $replace{'print_pass_cb_args'} = make_args($cmd_print_cb_args);
  132. $replace{'print_fmt_cb_args'} = make_format($cmd_print_cb_args);
  133. $template = "CALLBACK";
  134. } elsif ($cmd_name =~ /^get_/) {
  135. $template = "GETTER";
  136. $replace{'fmt'} = type_to_format($cmd_type);
  137. } elsif ($cmd_type eq "void ") {
  138. $template = "REGULAR_VOID";
  139. } else {
  140. $template = "REGULAR";
  141. $replace{'fmt'} = type_to_format($cmd_type);
  142. }
  143. $replace{'decl_args'} = $cmd_args;
  144. $replace{'print_pass_args'} = $replace{'pass_args'} = make_args($cmd_args);
  145. $replace{'print_fmt_args'} = make_format($cmd_args);
  146. for (keys %defines) {
  147. $replace{$1} = $defines{$_} if (/^${cmd_name}_(.*)$/);
  148. }
  149. my $text = $templates{$template};
  150. $text =~ s/^\h*\@(\w+)\@\n/$replace{$1} \/\/ ""/smeg;
  151. $text =~ s/\@(\w+)\@/$replace{$1} \/\/ ""/eg;
  152. print $outh $text."\n";
  153. }
  154. print $outh "struct driver proxy_driver = {\n".join("", map { "\t$_,\n" } @cmd_table)."};\n";
  155. close $outh;