xref: /openbsd/usr.sbin/pkg_add/OpenBSD/Subst.pm (revision 379777c0)
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