1# ex:ts=8 sw=4: 2# $OpenBSD: Subst.pm,v 1.26 2023/10/25 11:14:42 espie Exp $ 3# 4# Copyright (c) 2008 Marc Espie <espie@openbsd.org> 5# 6# Permission to use, copy, modify, and distribute this software for any 7# purpose with or without fee is hereby granted, provided that the above 8# copyright notice and this permission notice appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 18use v5.36; 19 20# very simple package, just holds everything needed for substitution 21# according to package rules. 22 23package OpenBSD::Subst; 24 25# XXX ReverseSubst takes a state as an extra parameter 26sub new($class, @) 27{ 28 bless {}, $class; 29} 30 31sub hash($self) 32{ 33 return $self; 34} 35 36sub add($self, $k, $v) 37{ 38 $k =~ s/^\^//; 39 $self->{$k} = $v; 40} 41 42sub value($self, $k) 43{ 44 return $self->{$k}; 45} 46 47sub parse_option($self, $opt) 48{ 49 if ($opt =~ m/^([^=]+)\=(.*)$/o) { 50 my ($k, $v) = ($1, $2); 51 $v =~ s/^\'(.*)\'$/$1/; 52 $v =~ s/^\"(.*)\"$/$1/; 53 # variable name can't end with a '+', 54 # recognize this as '+=' instead 55 if ($k =~ s/\+$//) { 56 if (defined $self->{$k}) { 57 return $self->{$k} .= " $v"; 58 } 59 } 60 $self->add($k, $v); 61 } else { 62 $self->add($opt, 1); 63 } 64} 65 66sub do($self, $s) 67{ 68 return $s unless $s =~ m/\$/o; # no need to subst if no $ 69 while ( my $k = ($s =~ m/\$\{([A-Za-z_][^\}]*)\}/o)[0] ) { 70 my $v = $self->{$k}; 71 unless ( defined $v ) { $v = "\$\\\{$k\}"; } 72 $s =~ s/\$\{\Q$k\E\}/$v/g; 73 } 74 $s =~ s/\$\\\{([A-Za-z_])/\$\{$1/go; 75 return $s; 76} 77 78sub copy_fh2($self, $src, $dest) 79{ 80 my $contents = do { local $/; <$src> }; 81 while (my ($k, $v) = each %{$self}) { 82 $contents =~ s/\$\{\Q$k\E\}/$v/g; 83 } 84 $contents =~ s/\$\\\{([A-Za-z_])/\$\{$1/go; 85 print $dest $contents; 86} 87 88sub copy_fh($self, $srcname, $dest) 89{ 90 open my $src, '<', $srcname or die "can't open $srcname: $!"; 91 $self->copy_fh2($src, $dest); 92} 93 94sub copy($self, $srcname, $destname) 95{ 96 open my $dest, '>', $destname or die "can't open $destname: $!"; 97 $self->copy_fh($srcname, $dest); 98 return $dest; 99} 100 101sub has_fragment($self, $state, $def, $frag, $location) 102{ 103 my $v = $self->value($def); 104 105 if (!defined $v) { 106 $state->fatal("Unknown fragment #1 in #2", 107 $frag, $location); 108 } elsif ($v == 1) { 109 return 1; 110 } elsif ($v == 0) { 111 return 0; 112 } else { 113 $state->fatal("Invalid fragment define #1=#2", $frag, $v); 114 } 115} 116 117sub empty($self, $k) 118{ 119 my $v = $self->value($k); 120 if (defined $v && $v) { 121 return 0; 122 } else { 123 return 1; 124 } 125} 126 1271; 128