Symbol.pm 5.6 KB

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