#!/usr/bin/env perl # Simple script for substitute placeholders in Texinfo files with # docstring values found in source code. # Copyright (C) 2020-2025 Sergey Matveev # # If you C source code contains: # # // TEXINFO: SomeKey # // ... # // last line of docstring # some C code # # Then under "SomeKey" you will have the whole docstring (starting from # the line after "TEXINFO", till "last line"). You can include its # contents (excluding comment characters) in your .texi files placing # # @DOCSTRING SomeKey@ use strict; use warnings; use Carp q{croak}; my $verbose = 0; if ($ARGV[0] eq q{-v}) { $verbose = 1; shift @ARGV; } my $outDir = $ARGV[0]; my @srcDirs = split /:/, $ARGV[1]; my @docDirs = split /:/, $ARGV[2]; my @exts = (defined $ENV{EXTS}) ? (split / /, $ENV{EXTS}) : qw{c h h.in}; my %docstrings; foreach my $srcDir (@srcDirs) { if ($verbose) { print "src: $srcDir\n"; } opendir my $dir, $srcDir or croak "can not open $srcDir"; foreach my $fn (readdir $dir) { foreach (@exts) { if ($fn =~ /[.]$_$/) { goto ExtIsGood; } } next; ExtIsGood: open my $src, q{<:encoding(UTF-8)}, "$srcDir/$fn" or croak "can not open $srcDir/$fn"; my $curEntry; while (<$src>) { chomp; if (not /^\/\//) { if (defined $curEntry) { undef $curEntry; } next; } s/^\/\/[ ]?//; if (/^TEXINFO: (.*)$/) { $curEntry = $1; $docstrings{$curEntry} = q{}; if ($verbose) { print "\t$fn: $curEntry\n"; } next; } if (defined $curEntry) { $docstrings{$curEntry} .= "$_\n"; } } close $src or croak "$!"; } closedir $dir; } foreach my $docDir (@docDirs) { if ($verbose) { print "doc: $docDir\n"; } opendir my $dir, $docDir or croak "can not open $docDir"; if ($docDir !~ /[\/]$/) { $docDir .= q{/}; } if ($docDir eq q{./}) { $docDir = q{}; } foreach my $fn (readdir $dir) { if ($fn !~ /[.]texi$/) { next; } $fn = $docDir . $fn; open my $src, q{<:encoding(UTF-8)}, $fn or croak "can not open $fn"; mkdir "$outDir/$docDir"; open my $dst, q{>:encoding(UTF-8)}, "$outDir/$fn" or croak "can not open $outDir/$fn"; my $ref; while (<$src>) { if (/^\s*\@DOCSTRING (.*)\@$/) { $ref = $1; } else { print {$dst} $_; next; } if ($verbose) { print "\t$fn: $ref\n"; } if (defined $docstrings{$ref}) { print {$dst} $docstrings{$ref}; } else { croak "unable to find docstring: $ref"; } } close $src or croak "$!"; close $dst or croak "$!"; } closedir $dir; }