1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693 |
- package Automake::Variable;
- use 5.006;
- use strict;
- use Carp;
- use Automake::Channels;
- use Automake::ChannelDefs;
- use Automake::Configure_ac;
- use Automake::Item;
- use Automake::VarDef;
- use Automake::Condition qw (TRUE FALSE);
- use Automake::DisjConditions;
- use Automake::General 'uniq';
- use Automake::Wrap 'makefile_wrap';
- require Exporter;
- use vars '@ISA', '@EXPORT', '@EXPORT_OK';
- @ISA = qw/Automake::Item Exporter/;
- @EXPORT = qw (err_var msg_var msg_cond_var reject_var
- var rvar vardef rvardef
- variables
- scan_variable_expansions check_variable_expansions
- variable_delete
- variables_dump
- set_seen
- require_variables
- variable_value
- output_variables
- transform_variable_recursively);
- my $_VARIABLE_CHARACTERS = '[.A-Za-z0-9_@]+';
- my $_VARIABLE_PATTERN = '^' . $_VARIABLE_CHARACTERS . "\$";
- my $_VARIABLE_RECURSIVE_PATTERN =
- '^([.A-Za-z0-9_@]|\$[({]' . $_VARIABLE_CHARACTERS . '[})]?)+' . "\$";
- my @_var_order;
- my %_gen_varname = ();
- my %_gen_varname_n = ();
- my %_am_macro_for_var =
- (
- CCAS => 'AM_PROG_AS',
- CCASFLAGS => 'AM_PROG_AS',
- EMACS => 'AM_PATH_LISPDIR',
- GCJ => 'AM_PROG_GCJ',
- LEX => 'AM_PROG_LEX',
- LIBTOOL => 'LT_INIT',
- lispdir => 'AM_PATH_LISPDIR',
- pkgpyexecdir => 'AM_PATH_PYTHON',
- pkgpythondir => 'AM_PATH_PYTHON',
- pyexecdir => 'AM_PATH_PYTHON',
- PYTHON => 'AM_PATH_PYTHON',
- pythondir => 'AM_PATH_PYTHON',
- );
- my %_ac_macro_for_var =
- (
- ALLOCA => 'AC_FUNC_ALLOCA',
- CC => 'AC_PROG_CC',
- CFLAGS => 'AC_PROG_CC',
- CXX => 'AC_PROG_CXX',
- CXXFLAGS => 'AC_PROG_CXX',
- F77 => 'AC_PROG_F77',
- FFLAGS => 'AC_PROG_F77',
- FC => 'AC_PROG_FC',
- FCFLAGS => 'AC_PROG_FC',
- OBJC => 'AC_PROG_OBJC',
- OBJCFLAGS => 'AC_PROG_OBJC',
- OBJCXX => 'AC_PROG_OBJCXX',
- OBJCXXFLAGS => 'AC_PROG_OBJCXX',
- RANLIB => 'AC_PROG_RANLIB',
- UPC => 'AM_PROG_UPC',
- UPCFLAGS => 'AM_PROG_UPC',
- YACC => 'AC_PROG_YACC',
- );
- my $configure_ac;
- my %_silent_variable_override =
- (AM_MAKEINFOHTMLFLAGS => 1,
- AR => 1,
- ARFLAGS => 1,
- DEJATOOL => 1,
- JAVAC => 1,
- JAVAROOT => 1);
- my $_appendvar;
- my $_traversal = 0;
- sub err_var ($$;%)
- {
- msg_var ('error', @_);
- }
- sub msg_cond_var ($$$$;%)
- {
- my ($channel, $cond, $var, $msg, %opts) = @_;
- my $v = ref ($var) ? $var : rvar ($var);
- msg $channel, $v->rdef ($cond)->location, $msg, %opts;
- }
- sub msg_var ($$$;%)
- {
- my ($channel, $var, $msg, %opts) = @_;
- my $v = ref ($var) ? $var : rvar ($var);
-
- my $cond = $v->conditions->one_cond;
- msg_cond_var $channel, $cond, $v, $msg, %opts;
- }
- sub reject_var ($$)
- {
- my ($var, $msg) = @_;
- my $v = var ($var);
- if ($v)
- {
- err_var $v, $msg;
- return 1;
- }
- return 0;
- }
- use vars '%_hooks';
- sub hook ($$)
- {
- my ($var, $fun) = @_;
- $_hooks{$var} = $fun;
- }
- use vars '%_variable_dict', '%_primary_dict';
- sub variables (;$)
- {
- my ($suffix) = @_;
- my @vars = ();
- if ($suffix)
- {
- if (exists $_primary_dict{$suffix})
- {
- @vars = values %{$_primary_dict{$suffix}};
- }
- }
- else
- {
- @vars = values %_variable_dict;
- }
-
-
- return wantarray ? sort { $a->name cmp $b->name } @vars : scalar @vars;
- }
- sub reset ()
- {
- %_variable_dict = ();
- %_primary_dict = ();
- $_appendvar = 0;
- @_var_order = ();
- %_gen_varname = ();
- %_gen_varname_n = ();
- $_traversal = 0;
- }
- sub var ($)
- {
- my ($name) = @_;
- return $_variable_dict{$name} if exists $_variable_dict{$name};
- return 0;
- }
- sub vardef ($$)
- {
- my ($name, $cond) = @_;
- my $var = var $name;
- return $var && $var->def ($cond);
- }
- sub _cvar ($)
- {
- my ($name) = @_;
- my $v = var $name;
- return $v if $v;
- return _new Automake::Variable $name;
- }
- sub rvar ($)
- {
- my ($name) = @_;
- my $v = var $name;
- prog_error ("undefined variable $name\n" . &variables_dump)
- unless $v;
- return $v;
- }
- sub rvardef ($$)
- {
- my ($name, $cond) = @_;
- return rvar ($name)->rdef ($cond);
- }
- sub _new ($$)
- {
- my ($class, $name) = @_;
- my $self = Automake::Item::new ($class, $name);
- $self->{'scanned'} = 0;
- $self->{'last-append'} = [];
- $_variable_dict{$name} = $self;
- if ($name =~ /_([[:alnum:]]+)$/)
- {
- $_primary_dict{$1}{$name} = $self;
- }
- return $self;
- }
- sub _check_ambiguous_condition ($$$)
- {
- my ($self, $cond, $where) = @_;
- my $var = $self->name;
- my ($message, $ambig_cond) = $self->conditions->ambiguous_p ($var, $cond);
-
-
- my $def = $self->def ($ambig_cond);
- if ($message && $def->pretty != VAR_SILENT)
- {
- msg 'syntax', $where, "$message ...", partial => 1;
- msg_var ('syntax', $var, "... '$var' previously defined here");
- verb ($self->dump);
- }
- }
- sub check_defined_unconditionally ($;$$)
- {
- my ($self, $parent, $parent_cond) = @_;
- if (!$self->conditions->true)
- {
- if ($parent)
- {
- msg_cond_var ('unsupported', $parent_cond, $parent,
- "automake does not support conditional definition of "
- . $self->name . " in $parent");
- }
- else
- {
- msg_var ('unsupported', $self,
- "automake does not support " . $self->name
- . " being defined conditionally");
- }
- }
- }
- sub output ($@)
- {
- my ($self, @conds) = @_;
- @conds = $self->conditions->conds
- unless @conds;
- my $res = '';
- my $name = $self->name;
- foreach my $cond (@conds)
- {
- my $def = $self->def ($cond);
- prog_error ("unknown condition '" . $cond->human . "' for '"
- . $self->name . "'")
- unless $def;
- next
- if $def->pretty == VAR_SILENT;
- $res .= $def->comment;
- my $val = $def->raw_value;
- my $equals = $def->type eq ':' ? ':=' : '=';
- my $str = $cond->subst_string;
- if ($def->pretty == VAR_ASIS)
- {
- my $output_var = "$name $equals $val";
- $output_var =~ s/^/$str/meg;
- $res .= "$output_var\n";
- }
- elsif ($def->pretty == VAR_PRETTY)
- {
-
-
- $val =~ s/\\$//mg;
- my $wrap = makefile_wrap ("$str$name $equals", "$str\t",
- split (' ', $val));
-
-
-
-
- $wrap = makefile_wrap ("$str$name $equals", "$str\t",
- split (' ', $val), '$(am__empty)')
- if $wrap =~ /\n(\s*@\w+@)+\s*$/;
- $res .= $wrap;
- }
- else
- {
-
-
- $val =~ s/\\$//mg;
- $res .= makefile_wrap ("$str$name $equals", "$str\t",
- sort (split (' ' , $val)));
- }
- }
- return $res;
- }
- sub value_as_list ($$;$$)
- {
- my ($self, $cond, $parent, $parent_cond) = @_;
- my @result;
-
- my $onceflag;
- foreach my $vcond ($self->conditions->conds)
- {
- if ($vcond->true_when ($cond))
- {
-
-
-
-
- $self->check_defined_unconditionally ($parent, $parent_cond)
- if $onceflag;
- $onceflag = 1;
- my $val = $self->rdef ($vcond)->value;
- push @result, split (' ', $val);
- }
- }
- return @result;
- }
- sub value_as_list_recursive ($;%)
- {
- my ($var, %options) = @_;
- return $var->traverse_recursively
- (
- sub {
- my ($var, $val, $cond, $full_cond) = @_;
- return [$var->rdef ($cond)->location, $val] if $options{'location'};
- return $val;
- },
-
- sub {
- my ($var, $parent_cond, @allresults) = @_;
- return map { my ($cond, @vals) = @$_; @vals } @allresults;
- },
- %options);
- }
- sub has_conditional_contents ($)
- {
- my ($self) = @_;
-
-
-
-
-
- eval
- {
- $self->traverse_recursively
- (sub
- {
- my ($subvar, $val, $cond, $full_cond) = @_;
- die $full_cond if ! $full_cond->true;
- return ();
- },
- sub { return (); });
- };
- if ($@)
- {
- return 1 if ref ($@) && $@->isa ("Automake::Condition");
-
- die;
- }
- return 0;
- }
- sub dump ($)
- {
- my ($self) = @_;
- my $text = $self->name . ": \n {\n";
- foreach my $vcond ($self->conditions->conds)
- {
- $text .= " " . $vcond->human . " => " . $self->rdef ($vcond)->dump;
- }
- $text .= " }\n";
- return $text;
- }
- sub scan_variable_expansions ($)
- {
- my ($text) = @_;
- my @result = ();
-
- $text =~ s/#.*$//;
-
- while ($text =~ /(?<!\$)\$(?:\{([^\}]*)\}|\(([^\)]*)\))/g)
- {
- my $var = $1 || $2;
-
-
- $var =~ s/:[^:=]*=[^=]*$//;
- push @result, $var;
- }
- return @result;
- }
- sub check_variable_expansions ($$)
- {
- my ($text, $where) = @_;
-
- foreach my $var (scan_variable_expansions ($text))
- {
- if ($var !~ /$_VARIABLE_PATTERN/o)
- {
-
-
-
- my $gnuext = "";
- $gnuext = "\n(probably a GNU make extension)" if $var =~ / /;
-
-
- if ($var =~ /$_VARIABLE_RECURSIVE_PATTERN/o)
- {
- msg ('portability-recursive', $where,
- "$var: non-POSIX recursive variable expansion$gnuext");
- }
- else
- {
- msg ('portability', $where, "$var: non-POSIX variable name$gnuext");
- }
- }
- }
- }
- sub define ($$$$$$$$)
- {
- my ($var, $owner, $type, $cond, $value, $comment, $where, $pretty) = @_;
- prog_error "$cond is not a reference"
- unless ref $cond;
- prog_error "$where is not a reference"
- unless ref $where;
- prog_error "pretty argument missing"
- unless defined $pretty && ($pretty == VAR_ASIS
- || $pretty == VAR_PRETTY
- || $pretty == VAR_SILENT
- || $pretty == VAR_SORTED);
- error $where, "bad characters in variable name '$var'"
- if $var !~ /$_VARIABLE_PATTERN/o;
-
-
-
-
- msg ('portability', $where, "':='-style assignments are not portable")
- if $type eq ':';
- check_variable_expansions ($value, $where);
-
- if ($comment)
- {
- chomp $comment;
- $comment .= "\n";
- }
- else
- {
- $comment = '';
- }
- my $self = _cvar $var;
- my $def = $self->def ($cond);
- my $new_var = $def ? 0 : 1;
-
- if ($owner == VAR_AUTOMAKE && ! $new_var)
- {
-
-
- if ($def->type ne $type && $def->owner == VAR_AUTOMAKE)
- {
- error ($def->location,
- "Automake variable '$var' was set with '"
- . $def->type . "=' here ...", partial => 1);
- error ($where, "... and is now set with '$type=' here.");
- prog_error ("Automake variable assignments should be consistently\n"
- . "defined with the same sign");
- }
-
-
- if ($def->owner != VAR_AUTOMAKE)
- {
- if (! exists $_silent_variable_override{$var})
- {
- my $condmsg = ($cond == TRUE
- ? '' : (" in condition '" . $cond->human . "'"));
- msg_cond_var ('override', $cond, $var,
- "user variable '$var' defined here$condmsg ...",
- partial => 1);
- msg ('override', $where,
- "... overrides Automake variable '$var' defined here");
- }
- verb ("refusing to override the user definition of:\n"
- . $self->dump ."with '" . $cond->human . "' => '$value'");
- return;
- }
- }
-
-
- if ($type eq '+' && ! $new_var)
- {
- $def->append ($value, $comment);
- $self->{'last-append'} = [];
-
-
- $def->set_owner ($owner, $where->clone)
- if $owner > $def->owner;
- }
-
- elsif ($type eq '+' && ! $self->conditions->false)
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- my $lastappend = [];
-
- if ($cond != TRUE)
- {
-
-
-
-
- my $condstr = $cond->string;
- my $key = "$var:$condstr";
- my ($appendvar, $appendvarcond) = @{$self->{'last-append'}};
- if ($appendvar && $condstr eq $appendvarcond)
- {
-
- $var = $appendvar;
- $owner = VAR_AUTOMAKE;
- $self = var ($var);
- $def = $self->rdef ($cond);
- $new_var = 0;
- }
- else
- {
-
- my $num = ++$_appendvar;
- my $hvar = "am__append_$num";
- $lastappend = [$hvar, $condstr];
- &define ($hvar, VAR_AUTOMAKE, '+',
- $cond, $value, $comment, $where, $pretty);
-
- $comment = '';
- $value = "\$($hvar)";
- }
- }
-
- foreach my $vcond ($self->conditions->conds)
- {
-
-
-
-
-
-
-
-
- my $undef_cond = $self->not_always_defined_in_cond ($cond);
- if (! $undef_cond->false)
- {
- error ($where,
- "cannot apply '+=' because '$var' is not defined "
- . "in\nthe following conditions:\n "
- . join ("\n ", map { $_->human } $undef_cond->conds)
- . "\neither define '$var' in these conditions,"
- . " or use\n'+=' in the same conditions as"
- . " the definitions.");
- }
- else
- {
- &define ($var, $owner, '+', $vcond, $value, $comment,
- $where, $pretty);
- }
- }
- $self->{'last-append'} = $lastappend;
- }
-
- else
- {
-
-
-
- _check_ambiguous_condition ($self, $cond, $where)
- unless (!$new_var
- && (($def->owner == VAR_AUTOMAKE && $owner != VAR_AUTOMAKE)
- || $def->owner == VAR_CONFIGURE));
-
- $owner = $def->owner
- if ! $new_var && $owner < $def->owner;
-
-
-
- $def = new Automake::VarDef ($var, $value, $comment, $where->clone,
- $type, $owner, $pretty);
- $self->set ($cond, $def);
- push @_var_order, $var;
- }
-
-
-
- &{$_hooks{$var}}($type, $value) if exists $_hooks{$var};
- }
- sub variable_delete ($@)
- {
- my ($var, @conds) = @_;
- if (!@conds)
- {
- delete $_variable_dict{$var};
- }
- else
- {
- for my $cond (@conds)
- {
- delete $_variable_dict{$var}{'defs'}{$cond};
- }
- }
- if ($var =~ /_([[:alnum:]]+)$/)
- {
- delete $_primary_dict{$1}{$var};
- }
- }
- sub variables_dump ()
- {
- my $text = "all variables:\n{\n";
- foreach my $var (variables())
- {
- $text .= $var->dump;
- }
- $text .= "}\n";
- return $text;
- }
- sub set_seen ($)
- {
- my ($self) = @_;
- $self = ref $self ? $self : var $self;
- return 0 unless $self;
- for my $c ($self->conditions->conds)
- {
- $self->rdef ($c)->set_seen;
- }
- return $self;
- }
- sub require_variables ($$$@)
- {
- my ($where, $reason, $cond, @vars) = @_;
- my $res = 0;
- $reason .= ' but ' unless $reason eq '';
- $configure_ac = find_configure_ac
- unless defined $configure_ac;
- VARIABLE:
- foreach my $var (@vars)
- {
-
- next VARIABLE
- if vardef ($var, $cond);
- my $text = "$reason'$var' is undefined\n";
- my $v = var $var;
- if ($v)
- {
- my $undef_cond = $v->not_always_defined_in_cond ($cond);
- next VARIABLE
- if $undef_cond->false;
- $text .= ("in the following conditions:\n "
- . join ("\n ", map { $_->human } $undef_cond->conds)
- . "\n");
- }
- ++$res;
- if (exists $_am_macro_for_var{$var})
- {
- my $mac = $_am_macro_for_var{$var};
- $text .= " The usual way to define '$var' is to add "
- . "'$mac'\n to '$configure_ac' and run 'aclocal' and "
- . "'autoconf' again.";
-
-
- $text .= "\n If '$mac' is in '$configure_ac', make sure\n"
- . " its definition is in aclocal's search path."
- unless $mac =~ /^AM_/;
- }
- elsif (exists $_ac_macro_for_var{$var})
- {
- $text .= " The usual way to define '$var' is to add "
- . "'$_ac_macro_for_var{$var}'\n to '$configure_ac' and "
- . "run 'autoconf' again.";
- }
- error $where, $text, uniq_scope => US_GLOBAL;
- }
- return $res;
- }
- sub requires_variables ($$@)
- {
- my ($var, $reason, @args) = @_;
- my $res = 0;
- for my $cond ($var->conditions->conds)
- {
- $res += require_variables ($var->rdef ($cond)->location, $reason,
- $cond, @args);
- }
- return $res;
- }
- sub variable_value ($)
- {
- my ($var) = @_;
- my $v = ref ($var) ? $var : var ($var);
- return () unless $v;
- $v->check_defined_unconditionally;
- my $d = $v->def (TRUE);
- return $d ? $d->value : "";
- }
- sub output_variables ()
- {
- my $res = '';
-
-
- my @vars = uniq @_var_order;
-
-
- foreach my $var (@vars)
- {
- my $v = rvar $var;
- foreach my $cond ($v->conditions->conds)
- {
- $res .= $v->output ($cond)
- if $v->rdef ($cond)->owner == VAR_AUTOMAKE;
- }
- }
-
- foreach my $var (@vars)
- {
- my $v = rvar $var;
- foreach my $cond ($v->conditions->conds)
- {
- $res .= $v->output ($cond)
- if $v->rdef ($cond)->owner != VAR_AUTOMAKE;
- }
- }
- return $res;
- }
- my @_substfroms;
- my @_substtos;
- sub traverse_recursively ($&&;%)
- {
- ++$_traversal;
- @_substfroms = ();
- @_substtos = ();
- my ($var, $fun_item, $fun_collect, %options) = @_;
- my $cond_filter = $options{'cond_filter'};
- my $inner_expand = $options{'inner_expand'};
- my $skip_ac_subst = $options{'skip_ac_subst'};
- return $var->_do_recursive_traversal ($var,
- $fun_item, $fun_collect,
- $cond_filter, TRUE, $inner_expand,
- $skip_ac_subst)
- }
- sub _do_recursive_traversal ($$&&$$$$)
- {
- my ($var, $parent, $fun_item, $fun_collect, $cond_filter, $parent_cond,
- $inner_expand, $skip_ac_subst) = @_;
- $var->set_seen;
- if ($var->{'scanned'} == $_traversal)
- {
- err_var $var, "variable '" . $var->name() . "' recursively defined";
- return ();
- }
- $var->{'scanned'} = $_traversal;
- my @allresults = ();
- my $cond_once = 0;
- foreach my $cond ($var->conditions->conds)
- {
- if (ref $cond_filter)
- {
-
- next if ! $cond->true_when ($cond_filter);
-
-
-
- $var->check_defined_unconditionally ($parent, $parent_cond)
- if $cond_once;
- $cond_once = 1;
- }
- my @result = ();
- my $full_cond = $cond->merge ($parent_cond);
- my @to_process = $var->value_as_list ($cond, $parent, $parent_cond);
- while (@to_process)
- {
- my $val = shift @to_process;
-
-
-
-
- if ($val =~ /^\$\{([^\}]*)\}$/ || $val =~ /^\$\(([^\)]*)\)$/)
- {
- my $subvarname = $1;
-
-
- next if ($subvarname =~ /\@.*\@/);
-
- my ($from, $to);
-
- if ($subvarname =~ /^([^:]*):([^=]*)=(.*)$/o)
- {
- $subvarname = $1;
- $to = $3;
- $from = quotemeta $2;
- }
- my $subvar = var ($subvarname);
-
- next unless $subvar;
- push @_substfroms, $from;
- push @_substtos, $to;
- my @res = $subvar->_do_recursive_traversal ($parent,
- $fun_item,
- $fun_collect,
- $cond_filter,
- $full_cond,
- $inner_expand,
- $skip_ac_subst);
- push (@result, @res);
- pop @_substfroms;
- pop @_substtos;
- next;
- }
-
-
-
-
- elsif ($inner_expand
- && ($val =~ /\$\{([^\}]*)\}/ || $val =~ /\$\(([^\)]*)\)/))
- {
- my $subvarname = $1;
- my $subvar = var $subvarname;
- if ($subvar)
- {
-
-
- foreach my $c ($subvar->conditions->conds)
- {
- if (ref $cond_filter)
- {
-
- next if ! $c->true_when ($cond_filter);
-
-
-
- $subvar->check_defined_unconditionally ($var,
- $full_cond)
- if $cond_once;
- $cond_once = 1;
- }
- my $subval = $subvar->rdef ($c)->value;
- $val =~ s/\$\{$subvarname\}/$subval/g;
- $val =~ s/\$\($subvarname\)/$subval/g;
- unshift @to_process, split (' ', $val);
- }
- next;
- }
-
-
- }
- elsif ($skip_ac_subst && $val =~ /^\@.+\@$/)
- {
- next;
- }
- if ($fun_item)
- {
- my $substnum=$#_substfroms;
- while ($substnum >= 0)
- {
- $val =~ s/$_substfroms[$substnum]$/$_substtos[$substnum]/
- if defined $_substfroms[$substnum];
- $substnum -= 1;
- }
-
-
-
- my @transformed = &$fun_item ($var, $val, $cond, $full_cond);
- push (@result, @transformed);
- }
- }
- push (@allresults, [$cond, @result]) if @result;
- }
-
-
- $var->{'scanned'} = -1;
- return ()
- unless $fun_collect;
-
-
- return &$fun_collect ($var, $parent_cond, @allresults);
- }
- sub _hash_varname ($)
- {
- my ($var) = @_;
- my $key = '';
- foreach my $cond ($var->conditions->conds)
- {
- my @values = $var->value_as_list ($cond);
- $key .= "($cond)@values";
- }
- return $key;
- }
- sub _hash_values (@)
- {
- my $key = '';
- foreach my $pair (@_)
- {
- my ($cond, @values) = @$pair;
- $key .= "($cond)@values";
- }
- return $key;
- }
- sub _gen_varname ($@)
- {
- my $base = shift;
- my $key = _hash_values @_;
- return ($_gen_varname{$base}{$key}, 0)
- if exists $_gen_varname{$base}{$key};
- my $num = 1 + ($_gen_varname_n{$base} || 0);
- $_gen_varname_n{$base} = $num;
- my $name = "${base}_${num}";
- $_gen_varname{$base}{$key} = $name;
- return ($name, 1);
- }
- sub transform_variable_recursively ($$$$$&;%)
- {
- my ($var, $resvar, $base, $nodefine, $where, $fun_item, %options) = @_;
- $var = ref $var ? $var : rvar $var;
- my $res = $var->traverse_recursively
- ($fun_item,
-
-
- sub {
- my ($subvar, $parent_cond, @allresults) = @_;
-
-
-
- return 'report-me' if $nodefine;
-
- my $key = _hash_varname $subvar;
- $_gen_varname{$base}{$key} = $subvar->name;
-
-
- my ($varname, $generated) =
- ($var != $subvar) ? _gen_varname ($base, @allresults) : ($resvar, 1);
-
-
-
- if ($generated
- && !($varname eq $var->name && $key eq _hash_values @allresults))
- {
-
-
-
- variable_delete ($varname) if $varname eq $var->name;
-
-
- @allresults = ([TRUE, '']) unless @allresults;
-
-
- foreach my $pair (@allresults)
- {
- my ($cond, @result) = @$pair;
- my $var = var $varname;
- my @conds = ($var
- ? $var->not_always_defined_in_cond ($cond)->conds
- : $cond);
- foreach (@conds)
- {
- define ($varname, VAR_AUTOMAKE, '', $_, "@result",
- '', $where, VAR_PRETTY);
- }
- }
- }
- set_seen $varname;
- return "\$($varname)";
- },
- %options);
- return $res;
- }
- 1;
|