From: Ian Jackson Date: Wed, 25 Dec 2019 23:29:40 +0000 (+0000) Subject: Dollar doubling feature X-Git-Tag: subdirmk/0.3~64 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?p=subdirmk.git;a=commitdiff_plain;h=f68bcc4648c8cbe549e37159df8bb488178c510c Dollar doubling feature This makes it easier to write certain rules commands, and macros involving eval. Further enhancements will follow, but for now: * Document the new facility, including the &-escapes to turn it on and off, its effect, and the three within-doubling don't-double escapes. * Implementation. Specifically: - Rename od to oud (`undoubled'). - Provide od which does double things if $ddbl (a global) is set. - Implement the escapes, and add some error checks. - Change `od' to `oud' in `&\$', so that that always produces an undoubled $. * Enhance extract-doctest: - Set $e->{DD} to say if it's in `while dollar doubling'. - Filter out such entries from the `normal' test - they are not legal outside dollar-doubling. - Add a dollar-doubling test which includes versions of all the normal tests as well as the dollar-doubling ones, and which dollar-doubles the outputs when appropriate. Signed-off-by: Ian Jackson --- diff --git a/README b/README index 7de4def..d750cb8 100644 --- a/README +++ b/README @@ -254,7 +254,7 @@ So pathname syntax is a subset of: && => && for convenience in shell runes &\& => & general escaping mechanism -&\$ => $ +&\$ => $ provided for $-doubling regimes &\NEWLINE eats the newline and vanishes &$VARIABLE => $(sub_dir_VARIABLE) or $(TOP_VARIABLE) @@ -323,6 +323,25 @@ So pathname syntax is a subset of: `all' is extra special: every directory has an `all' target, which corresponds to &TARGETS. + +Dollar doubling and macro assistance +------------------------------------ + +&$+ Starts dollar-doubling +&$- Stops dollar-doubling + Both are idempotent and local to the file or context. + +While dollar-doubling: +- - - - - - - - - - - + +$ => $$ including $'s produced by other + &-expansions not mentioned here + +&\$ => $ +&$NN => $(NN) where N are digits +&$( => $( + + Subdirectory and variable naming -------------------------------- diff --git a/generate b/generate index c608e8c..ec47866 100755 --- a/generate +++ b/generate @@ -74,7 +74,7 @@ sub oraw { print O @_ or die "error writing $writing_output.tmp: $!\n"; } -sub od { # maybe $-doubled +sub oud { # undoubled if (defined $buffering_output) { $buffering_output .= $_ foreach @_; return; @@ -82,6 +82,20 @@ sub od { # maybe $-doubled oraw @_; } +our $ddbl; + +sub od { # maybe $-doubled + if (!$ddbl) { + oud @_; + return; + } + foreach (@_) { + my $e = $_; + $e =~ s{\$}{\$\$}g; + oud $e; + } +} + sub start_output_file ($) { close_any_output_file(); ($writing_output) = @_; @@ -165,6 +179,8 @@ sub process_input_mk ($$$$) { ); $pfxmap{$_} = $srcdirmap{$_}.'/' foreach keys %srcdirmap; + local $ddbl; + while (<$input>) { if (s#^\s*$esc\:changequote\s+(\S+)\s+$##) { $$esclitr = $1; @@ -180,10 +196,11 @@ sub process_input_mk ($$$$) { $targets->{$t} //= [ ]; } for (;;) { + die if $ddbl && defined $buffering_output; unless (s{^(.*?)$esc}{}) { od $_; last; } od $1; if (s{^\\$esc}{}) { od "$$esclitr" } - elsif (s{^\\\$}{}) { od '$' } + elsif (s{^\\\$}{}) { oud '$' } elsif (s{^\\\s+$}{}) { } elsif (s{^$esc}{}) { od "$$esclitr$$esclitr" } elsif (m{^(?=$caps_re)}) { od $var_prefix } @@ -194,6 +211,10 @@ sub process_input_mk ($$$$) { elsif (s{^([~^]?)/}{}) { od $pfxmap{$1} } elsif (s{^\.}{}) { od $dir_name } elsif (s{^([~^])\.}{}) { od $srcdirmap{$1} } + elsif (s{^\$\-}{}) { $ddbl=undef; } + elsif (s{^\$\+}{}) { $ddbl=1; } + elsif (s{^\$\(}{}) { die unless $ddbl; oud "\$("; } + elsif (s{^\$(\d+)}{}) { die unless $ddbl; oud "\$($1)"; } elsif (s{^([~^]?)(?=[ \t])}{}) { my $prefix = $pfxmap{$1} // die; my $after=''; diff --git a/tests/filter/extract-doctest b/tests/filter/extract-doctest index 10dd42a..b63f309 100755 --- a/tests/filter/extract-doctest +++ b/tests/filter/extract-doctest @@ -61,6 +61,8 @@ while (<>) { confess "unk rhs $_ ?"; } $e->{CQ} = $in_changequote; + # adhoc: rely on this specific section title + $e->{DD} = $csection =~ m{^while dollar[- ]doubling}i; } else { confess "$_ ?"; } @@ -130,7 +132,26 @@ sub writeout ($) { oh "# doctest starts $dir_prefix\n"; write_permode($dir_prefix, '','','', 'normal', - sub { !$_[0]{CQ} } ); + sub { !$_[0]{DD} && !$_[0]{CQ} } ); + write_permode($dir_prefix, + '&$+', '&$-', "\n", + 'dollar doubling', + sub { + my ($e) = @_; + return 0 if $e->{CQ}; + return $e->{DD} || !grep { + # If there are two entries with the same In, + # use only the one from the `while dollar + # doubling' section. So entries there override + # entries in the rest o the file. + $_ ne $e && $_->{In} eq $e->{In} + } @exp; + }, + sub { + $_=$_[0]; + s/\$/\$\$/g unless $_[1]{DD}; + $_; + } ); write_permode($dir_prefix, "&:changequote NEWQUOTE\n", "NEWQUOTE:changequote &\n",