Symbol.pm 5.6 KB

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