From 8c3e6dc4a16406496aa6991f8dc2fb77a96359ea Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 24 Dec 2019 23:04:58 +0000 Subject: [PATCH] Macro assistance part 2 - syntax for $(eval $(call...)) This can be used to call a macro defined with &:macro. In combination these provide a more reasonable macro facility than make's. Specifically: * Document the new facility. * Motivate it in the README. * Provide the new @nest kind for &${ }, which uses $ddbl as a counter to count { and }. * Implement the {}-counting and nesting end in the main parsing loop. (We must now search for things besides $esc.) * In extract-doctest, provide a slightly adhoc special case for understanding ${eval ...} as an expansion text in the README. And do not attempt to test &${ } when already $-doubling. Signed-off-by: Ian Jackson --- README | 13 +++++++++++++ generate | 19 +++++++++++++++++-- tests/filter/extract-doctest | 5 +++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/README b/README index 130a1c7..20658ae 100644 --- a/README +++ b/README @@ -340,6 +340,19 @@ STUFF $ THINGS .. STUFF $$ THINGS &:endm .. endef NAME is processed for & +&${..$..} => ${eval ${call ..$$..}} + (matches { } pairs to find the end) + content is $-doubled (unless it contains $- to turn that off) + + Together &:macro and &${...} provide a more reasonable macro + facility than raw make. They solve the problem that make + expansions cannot directly generate multiple rules, variable, + etc.; instead, `$(eval )' must be used, but that re-expands + the argument, meaning that all the literal text must be + $-doubled. This applies to the macro text and to the + arguments. Also `$(eval $(call ...))' is an unfortunate syntax. + Hence &:macro and &${...}. + While dollar-doubling: - - - - - - - - - - - diff --git a/generate b/generate index 3ccfa0d..52a0ec8 100755 --- a/generate +++ b/generate @@ -213,8 +213,19 @@ sub process_input_mk ($$$$) { } for (;;) { die if $ddbl && defined $buffering_output; - unless (s{^(.*?)$esc}{}) { od $_; last; } + unless (@nest && $nest[0][0] eq 'Eval' + ? s{^(.*?)($esc|[{}])}{} + : s{^(.*?)($esc)}{}) { od $_; last; } od $1; + if ($2 eq '{') { + $ddbl++; + next; + } elsif ($2 eq '}') { + next if --$ddbl; + $pop_nest->('Eval'); + od '}}'; + next; + } if (s{^\\$esc}{}) { od "$$esclitr" } elsif (s{^\\\$}{}) { oud '$' } elsif (s{^\\\s+$}{}) { } @@ -231,7 +242,11 @@ sub process_input_mk ($$$$) { elsif (s{^\$\+}{}) { $ddbl=1; } elsif (s{^\$\(}{}) { die unless $ddbl; oud "\$("; } elsif (s{^\$(\d+)}{}) { die unless $ddbl; oud "\$($1)"; } - elsif (s{^([~^]?)(?=[ \t])}{}) { + elsif (s{^\$\{}{}) { + die if $ddbl; + od '${eval ${call '; + $push_nest->('Eval',1); + } elsif (s{^([~^]?)(?=[ \t])}{}) { my $prefix = $pfxmap{$1} // die; my $after=''; if (m{([ \t])$esc}) { ($_,$after) = ($`, $1.$'); } diff --git a/tests/filter/extract-doctest b/tests/filter/extract-doctest index 57f5313..d779e00 100755 --- a/tests/filter/extract-doctest +++ b/tests/filter/extract-doctest @@ -56,6 +56,9 @@ while (<>) { $e->{OutTop} = $1 eq 'nothing' ? '' : $1; } elsif (# parse: expect other wordish things to be comments m{^(?!or\b)\w{2,} }) { + } elsif (# adhoc: slightly special case for $(eval $(call + m{^\$\{.*}) { + $e->{Out} .= ' '.$&; } elsif (m/^$/) { } else { confess "unk rhs $_ ?"; @@ -140,6 +143,8 @@ sub writeout ($) { my ($e) = @_; # adhoc: skip &:macro in already-doubling part return 0 if $e->{In} =~ m{^\&\:macro}; + # adhoc: skip &${ ie eval in already-doubling part + return 0 if $e->{In} =~ m{^\&\$\{}; return 0 if $e->{CQ}; return $e->{DD} || !grep { # If there are two entries with the same In, -- 2.30.2