From: Marc Espie Subject: having fun with ports tree introspection To: ports@openbsd.org Date: Mon, 22 Jun 2026 18:59:09 +0200 I've been playing with three scripts for identifying variables in the ports tree and locating their doc. I've attached all 3. Basically: I go make show=.VARIABLES | lister >fullwords to extract every relevant public variable name from the tree. The second script, locatewords, will try to find all variables in manpages. Coincidentally, it's great at finding badly annotated variables ! The third script, mgrep, looks in MAKEFILE_LIST for a given construct, helping the user figure out where a variable is defined/used #! /usr/bin/perl use v5.36; my %hash; my ($pkgpath, $fullpkgpath); while (<>) { chomp; if (m/^\=\=\=\>\s+(.*)/) { $fullpkgpath = $1; $pkgpath = $fullpkgpath; $pkgpath =~ s/,.*//; say STDERR $pkgpath; next; } for my $word (split /\s+/, $_) { next if $word =~ m/^\_/; next if $word eq "BULK_$pkgpath"; next if $word eq "BULK_DO_$pkgpath"; next if $word eq "BULK_TARGETS_$pkgpath"; next if $word eq "CLEANDEPENDS_$pkgpath"; next if $word eq "WRKOBJDIR_$pkgpath"; next if $word eq "FAKEOBJDIR_$pkgpath"; next if $word =~ m/^LIB.*_VERSION$/; for my $w (qw(COMMENT PKG_ARCH PERMIT_PACKAGE PKGFILE PKGNAME PKGSTEM FULLPKGNAME REVISION EPOCH FULLPKGPATH RUN_DEPENDS WANTLIB LIB_DEPENDS IGNORE ONLY_FOR_ARCHS NOT_FOR_ARCHS PKG_ARGS PREFIX CATEGORIES MESSAGE UNMESSAGE DESCR PLIST STATIC_PLIST PKGSPEC SUBST_CMD)) { $word =~ s/^(\Q$w\E)\-.*/$1/; } for my $w (qw(SITES DISTFILES SUPDISTFILES PATCHFILES TEMPLATE_DISTFILES TEMPLATE_HOMEPAGE)) { $word =~ s/^(\Q$w\E)\..*/$1/; } $hash{$word} //= $pkgpath; } } for my $w (sort keys %hash) { say "$w => $hash{$w}"; } #! /usr/bin/perl use v5.36; my %keys; sub find_manpage($man, $section) { my $f; for my $d ("/usr/share/man/", "/usr/X11R6/man", "/usr/local/man") { for my $try (split(/,\s+/, $man)) { if (open($f, '<', "$d/man$section/$try.$section")) { return $f; } } } return undef; } sub cache_file($man, $section) { my $f = find_manpage($man, $section); if (!defined $f) { say STDERR "Can't locate $man($section)"; return; } my $h = {}; while (<$f>) { chomp; if (m/^\.Ev\s+(.*)/) { for my $word (split(/\s+/, $1)) { $h->{$word} = 1; } } elsif (m/^\.It\s+Ev\s+(.*)/) { for my $word (split(/\s+/, $1)) { $h->{$word} = 1; } } } $keys{$man.$section} = $h; close($f); } sub contains($man, $section, $ev) { if (!defined $keys{$man.$section}) { cache_file($man, $section); } if ($keys{$man.$section}{$ev}) { return 1; } else { return 0; } } open(my $g, '<', "fullwords") or die; while (<$g>) { chomp; if (m/^(.*)(\s\=\>.*)/) { my ($var, $rest) = ($1, $2); my @mans; open(my $pipe, "man -k Ev=$var 2>/dev/null|"); while (<$pipe>) { chomp; if (m/^(.*)\((\dp?)\)\s+\-\s+/) { my ($man, $section) = ($1, $2); if (contains($man, $section, $var)) { push(@mans, "$man($section)"); } } } close($pipe); if (@mans) { say $var.' ('.join(', ', @mans).')'.$rest; } else { say $var.$rest; } } } #! /bin/sh for i in `make show=MAKEFILE_LIST` do grep -l "$1" $i done