Symbol.pm 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. # Copyright © 2007 Raphaël Hertzog <hertzog@debian.org>
  2. # Copyright © 2009 Modestas Vainius <modestas@vainius.eu>
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2 of the License, or
  6. # (at your option) any later version.
  7. # This program is distributed in the hope that it will be useful,
  8. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. # GNU General Public License for more details.
  11. # You should have received a copy of the GNU General Public License
  12. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. package Dpkg::Shlibs::Symbol;
  14. use strict;
  15. use warnings;
  16. use Dpkg::Gettext;
  17. use Dpkg::Deps;
  18. use Dpkg::ErrorHandling;
  19. use Storable qw(dclone);
  20. sub new {
  21. my $this = shift;
  22. my $class = ref($this) || $this;
  23. my %args = @_;
  24. my $self = bless {
  25. symbol => undef,
  26. symbol_templ => undef,
  27. minver => undef,
  28. dep_id => 0,
  29. deprecated => 0,
  30. tags => {},
  31. tagorder => [],
  32. }, $class;
  33. $self->{$_} = $args{$_} foreach keys %args;
  34. return $self;
  35. }
  36. sub clone {
  37. my $self = shift;
  38. my $clone = dclone($self);
  39. if (@_) {
  40. my %args=@_;
  41. $clone->{$_} = $args{$_} foreach keys %args;
  42. }
  43. return $clone;
  44. };
  45. sub parse_tagspec {
  46. my ($self, $tagspec) = @_;
  47. if ($tagspec =~ /^\((.*?)\)(.*)$/ && $1) {
  48. # (tag1=t1 value|tag2|...|tagN=tNp)
  49. # Symbols ()|= cannot appear in the tag names and values
  50. my $tagspec = $1;
  51. my $rest = ($2) ? $2 : "";
  52. my @tags = split(/\|/, $tagspec);
  53. # Parse each tag
  54. for my $tag (@tags) {
  55. if ($tag =~ /^(.*)=(.*)$/) {
  56. # Tag with value
  57. $self->add_tag($1, $2);
  58. } else {
  59. # Tag without value
  60. $self->add_tag($tag, undef);
  61. }
  62. }
  63. return $rest;
  64. }
  65. return undef;
  66. }
  67. sub parse {
  68. my ($self, $symbolspec) = @_;
  69. my $symbol;
  70. my $symbol_templ;
  71. my $symbol_quoted;
  72. my $rest;
  73. if (defined($symbol = $self->parse_tagspec($symbolspec))) {
  74. # (tag1=t1 value|tag2|...|tagN=tNp)"Foo::Bar::foobar()"@Base 1.0 1
  75. # Symbols ()|= cannot appear in the tag names and values
  76. # If the tag specification exists symbol name template might be quoted too
  77. if ($symbol =~ /^(['"])/ && $symbol =~ /^($1)(.*?)$1(.*)$/) {
  78. $symbol_quoted = $1;
  79. $symbol_templ = $2;
  80. $symbol = $2;
  81. $rest = $3;
  82. } else {
  83. if ($symbol =~ m/^(\S+)(.*)$/) {
  84. $symbol_templ = $1;
  85. $symbol = $1;
  86. $rest = $2;
  87. }
  88. }
  89. error(_g("symbol name unspecified: %s"), $symbolspec) if (!$symbol);
  90. } else {
  91. # No tag specification. Symbol name is up to the first space
  92. # foobarsymbol@Base 1.0 1
  93. if ($symbolspec =~ m/^(\S+)(.*)$/) {
  94. $symbol = $1;
  95. $rest = $2;
  96. } else {
  97. return 0;
  98. }
  99. }
  100. $self->{symbol} = $symbol;
  101. $self->{symbol_templ} = $symbol_templ;
  102. $self->{symbol_quoted} = $symbol_quoted if ($symbol_quoted);
  103. # Now parse "the rest" (minver and dep_id)
  104. if ($rest =~ /^\s(\S+)(?:\s(\d+))?/) {
  105. $self->{minver} = $1;
  106. $self->{dep_id} = defined($2) ? $2 : 0;
  107. } else {
  108. return 0;
  109. }
  110. return 1;
  111. }
  112. # A hook for processing of tags which may change symbol name.
  113. # Called from Dpkg::Shlibs::SymbolFile::load(). Empty for now.
  114. sub process_tags {
  115. my $self = shift;
  116. }
  117. sub get_symbolname {
  118. return $_[0]->{symbol};
  119. }
  120. sub get_symboltempl {
  121. return $_[0]->{symbol_templ} || $_[0]->{symbol};
  122. }
  123. sub get_wildcard_version {
  124. my $self = shift;
  125. if ($self->get_symbolname() =~ /^\*@(.*)$/) {
  126. return $1;
  127. }
  128. return undef;
  129. }
  130. sub has_tags {
  131. my $self = shift;
  132. return scalar (@{$self->{tagorder}});
  133. }
  134. sub add_tag {
  135. my ($self, $tagname, $tagval) = @_;
  136. if (exists $self->{tags}{$tagname}) {
  137. $self->{tags}{$tagname} = $tagval;
  138. return 0;
  139. } else {
  140. $self->{tags}{$tagname} = $tagval;
  141. push @{$self->{tagorder}}, $tagname;
  142. }
  143. return 1;
  144. }
  145. sub delete_tag {
  146. my ($self, $tagname) = @_;
  147. if (exists $self->{tags}{$tagname}) {
  148. delete $self->{tags}{$tagname};
  149. $self->{tagorder} = [ grep { $_ ne $tagname } @{$self->{tagorder}} ];
  150. return 1;
  151. }
  152. return 0;
  153. }
  154. sub has_tag {
  155. my ($self, $tag) = @_;
  156. return exists $self->{tags}{$tag};
  157. }
  158. sub get_tag_value {
  159. my ($self, $tag) = @_;
  160. return $self->{tags}{$tag};
  161. }
  162. sub is_optional {
  163. my $self = shift;
  164. return $self->has_tag("optional");
  165. }
  166. sub is_arch_specific {
  167. my $self = shift;
  168. return $self->has_tag("arch");
  169. }
  170. sub arch_is_concerned {
  171. my ($self, $arch) = @_;
  172. my $arches = $self->{tags}{arch};
  173. if (defined $arch && defined $arches) {
  174. my $dep = Dpkg::Deps::Simple->new();
  175. my @arches = split(/[\s,]+/, $arches);
  176. $dep->{package} = "dummy";
  177. $dep->{arches} = \@arches;
  178. return $dep->arch_is_concerned($arch);
  179. }
  180. return 1;
  181. }
  182. sub get_tagspec {
  183. my ($self) = @_;
  184. if ($self->has_tags()) {
  185. my @tags;
  186. for my $tagname (@{$self->{tagorder}}) {
  187. my $tagval = $self->{tags}{$tagname};
  188. if (defined $tagval) {
  189. push @tags, $tagname . "=" . $tagval;
  190. } else {
  191. push @tags, $tagname;
  192. }
  193. }
  194. return "(". join("|", @tags) . ")";
  195. }
  196. return "";
  197. }
  198. sub get_symbolspec {
  199. my $self = shift;
  200. my $template_mode = shift;
  201. my $spec = "";
  202. $spec .= "#MISSING: $self->{deprecated}#" if $self->{deprecated};
  203. $spec .= " ";
  204. if ($template_mode && $self->has_tags()) {
  205. $spec .= sprintf('%s%3$s%s%3$s', $self->get_tagspec(),
  206. $self->get_symboltempl(), $self->{symbol_quoted} || "");
  207. } else {
  208. $spec .= $self->get_symbolname();
  209. }
  210. $spec .= " $self->{minver}";
  211. $spec .= " $self->{dep_id}" if $self->{dep_id};
  212. return $spec;
  213. }
  214. 1;