# lib_acscan.pl # 14/10/2011 - Found a case where only 2 Makefile.am found in configure.ac scan, BUT there is a line # [01] 39: [AC_CONFIG_SUBDIRS(autoconf-lib-link gettext-runtime gettext-tools)], and these SUBDIRS do # contain Makefile.am files... so add them to the list of AM to scan # 06/03/2011 - FIX20110306 - fix a Makefile path to DOS only # 23/09/2010 Add warning about input # 04/09/2010 This version is similar to lib_acscan-ok.pl, excepted does NOT use while () and $_, nor $. # 02/09/2010 geoff mclane http://geoffair.net/mperl use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) # options my $abort_on_ac_config = 0; # automake requires 'AM_CONFIG_HEADER', not 'AC_CONFIG_HEADER' # forward sub scan_configure_ac_file($$); my $AM_CONDITIONAL_PATTERN = "AM_CONDITIONAL\\((\\w+)"; my $AM_INIT_AUTOMAKE = "AM_INIT_AUTOMAKE\\(([^,]+),[ \t]*([^)]+)"; # AC_INIT (package, version, [bug-report], [tarname]) # Set the name of the package and its version # BUT can be a FILE NAME ONLY my $AC_INIT = "AC_INIT\\((.+)\\)"; my $AC_DEFINE = "AC_DEFINE\\((.+)\\)"; my $AC_DEFINE_UNQ = "AC_DEFINE_UNQUOTED\\((.+)\\)"; my $AC_CONF_SUBDIRS = "AC_CONFIG_SUBDIRS\\((.+)\\)"; ### shared with library our ($dbg_lac01, $dbg_lac02, $dbg_lac03, $dbg_lac04, $dbg_lac05, $dbg_lac06, $dbg_lac07, $dbg_lac08, $dbg_lac09, $dbg_lac10, $dbg_lac11, $dbg_lac12, $dbg_lac13, $dbg_lac14, $dbg_lac15, $dbg_lac16, $dbg_lac17, $dbg_lac18, $dbg_lac19, $dbg_lac20, $dbg_last ); my $ac_done_debug_flags = 0; my $dbg_extra = 0; my $dbg_extra2 = 0; my $dbg_extra3 = 0; sub set_dbg_shell_actions(); sub ac_set_dbg_extra() { $dbg_extra = 1; $dbg_extra2 = 1; $dbg_extra3 = 1; set_dbg_shell_actions(); } my $ac_dbg_base = 'dbg_lac'; sub ac_get_dbg_val_var($) { my $val = shift; my $var = $ac_dbg_base; if ($val < 10) { $var .= "0$val"; } else { $var .= "$val"; } return $var; } sub ac_get_dbg_var($) { my $val = shift; my $var = ac_get_dbg_val_var($val); my $res = -1; # from : http://perldoc.perl.org/functions/eval.html if (eval "defined \$$var") { $res = eval "\$$var"; } return $res; } sub ac_set_dbg_var($) { my $val = shift; my $var = ac_get_dbg_val_var($val); # from : http://perldoc.perl.org/functions/eval.html # NOT $$var++; # does not work! if (eval "defined \$$var") { eval "\$$var++"; } else { #print "ERROR: \$$var does NOT exist\n"; return 0; } return 1; } sub ac_get_dbg_range() { my ($i,$res); for ($i = 1; ;$i++) { $res = ac_get_dbg_var($i); last if ($res == -1); } return $i - 1; } sub ac_get_dbg_stg() { my $s = ''; my ($i,$res,$i2); for ($i = 1; ;$i++) { $res = ac_get_dbg_var($i); last if ($res == -1); if ($i < 10) { $i2 = "0$i"; } else { $i2 = "$i"; } if ($res > 0) { $s .= "$i2 "; } } return $s; } # this converts a BIT to a flag value sub ac_set_debug_flags($) { my $dbg = shift; $ac_done_debug_flags = 1; my $nxt = 1; my $flg = 0; my $rng = ac_get_dbg_range(); my $pack = __PACKAGE__; prt("Setting [$pack] debug flags for 1 to $rng, for value [$dbg]\n") if ($dbg); while ($dbg && $nxt) { $flg++; if ($dbg & $nxt) { if ($flg < $rng) { ac_set_dbg_var($flg); } else { last; } } $dbg &= ~$nxt; $nxt = $nxt << 1; } } sub ac_set_all_dbg_on() { my ($i,$res); for ($i = 1; ;$i++) { $res = ac_set_dbg_var($i); last if (!$res); } } sub ac_set_all_dbg_off() { my ($i,$res); for ($i = 1; ;$i++) { $res = ac_clear_dbg_var($i); last if (!$res); } } ######################################################## ### DIRECTORY SCANNING ### sub ac_do_dir_scan($$$); sub ac_do_dir_scan($$$) { my ($rparams,$dir,$lv) = @_; my $rda = ${$rparams}{'CURR_DIR_SCAN'}; $dir .= "\\" if !($dir =~ /(\\|\/)$/); $dir = path_u2d($dir); my ($file,$ff,$n,$d); my @dirs = (); if ($lv == 0) { prt("Moment, doing full directory scan of [$dir]...\n"); ${$rparams}{'CURR_AM_COUNT'} = 0; ${$rparams}{'CURR_AM_LIST'} = []; } if (opendir(DIR,$dir)) { my @files = readdir(DIR); closedir(DIR); foreach $file (@files) { next if (($file eq '.')||($file eq '..')); $ff = $dir.$file; if (-d $ff) { push(@dirs,$ff); next; } if ($file eq "Makefile.am") { ${$rparams}{'CURR_AM_COUNT'}++; $n = ${$rparams}{'CURR_AM_LIST'}; push(@{$n},$ff); } # 0 1 2 3 push(@{$rda},[$file,$ff,0,0]); } } if (@dirs) { foreach $file (@dirs) { ac_do_dir_scan($rparams,$file,$lv+1); } } if ($lv == 0) { $d = scalar @{$rda}; $n = ${$rparams}{'CURR_AM_COUNT'}; prt("Done scan... got $d files... $n are Makefile.am\n"); ${$rparams}{'CURR_DONE_SCAN'} = 1; ${$rparams}{'CURR_FILE_COUNT'} = $file; } } my %ac_searches_shown = (); sub ac_is_file_in_scan($$$$) { my ($rparams,$test,$fd,$ra) = @_; if (! ${$rparams}{'CURR_DONE_SCAN'} ) { my $dir = ${$rparams}{'CURR_FILE_DIR'}; if (-d $dir) { ac_do_dir_scan($rparams,$dir,0); } else { prtw("WARNING: Directory SEARCH FAILED! [$dir] NOT found!\n"); return 0; } } my $rda = ${$rparams}{'CURR_DIR_SCAN'}; my $cnt = scalar @{$rda}; my ($i,$file,$fcnt,$ff); $fcnt = 0; for ($i = 0; $i < $cnt; $i++) { $file = ${$rda}[$i][0]; if ($test eq $file) { $ff = ${$rda}[$i][1]; # could now check if $fd at least partially matches, but for now push(@{$ra},$ff); $fcnt++; } } if ($dbg_lac20 && !defined $ac_searches_shown{$test}) { prt("[20] Directory SEARCH for [$test], found $fcnt.\n") if ($dbg_lac20); } $ac_searches_shown{$test} = 1; return $fcnt; } sub ac_match_dir_for_c_source($$$$) { my ($rparams,$oky,$dir,$ra) = @_; if (! ${$rparams}{'CURR_DONE_SCAN'} ) { my $dir = ${$rparams}{'CURR_FILE_DIR'}; if (-d $dir) { ac_do_dir_scan($rparams,$dir,0); } else { prtw("WARNING: Directory SEARCH FAILED! [$dir] NOT found!\n"); return 0; } } my $rda = ${$rparams}{'CURR_DIR_SCAN'}; my $cnt = scalar @{$ra}; # 04/12/2010 my ($i,$file,$fcnt,$fn,$fd,$fx); $fcnt = 0; $dir = path_u2d($dir); $dir .= "\\" if (!($dir =~ /\\$/)); for ($i = 0; $i < $cnt; $i++) { $file = ${$rda}[$i][1]; # get FULL FILE ($fn,$fd,$fx) = fileparse($file,qr/\.[^.]*/); $fd = path_u2d($fd); if (($fd eq $dir) && ($fn eq $oky)) { if (is_c_source_extended($file)) { push(@{$ra},$file); return 1; } } } return 0; } ######################################################### sub show_ac_hash($) { my ($rparams) = @_; my ($key,$val,$cnt,$ky2,$val2,$len,$min,$ff,$ok,$typ,$cnt2,$msg); my $inf = ${$rparams}{'CURR_FILE'}; my $rh = ${$rparams}{'CURR_HASH'}; my $supp_in = ${$rparams}{'SUPP_MAKE_IN'}; my ($in_name, $in_dir) = fileparse($inf); $msg = "\nGot keys: "; foreach $key (keys %{$rh}) { $msg .= "$key "; } prt("$msg\n") if ($dbg_lac13); my $tot_cnt = 0; $cnt2 = 0; foreach $key (keys %{$rh}) { $val = ${$rh}{$key}; $cnt2++; if ($key eq '-NEW_PROJECT_NAME-') { prt("\n") if ($dbg_lac13); prt("KEY:$cnt2: $key = [$val]\n"); } elsif ($key eq 'H_CONF_AC_MACS') { $cnt = scalar keys(%{$val}); prt("\n") if ($dbg_lac13); prt("KEY:$cnt2: $key with $cnt macros in hash\n"); $tot_cnt += $cnt; if ($dbg_lac13) { $min = 0; foreach $ky2 (keys %{$val}) { $val2 = ${$val}{$ky2}; $len = length($ky2); $min = $len if ($len > $min); } $min = 40 if ($min > 40); foreach $ky2 (keys %{$val}) { $val2 = ${$val}{$ky2}; $ky2 .= ' ' while (length($ky2) < $min); prt(" $ky2 = [$val2]\n"); } } } elsif ($key eq 'R_SUBS_NOT_FOUND') { $cnt = scalar keys(%{$val}); prt("\n") if ($dbg_lac13); prt("KEY:$cnt2: $key with $cnt macros in hash\n"); $tot_cnt += $cnt; if ($dbg_lac13) { $min = 0; foreach $ky2 (keys %{$val}) { $val2 = ${$val}{$ky2}; $len = length($ky2); $min = $len if ($len > $min); } $min = 40 if ($min > 40); foreach $ky2 (keys %{$val}) { $val2 = ${$val}{$ky2}; $ky2 .= ' ' while (length($ky2) < $min); prt(" $ky2 = [$val2]\n"); } } } elsif ($key eq 'A_MAKE_INPUT_LIST') { prt("\n") if ($dbg_lac13); $cnt = scalar @{$val}; prt("KEY:$cnt2: $key with $cnt in array...\n"); foreach $ky2 (@{$val}) { $typ = ".am"; $ff = $in_dir.$ky2.$typ; if ($supp_in && ( ! -f $ff ) && ( -f $in_dir.$ky2.'.in') && ($ky2 =~ /^Makefile/)) { $typ = ".in"; $ff = $in_dir.$ky2.$typ; } if (-f $ff) { $ok = "$typ ok"; write_to_am_list($ff,1); } else { $ok = "NOT FOUND [$ff]"; write_to_am_list($ff,0); } prt( " $ky2 $ok, "); prt("\n") if ($dbg_lac13); } prt("\n") if ($cnt && !$dbg_lac13); } elsif ($key eq 'A_OTHER_INPUT_LIST') { $cnt = scalar @{$val}; prt("\n") if ($dbg_lac13); prt("KEY:$cnt2: $key with $cnt in array...\n"); $tot_cnt += $cnt; if ($dbg_lac13) { foreach $ky2 (@{$val}) { $ff = $in_dir.$ky2; if (-f $ff) { $ok = "ok"; #write_to_am_list($ff,1); } else { $ok = "NOT FOUND [$ff]"; #write_to_am_list($ff,0); } prt( " $ky2 $ok\n"); } } } elsif ($key =~ /^CURR_/) { # ignore current items # ==================== } else { prtw("WARNING:$cnt2: Unhandled key [$key]!\n"); } } if ($dbg_lac13) { prt("End show_ac_hash\n"); } else { prt("Add command '-d 113' to view $tot_cnt items in detail.\n"); } } ########################################################## ### attempt to emulate a few shell actions to set a macro my $dbg01 = 0; my $dbg05 = 0; my $dbg06 = 0; my $dbg37 = 0; my $dbg38 = 0; sub set_dbg_shell_actions() { $dbg01 = 1; $dbg05 = 1; $dbg06 = 1; $dbg37 = 1; $dbg38 = 1; } # [m]/PATTERN/[g][i][m][o][s][x] # s/PATTERN/REPLACEMENT/[e][g][i][m][o][s][x] # tr/SEARCHLIST/REPLACMENTLIST/[c][d][s] my $m_mods = 'gimosx'; my $s_mods = 'egimosx'; my $t_mods = 'cds'; my $add_scalars = 0; my $add_quoted = 1; # FLAGS my $FG_NONE = 0; my $FG_SCAL = 1; # is a SCALAR entry my $FG_QUOT = 1; # is a QUOTED entry # simply, does it start and end with '`' chars sub ac_is_shell_action($) { my $txt = shift; return 1 if ($txt =~ /^`.+`$/); return 0; } # 2010-08-27: This could be split(/\s/,$line), but there is a # problem with name="with space", that this overcomes. # Slower. but sure the split is as desired. # This version obeys either type of quote - single or double sub ac_local_space_split($) { my ($lin) = shift; my $ll = length($lin); my $tag = ''; my @rarr = (); my $inquots = 0; my ($p,$ch,$cq); for ($p = 0; $p < $ll; $p++) { $ch = substr($lin,$p,1); if ($inquots) { $tag .= $ch; # accumulate if ($ch eq $cq) { $inquots = 0; # end of quotes push(@rarr, $tag) if (length($tag)); $tag = ''; } } else { if ($ch =~ /\s/) { push(@rarr, $tag) if (length($tag)); $tag = ''; } else { $tag .= $ch; # accumulate if (($ch eq '"')||($ch eq "'")) { $inquots = 1; $cq = $ch; # keep the quote type } } } } push(@rarr, $tag) if (length($tag)); return @rarr; } sub grep_for_value($$) { my ($file,$find) = @_; my $res = ''; if (open INF,"<$file") { my @lns = ; close INF; my ($ln,$ind); foreach $ln (@lns) { $ind = index($ln,$find); if ($ind >= 0) { chomp $ln; $res = $ln; last; } } } else { prtw("WARNING: Unable to open file [$file]\n") if ($dbg38); } return $res; } sub ac_return_regex2($) { my ($rp) = @_; my $txt = ${$rp}{'TEXT'}; my ($ind,$len,$i,$c,$reg,$nc,$go,$pc,$mods,$ppc,$endc,$sub,$rege1,$dn1,$rege2); $len = length($txt); $ind = 0; $reg = ''; $go = 0; $endc = '/'; $sub = 0; $rege1 = ''; $dn1 = 0; $rege2 = ''; for ($i = 0; $i < $len; $i++) { $c = substr($txt,$i,1); $nc = (($i + 1) < $len) ? substr($txt,$i+1,1) : ''; #prt( "Check char [$c] nc = [$nc]\n" ); if ($c eq '/') { $reg = $c; $mods = $m_mods; $go = 1; } elsif (($c eq 'm')&&($nc eq '/')) { $reg = "$c$nc"; $mods = $m_mods; $i++; $go = 1; } elsif (($c eq 'm')&&($nc eq '|')) { $reg = "$c$nc"; $mods = $m_mods; $endc = $nc; $i++; $go = 1; } elsif (($c eq 's')&&($nc eq '/')) { $reg = "$c$nc"; $mods = $s_mods; $sub = 1; $i++; $go = 1; } elsif (($c eq 't')&&($nc eq 'r')) { if (($i + 2) < $len) { $nc = (($i + 2) < $len) ? substr($txt,$i+2,1) : ''; if ($nc eq '/') { $reg = "tr/"; $i += 2; $mods = $t_mods; $sub = 1; $go = 1; } } } elsif ($c eq '$') { # special case of a scalar if ($add_scalars) { $reg = $c; $i++; for (; $i < $len; $i++) { $ppc = $pc; $pc = $c; $c = substr($txt,$i,1); $nc = (($i + 1) < $len) ? substr($txt,$i+1,1) : ''; if ($c =~ /\w/) { $reg .= $c; } else { last; } } if (length($reg) > 1) { $ind += $i; ${$rp}{'REGEX'} = $reg; ${$rp}{'OFFSET'} = $ind; ${$rp}{'FLAG'} = $FG_SCAL; ${$rp}{'REG1'} = $rege1; ${$rp}{'REG2'} = $rege2; prt( "Returning SCALAR success [$reg] at off=[$ind]\n" ) if ($dbg06); return 1; } } } elsif ($c eq '"') { if ($add_quoted) { # limited to '"\w+"' $reg = $c; $i++; for (; $i < $len; $i++) { $ppc = $pc; $pc = $c; $c = substr($txt,$i,1); $nc = (($i + 1) < $len) ? substr($txt,$i+1,1) : ''; if ($c =~ /\w/) { $reg .= $c; } elsif ($c eq '"') { $reg .= $c; $i++; last; } else { $reg = ''; last; } } if (length($reg) > 1) { $ind += $i; ${$rp}{'REGEX'} = $reg; ${$rp}{'OFFSET'} = $ind; ${$rp}{'FLAG'} = $FG_QUOT; ${$rp}{'REG1'} = $rege1; ${$rp}{'REG2'} = $rege2; prt( "Returning QUOTED success [$reg] at off=[$ind]\n" ) if ($dbg05); return 1; } } } if ($go) { prt( "Found GO at offset $i\n" ) if ($dbg01); $i++; $c = '/'; for (; $i < $len; $i++) { $ppc = $pc; $pc = $c; $c = substr($txt,$i,1); $nc = (($i + 1) < $len) ? substr($txt,$i+1,1) : ''; $reg .= $c; # if (($c eq '/')&&($pc ne "\\")) { if ( ($c eq $endc) && (($pc ne "\\") || (($pc eq "\\") && ($ppc eq "\\")) ) ) { # we appear to have it... if ($sub) { $sub--; $dn1 = 1; next; # continue for next part of tr or s/.../.../ } $i++; # now check for MODS for (; $i < $len; $i++) { $c = substr($txt,$i,1); last if ( !($c =~ /\w/) ); if ($c =~ /[$mods]/) { $reg .= $c; } else { last; } } $ind += $i; ${$rp}{'REGEX'} = $reg; ${$rp}{'OFFSET'} = $ind; ${$rp}{'FLAG'} = $FG_NONE; ${$rp}{'REG1'} = $rege1; ${$rp}{'REG2'} = $rege2; prt( "Returning success [$reg] at off=[$ind] 1 [$rege1] 2 [$rege2]\n" ) if ($dbg01); return 1; } if ($dn1) { $rege2 .= $c; } else { $rege1 .= $c; } } last; } } #prt( "Returning FAILED\n" ); return 0; } sub ac_return_regex($$$$) { my ($txt,$roff,$rreg,$rflag) = @_; # like substr($line,$off), \$off, \$reg ) my ($ind); $ind = index($txt,'=~'); if ($ind >= 0) { $ind += 2; $txt = substr($txt,$ind); my %p = (); my $rp = \%p; ${$rp}{'TEXT'} = trim_all($txt); my ($rege1,$rege2); if (ac_return_regex2($rp)) { if (${$rp}{'FLAG'} == $FG_NONE) { $rege1 = ${$rp}{'REG1'}; $rege2 = ${$rp}{'REG2'}; ${$roff} = ${$rp}{'OFFSET'}; ${$rreg} = ${$rp}{'REGEX'}; ${$rflag} = ${$rp}{'FLAG'}; return 1; } } # return ac_return_regex2($txt,$roff,$rreg,$rflag); } #prt( "Returning FAILED\n" ); return 0; } # cut range # N N'th byte, char or field, counted from 1 # N- from N'th to end # N-M from N'th to M'th (included) # -M from 1st to M'th (included) sub get_cut_range($$) { my ($txt,$rrng) = @_; if ($txt =~ /^\d+$/) { # only digits if ($txt >= 1) { ${$rrng}[0] = 1; ${$rrng}[1] = $txt; return 1; } } elsif ($txt =~ /^\d+-\d*$/) { my @arr = split('-',$txt); my ($bgn,$end,$len); $len = scalar @arr; if ($len == 1) { $bgn = $arr[0]; if ($bgn >= 1) { ${$rrng}[0] = $bgn; ${$rrng}[1] = -1; return 1; } } elsif ($len == 2) { $bgn = $arr[0]; $end = $arr[1]; if (($bgn >= 1)&&($end >= $bgn)) { ${$rrng}[0] = $bgn; ${$rrng}[1] = $end; } } } elsif ($txt =~ /^-/) { $txt = substr($txt,1); if ($txt =~ /^\d+$/) { ${$rrng}[0] = 1; ${$rrng}[1] = $txt; return 1; } } return 0; } sub ac_set_by_shell_action($$$) { my ($rparams,$key,$rval) = @_; my $val = ${$rval}; # get the shell action string my (@arr,$len,$act,$k,$res,$find,$file,$rng,$oval,$rlen); $res = ''; $oval = $val; my $dir = ${$rparams}{'CURR_FILE_DIR'}; prt("Set by shell [$key] val [${$rval}], in dir [$dir]\n") if ($dbg37); if ($val =~ /^`(.+)`$/) { $val = $1; } $oval = $val; @arr = ac_local_space_split($val); $len = scalar @arr; if ($dbg37) { prt("Got space split... $len pieces...\n"); for ($k = 0; $k < $len; $k++) { $act = $arr[$k]; prt(" [$act]\n"); } } for ($k = 0; $k < $len; $k++) { $act = $arr[$k]; if ($act eq 'grep') { # ok expect 'something' in file if (($k + 2) < $len) { $k++; $find = strip_both_quotes($arr[$k]); $k++; $file = $arr[$k]; $file =~ s/\$\{srcdir\}/$dir/; $file = path_u2d($file); $file =~ s/\\\\/\\/g; prt("Act = $act, find [$find], in [$file]\n") if ($dbg37); $res = grep_for_value($file,$find); if (length($res)) { prt("Result: [$res]\n") if ($dbg37); } else { prtw("WARNING: grep_for_value: $act, find [$find], in [$file] in [$dir] FAILED!\n") if ($dbg37); } } } elsif ($act eq 'cut') { # expect - like cut -c 29- $k++; if ($k < $len) { $find = $arr[$k]; $k++; if ($k < $len) { $file = $arr[$k]; prt("Act = $act, type [$find], range [$file]\n") if ($dbg37); $rlen = length($res); if ($rlen) { my (@rng); # cut range if (get_cut_range($file,\@rng)) { my ($bgn,$end,$dif); $bgn = $rng[0]; $end = $rng[1]; prt("Got 'cut' range [$bgn] to [".(($end == -1) ? "End" : $end)."], on string [$rlen]\n") if ($dbg37); if ($end == -1) { if (($bgn - 1) < $rlen) { $val = substr($res,($bgn - 1)); } else { $val = ''; } } else { $dif = $end - $bgn + 1; $bgn--; $val = substr($res,$bgn,$dif); } } } } } } elsif ($act eq 'sed') { # sed -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' C:\Projects\curl\/include/curl/curlver.h # Got space split... 4 pieces... # [sed] [-ne] ['s/^#define LIBCURL_VERSION "\(.*\)"/\1/p'] [C:\Projects\curl\/include/curl/curlver.h] if ($len == 4) { $find = strip_both_quotes($arr[2]); $file = $arr[3]; $file = path_u2d($file); $file =~ s/\\\\/\\/g; prt("Act = $act, find [$find], in [$file]\n") if ($dbg37); my %p = (); my $rp = \%p; $p{'TEXT'} = $find; if (ac_return_regex2($rp)) { if (${$rp}{'FLAG'} == $FG_NONE) { #$reg = ${$rp}{'REGEX'}; #$off = ${$rp}{'OFFSET'}; my $rege1 = ${$rp}{'REG1'}; my @ar2 = ac_local_space_split($rege1); if (scalar @ar2 >= 2) { my $f1 = $ar2[0]; my $f2 = $ar2[1]; if (open INF, "<$file") { while () { if (/^$f1\s+$f2\s+(.+)$/) { $val = $1; $val = strip_both_quotes($val); last; } } close INF; } } } } $k += 3; } } elsif ($act eq '|') { prt("Act = $act\n") if ($dbg37); } else { prt("Item NOT handled [$act]\n") if ($dbg37); } } if ($dbg37) { prt("Setting NEW value [$val]\n") if ($val ne $oval); } #exit(1); ${$rval} = $val; } # ======================================================== # split ac file macro # 1: $MACRO\W # 2: $(MACRO) # 3: ${MACRO} # Not done @MACRO@ # input: # $val = string value to SPLIT # $add = 0=only macro keys in array # 1=Macro key, and other bits in array sub ac_split_macros($$) { my ($val,$add) = @_; my $len = length($val); my @arr = (); my $tag = ''; my ($i,$ch,$nxt,$nc,$k,$pc,$i2,$cn,$min); for ($i = 0; $i < $len; $i++) { $i2 = $i + 1; $ch = substr($val,$i,1); if ($ch eq '$') { # got the beginning '$' char, so get NEXT $cn = (($i2 < $len) ? substr($val,$i2,1) : ''); $nxt = $ch; $k = $i + 1; $pc = ''; # NO end cahr $min = 3; # has to be '$12' - a length greater than this if ($cn eq '{') { $pc = '}'; # set end '}' $nxt .= $cn; $k++; $min = 5; } elsif ($cn eq '(') { $pc = ')'; # set end ')' $nxt .= $cn; $k++; $min = 5; } for (; $k < $len; $k++) { $nc = substr($val,$k,1); if ($nc =~ /\W/) { # NOT an alpha-numeric + '_', then # hmmm, what to do about things like ${DEFAULT_BLOCKING-20} if ($nc eq $pc) { $nxt .= $nc; $k++; } elsif (length($pc)) { $nxt = ''; # NOT HANDLED like ${DEFAULT_BLOCKING-20} } last; } $nxt .= $nc; } if (length($nxt) > $min) { push(@arr,$tag) if (length($tag) && $add); push(@arr,$nxt); $tag = ''; $i = $k - 1; $ch = ''; next; } } $tag .= $ch; } push(@arr,$tag) if (length($tag) && $add); if ($dbg_lac14) { $len = scalar @arr; prt("[14] Value [$val] split into $len pieces...\n"); $len = 0; foreach $nxt (@arr) { $len++; prt(" $len: [$nxt]\n"); } } return \@arr; } sub ac_add_2_ac_macros($$$) { my ($key,$val,$rcacm) = @_; #prt("[18] ac_add_2_ac_macros: KEY = [$key] VALUE = [$val]\n"); if (defined ${$rcacm}{$key}) { my $cval = ${$rcacm}{$key}; prt("[18] KEY: [$key] Replacing [$cval], with [$val]\n") if ($dbg_lac18); } else { prt("[18] KEY: [$key] Setting [$val]\n") if ($dbg_lac18); } ${$rcacm}{$key} = $val; } sub ac_do_macro_subs($$$); # $nval = ac_do_macro_sub($nval,$rmh); # 13/09/2010 - Added USER supplied, and do this FIRST # 27/09/2010 - Added GLOBAL hash, and do this LAST sub ac_do_macro_subs($$$) { my ($val,$src,$rparams) = @_; my $ruserh = ${$rparams}{'CURR_USERS_SUBS'}; # user supplied MACRO SUBS my $rmh = ${$rparams}{'CURR_AC_MAC'}; my $key = ${$rparams}{'CURR_KEY'}; my $rch = ${$rparams}{'CURR_COMMON_SUBS'}; my $rgh = ${$rparams}{'REF_GLOBAL_HASH'}; if ($val =~ /^`(.+)`$/) { $val = $1; # stripped outer shell quotes # prt("Value before [$val]\n"); $val = ac_do_macro_subs($val,$src,$rparams); # prt("Value after [$val]\n"); ac_set_by_shell_action($rparams,$key,\$val); } if ($val =~ /\$/) { my $rvarr = ac_split_macros($val,0); my ($blk,$key2,$nval,$done,$cnt,$oline,$typ,$typ2,$msg); my %failed_macro = (); $cnt = 0; $oline = $val; foreach $blk (@{$rvarr}) { if ($blk =~ /\$/) { $done = 0; $key2 = ''; $typ = 0; $typ2 = 0; # 1: if a bare '$ABC' if ($blk =~ /^\$(\w+)$/) { $key2 = $1; $typ = 1; if (defined ${$ruserh}{$key2}) { $nval = ${$ruserh}{$key2}; $done = 1; $typ2 = 4; $cnt++; } elsif (defined ${$rmh}{$key2}) { $nval = ${$rmh}{$key2}; $done = 1; $typ2 = 1; $cnt++; } elsif (defined ${$rch}{$key2}) { $nval = ${$rch}{$key2}; $done = 1; $typ2 = 2; $cnt++; } elsif (defined ${$rgh}{$key2}) { $nval = ${$rgh}{$key2}; $done = 1; $typ2 = 5; $cnt++; } elsif ($key eq $key2) { $nval = ''; ac_add_2_ac_macros($key2,$nval,$rmh); $done = 1; $typ2 = 3; $cnt++; } if ($done) { if (length($nval)) { $val =~ s/\$$key2/$nval/; } else { $val =~ s/\$$key2\s*//; } } # 2: if a curly '${ABC}' } elsif ($blk =~ /^\$\{(\w+)\}$/) { $key2 = $1; $typ = 2; if (defined ${$ruserh}{$key2}) { $nval = ${$ruserh}{$key2}; $done = 1; $typ2 = 4; $cnt++; } elsif (defined ${$rmh}{$key2}) { $nval = ${$rmh}{$key2}; $done = 1; $typ2 = 1; $cnt++; } elsif (defined ${$rch}{$key2}) { $nval = ${$rch}{$key2}; $done = 1; $typ2 = 2; $cnt++; } elsif (defined ${$rgh}{$key2}) { $nval = ${$rgh}{$key2}; $done = 1; $typ2 = 5; $cnt++; } elsif ($key eq $key2) { $nval = ''; ac_add_2_ac_macros($key2,$nval,$rmh); $typ2 = 3; $done = 1; $cnt++; } if ($done) { if (length($nval)) { $val =~ s/\$\{$key2\}/$nval/; } else { $val =~ s/\$\{$key2\}\s*//; } } # 3: if a bracket '$(ABC)' } elsif ($blk =~ /^\$\((\w+)\)$/) { $key2 = $1; $typ = 3; if (defined ${$ruserh}{$key2}) { $nval = ${$ruserh}{$key2}; $done = 1; $typ2 = 4; $cnt++; } elsif (defined ${$rmh}{$key2}) { $nval = ${$rmh}{$key2}; $done = 1; $typ2 = 1; $cnt++; } elsif (defined ${$rch}{$key2}) { $nval = ${$rch}{$key2}; $done = 1; $typ2 = 2; $cnt++; } elsif (defined ${$rgh}{$key2}) { $nval = ${$rgh}{$key2}; $done = 1; $typ2 = 5; $cnt++; } elsif ($key eq $key2) { $nval = ''; ac_add_2_ac_macros($key2,$nval,$rmh); $done = 1; $typ2 = 3; $cnt++; } if ($done) { if (length($nval)) { $val =~ s/\$\($key2\)/$nval/; } else { $val =~ s/\$\($key2\)\s*//; } } } # ========================================================================================== if ($done) { prt("[17] ac macro subs:$typ:$typ2: [$key2] for [$nval]\n") if ($dbg_lac17); } elsif (!$done && $src) { my $file = ${$rparams}{'CURR_FILE'}; my $lnn = ${$rparams}{'CURR_LINENUM'}; $msg = "[13] $lnn: Failed on MACRO [$key] = [$blk], [$typ] [$key2], in file [$file]"; if (!defined $failed_macro{$msg}) { $failed_macro{$msg} = 1; prt("$msg\n") if ($dbg_lac13); } $key2 = $blk if (!$typ); my $rsnf = ${$rparams}{'CURR_SUBS_NOT_FOUND'}; if (! defined ${$rsnf}{$key2}) { # keep the first instance of not found ${$rsnf}{$key2} = "$lnn:$file"; } } # ========================================================================================== } } } return $val; } # ======================================================================= # based on ALL AC_MACROS are of the form # AC_MACRO([...],....,....), could also check [ ], but that's for later.. # $cline = accumulate_ac_macro($cline,$lncnt,\$ln,\@lines); # ======================================================================= sub accumulate_ac_macro($$$$) { my ($iline,$lncnt,$ri,$rlines) = @_; my ($i,$ch,$brcnt,$k,$k2,$lcnt,$acmac,$oline,$sqcnt,$bgnln); # prt("Accumulate AC MACRO until end...\n"); $k = ${$ri}; # extract current line number, 0 based $bgnln = $k + 1; $oline = $iline; my $len = length($iline); prt("[dbg_extra3] $bgnln: Doing line [$iline], len $len\n") if ($dbg_extra3); # eat any initial space only for ($i = 0; $i < $len; $i++) { $ch = substr($iline,$i,1); last if ($ch =~ /\S/); # stop on first non-white space } $acmac = ''; # accumulate the name of the MACRO for (; $i < $len; $i++) { $ch = substr($iline,$i,1); last if ($ch =~ /\W/); # stop on non-alpha-numeric - should be '(' $acmac .= $ch; } # could allow 'space' BEFORE '(' # ONE DAY pgm_exit(1,"ERROR: mac=[$acmac] Fix eat_ac_macro to accept [$ch] following 'name'!\n") if ($ch ne '('); # essentially get to END of MACRO - may be mutiple lines $i++; # note, BUMP past FIRST '(', and set $brcnt == 0 $brcnt = 0; $sqcnt = 0; $lcnt = 1; for (; $i < $len; $i++) { $ch = substr($iline,$i,1); if ($ch eq '(') { if (!$sqcnt) { $brcnt++; prt("[dbg_extra2]:1:$i:$len: br=$brcnt sq=$sqcnt bumped br count\n") if ($dbg_extra2); } else { prt("[dbg_extra2]:1:$i:$len: br=$brcnt sq=$sqcnt skipped br count due sqcnt\n") if ($dbg_extra2); } } elsif ($ch eq '[') { $sqcnt++; prt("[dbg_extra2]:1:$i:$len: br=$brcnt sq=$sqcnt bumped sq count\n") if ($dbg_extra2); } elsif ($ch eq ']') { prt("[dbg_extra2]:1:$i:$len: br=$brcnt sq=$sqcnt will decrement sq count\n") if ($dbg_extra2); $sqcnt-- if ($sqcnt); } elsif ($ch eq ')') { if ($sqcnt) { $ch = ''; prt("[dbg_extra2]:1:$i:$len: br=$brcnt sq=$sqcnt skipped br decement due sq count\n") if ($dbg_extra2); } else { if ($brcnt) { $brcnt--; $ch = ''; prt("[dbg_extra2]:1:$i:$len: br=$brcnt sq=$sqcnt decrement br count\n") if ($dbg_extra2); } else { prt("[dbg_extra2]:1:$i:$len: br=$brcnt sq=$sqcnt EXIT0\n") if ($dbg_extra2); last; } } } } if ($ch ne ')') { # oops, need more lines $k++; $k2 = $k + 1; my $nline = ''; prt( "\n[dbg_extra] br=$brcnt sq=$sqcnt no closed! Get next line $k, of $lncnt lines\n" ) if ($dbg_extra); while ($k < $lncnt) { #prt( "$k2:$.: need more lines...br=$brcnt, sq=$sqcnt...\n" ); # if ($dbg01); $nline = trim_all(${$rlines}[$k]); $lcnt++; $len = length($nline); prt( "[dbg_extra] br=$brcnt sq=$sqcnt line=$lcnt, len=$len [$nline]\n" ) if ($dbg_extra); for ($i = 0; $i < $len; $i++) { $ch = substr($nline,$i,1); if ($ch eq '(') { if ($sqcnt) { $ch = ''; prt("[dbg_extra] br=$brcnt sq=$sqcnt skipped br count due sqcnt\n") if ($dbg_extra); } else { $brcnt++; prt("[dbg_extra] br=$brcnt sq=$sqcnt bumped br count\n") if ($dbg_extra); } } elsif ($ch eq '[') { $sqcnt++; prt("[dbg_extra] br=$brcnt sq=$sqcnt bumped sq count\n") if ($dbg_extra); } elsif ($ch eq ']') { prt("[dbg_extra] br=$brcnt sq=$sqcnt will decrement sq count\n") if ($dbg_extra); $sqcnt-- if ($sqcnt); } elsif ($ch eq ')') { if ($sqcnt) { $ch = ''; prt("[dbg_extra] br=$brcnt sq=$sqcnt skipped br decement due sq count\n") if ($dbg_extra); } else { if ($brcnt) { $brcnt--; $ch = ''; # CLEAR this char - is NOT the end prt("[dbg_extra] br=$brcnt sq=$sqcnt decrement sq count\n") if ($dbg_extra); } else { prt("[dbg_extra] br=$brcnt sq=$sqcnt EXIT1\n") if ($dbg_extra); last; } } } } if ($ch eq ')') { prt("[dbg_extra] br=$brcnt sq=$sqcnt EXIT2\n") if ($dbg_extra); if (length($nline)) { #$iline .= ' ' if ( !( ($iline =~ /\s$/) || ($nline =~ /^\s/) ) ); $iline .= " "; # "\n"; $iline .= $nline; $nline = ''; } last; } $k++; # need MORE $k2 = $k + 1; if (length($nline)) { #$iline .= ' ' if ( !( ($iline =~ /\s$/) || ($nline =~ /^\s/) ) ); $iline .= " "; #"\n"; $iline .= $nline; $nline = ''; } } if ($k >= $lncnt) { $ch = ${$ri}; # extract current line number prt("Started at line $ch, and now at line $k, of $lncnt, searching AC MACRO [$acmac] end...\n"); $iline = trim_all($iline); if (length($iline) > 200) { $nline = substr($iline,0,100)."...\n".substr($iline,(length($iline) - 100)); prt("Have accumulated [$nline]!\n"); } else { prt("Have accumulated [$iline]!\n"); } pgm_exit(1,"ERROR: Ran out of line in an ac macro!\n"); } ${$ri} = $k; # pass back new line number } else { prt( "[dbg_extra] Closed in current line\n" ) if ($dbg_extra); } if ($dbg_lac15 && ($oline ne $iline)) { prt("Accumulated from [$bgnln]\n[$oline] to line $k2\n[$iline]\n"); } return $iline; } # $cline = accumulate_with_back($cline,$lncnt,\$ln,\@lines); sub accumulate_with_back($$$$) { my ($iline,$lncnt,$rln,$rlines) = @_; my ($nline,$oline); $oline = $iline; $oline =~ s/\\$//; $oline = substr($oline,0,length($oline) - 1) while ($oline =~ /\s$/); # remove all TRAILING space my $ln = ${$rln}; while ($iline =~ /\\$/) { $iline =~ s/\\$//; # remove '\' $iline = substr($iline,0,length($iline) - 1) while ($iline =~ /\s$/); # remove all TRAILING space $ln++; if ($ln < $lncnt) { $nline = trim_all(${$rlines}[$ln]); if (length($nline)) { $iline .= " "; $iline .= $nline; } } else { last; } } ${$rln} = $ln; # pass back potentially new line... if ($dbg_lac16 && ($oline ne $iline)) { prt("Accumulated back from\n[$oline] to line $ln\n[$iline]\n"); } return $iline; } #ac_am_conf_line_error($filename, # $., "automake requires 'AM_CONFIG_HEADER', not 'AC_CONFIG_HEADER'") if $1 eq 'C'; sub ac_am_conf_line_error($$$) { my ($fname,$lnum,$msg) = @_; prt("ERROR: file $fname: line $lnum: $msg\n"); mydie("Aborting scan ...\n"); } sub ac_trim_all2 { my ($txt) = shift; $txt = trim_all($txt); if ($txt =~ /^\[.+\]$/) { $txt = substr($txt,1,length($txt)-2); } $txt = trim_all($txt); return $txt; } sub trim_ac_define($) { my ($txt) = shift; my $len = length($txt); my $ntxt = ''; my ($i,$ch,$brcnt,$sqcnt); $brcnt = 0; $sqcnt = 0; for ($i = 0; $i < $len; $i++) { $ch = substr($txt,$i,1); $ntxt .= $ch; if ($ch eq '[') { $sqcnt++; } elsif ($ch eq ']') { $sqcnt-- if ($sqcnt); } elsif ($ch eq '(') { if (!$sqcnt) { $brcnt++; } } elsif ($ch eq ')') { if (!$sqcnt) { if ($brcnt) { $brcnt--; } else { last; } } } } return $ntxt; } # 14/10/2011 - Found a case where only 2 Makefile.am found in configure.ac scan, BUT there is a line # [01] 39: [AC_CONFIG_SUBDIRS(autoconf-lib-link gettext-runtime gettext-tools)], and these SUBDIRS do # contain Makefile.am files... so add them to the list of AM to scan # tried very HARD to use while () but it seems WRONG sometimes # so do a FULL LINE READ, and CLOSE FILE sub scan_configure_ac_file($$) { my ($rparams,$lev) = @_; ac_set_debug_flags(${$rparams}{'CURR_DEBUG_FLAG'}) if (!$ac_done_debug_flags); my $filename = ${$rparams}{'CURR_FILE'}; #my $rch = ${$rparams}{'CURR_COMMON_SUBS'}; #my $ruserh = ${$rparams}{'CURR_USERS_SUBS'}; my ($sfilnm,$root_dir) = fileparse($filename); my $in_ac_output = 0; my $ac_output_line = ''; my %var_hash = (); my $ac_prog = ''; # this is an IMPORTANT name set by AC_INIT but hopefully later by AM_INIT_AUTOMAKE my $ac_vers = ''; my %make_list = (); my ($roif); my $rh = ${$rparams}{'CURR_HASH'}; my $racdefs = ${$rparams}{'REF_DEF_CONDITIONS'}; # get user CONDITIONALS my $racmacs = ${$rparams}{'CURR_AC_MAC'}; my $rsnf = ${$rparams}{'CURR_SUBS_NOT_FOUND'}; my $ramil = ${$rparams}{'CURR_MAKE_INP_LIST'}; my $supp_in = ${$rparams}{'SUPP_MAKE_IN'}; if ($lev == 0) { my @other_in_files = (); $roif = \@other_in_files; } else { $roif = ${$rh}{'A_OTHER_INPUT_LIST'}; } my $config_header_line = ''; my @config_fullnames = (); my @config_names = (); my @config_headers = (); my %configure_cond = (); my ($err_msg); my ($ln,$lncnt,$lnn,$tline,$ff,$cline); my ($key,$nval,$orgkey,$orgnval,@varr,$vlen,$i,$ky,$nline,$msg,$tmp); my $scan_flag = 0; #my %ac_defines = (); #my $racdefs = \%ac_defines; if (!open(CONFIGURE, $filename)) { pgm_exit(1,"ERROR: can not open [$filename]: $!\n"); } my @lines = ; close CONFIGURE; $lncnt = scalar @lines; ${$rparams}{'TOTAL_LINE_COUNT'} += $lncnt; prt("[01] SCAN CONFIGURE AC FILE: Reading [$filename], $lncnt lines... level=$lev\n" ) if $dbg_lac01; # ============================================================ for ($ln = 0; $ln < $lncnt; $ln++) { $cline = $lines[$ln]; # get current line chomp $cline; $nline = $cline; $lnn = $ln + 1; prt( "[01] $lnn: [$cline]\n" ) if ($dbg_lac01); # Remove comments from current line. $cline =~ s/\bdnl\b.*$//; $cline =~ s/^\#.*$//; $tline = trim_all($cline); next if (length($tline) == 0); if ($cline =~ /\\$/) { $cline = accumulate_with_back($cline,$lncnt,\$ln,\@lines); } if ($cline =~ /^\s*\w+\(.*$/) { $cline = accumulate_ac_macro($cline,$lncnt,\$ln,\@lines); } $lnn = $ln + 1; if ($cline =~ /(\$|\@)/) { ${$rparams}{'CURR_KEY'} = ""; ${$rparams}{'CURR_LINENUM'} = $lnn; $cline = ac_do_macro_subs($cline,1,$rparams); } $tline = trim_all($cline); prt( "[02] $lnn: [$cline]\n" ) if ($dbg_lac02 && ($nline ne $cline)); if ($cline =~ /^(\w+)="(\d+)"$/) { $key = $1; $nval = $2; prt("[03] $lnn: Num Variable $key=$nval\n") if ($dbg_lac03); $var_hash{$key} = $nval; ac_add_2_ac_macros($key, $nval, $racmacs); ###} elsif ($cline =~ /^(\w+)="(.+)"$/) { ###} elsif ($cline =~ /^(\w+)=(.+)$/) { } elsif ($cline =~ /^\s*(\w+)=(.+)$/) { $key = $1; $nval = $2; $nval = substr($nval,1,length($nval)-2) if ($nval =~ /^".*"$/); $orgkey = $key; $orgnval = $nval; prt( "[03] $lnn: Var [$key] = [$nval], ln [$cline]\n" ) if ($dbg_lac03); ${$rparams}{'CURR_KEY'} = $key; ${$rparams}{'CURR_LINENUM'} = $lnn; $nval = ac_do_macro_subs($nval,1,$rparams); if ($dbg_lac05) { if (($orgkey ne $key)||($orgnval ne $nval)) { prt( "[05] Substitute [$key] = [$nval]\n" ); } elsif (($orgkey =~ /\$/)||($orgnval =~ /\$/)) { prt( "[05] Sub FAILED [$key] = [$nval]\n" ); } } $var_hash{$key} = $nval; ac_add_2_ac_macros($key, $nval, $racmacs); # $conf_ac_macs{$key} = $nval; } elsif ($cline =~ /^\s+(\w+)=(.+)$/) { prt( "[12] $lnn: 1=[$1] = 2=[$2] NOT USED [$cline]\n" ) if ($dbg_lac12); # there are lots of them ... } # Skip macro definitions. Otherwise we might be confused into # thinking that a macro that was only defined was actually # used. if ($cline =~ /AC_DEFUN/) { prt( "[07] $lnn: Got AC_DEFUN = [$cline] SKIPPING\n" ) if ($dbg_lac07); next; } if ($cline =~ /$AC_INIT/) { $nval = trim_all($1); # Macro: AC_INIT (package, version, [bug-report], [tarname], [url]) # but can sometimes just be a FILE NAME $scan_flag |= 1; @varr = split(',', $nval); $vlen = scalar @varr; if ($dbg_lac07) { prt( "[07] $lnn: Got AC_INIT = [$nval] $vlen items {" ); for ($i = 0; $i < $vlen; $i++) { $nval = trim_all(strip_square_braces(trim_all($varr[$i]))); prt("$nval"); prt(", ") if (($i + 1) < $vlen); } prt("}\n"); } for ($i = 0; $i < $vlen; $i++) { $nval = trim_all(strip_square_braces(trim_all($varr[$i]))); if ($i == 0) { $nval =~ s/\s/_/g; if ($nval =~ /(\\|\/)/) { # looks like a FILE name ($nval,$key) = fileparse($nval); $nval =~ s/\./_/g; } ac_add_2_ac_macros('PACKAGE_NAME', $nval, $racmacs); prt("[07] $lnn:AC_INIT: Setting PACKAGE_NAME = [$nval]\n") if ($dbg_lac07); ${$rparams}{'PROJECT_NAME'} = $nval; # overall PROJECT NAME $ac_prog = $nval; } elsif ($i == 1) { ac_add_2_ac_macros('PACKAGE_VERSION', $nval, $racmacs); ac_add_2_ac_macros('PACKAGE_STRING', ${$racmacs}{'PACKAGE_NAME'} .' ' .$nval, $racmacs ); $ac_vers = $nval; } elsif ($i == 2) { ac_add_2_ac_macros('PACKAGE_BUGREPORT', $nval, $racmacs); } elsif ($i == 3) { ac_add_2_ac_macros('PACKAGE_TARNAME', $nval, $racmacs); } elsif ($i == 4) { # 08/09/2010 - added ac_add_2_ac_macros('PACKAGE_URL', $nval, $racmacs); } else { $err_msg = "WARNING: $i Split of AC_INIT = $nval\n"; prtw($err_msg); } } next; } elsif ($cline =~ /$AC_DEFINE/) { $nval = trim_ac_define($1); prt( "[07] $lnn: Got AC_DEFINE = [$nval]\n" ) if ($dbg_lac07); @varr = split(',', $nval); $vlen = scalar @varr; if ($vlen >= 2) { $ky = ac_trim_all2($varr[0]); $nval = ac_trim_all2($varr[1]); ac_add_2_ac_macros( $ky, $nval, $racmacs ); } next; } elsif ($cline =~ /$AC_DEFINE_UNQ/) { $nval = trim_ac_define($1); prt( "[07] $lnn: Got AC_DEFINE_UNQUOTED = [$nval]\n" ) if ($dbg_lac07); @varr = split(',', $nval); $vlen = scalar @varr; if ($vlen >= 2) { $ky = ac_trim_all2($varr[0]); $nval = ac_trim_all2($varr[1]); ac_add_2_ac_macros( $ky, $nval, $racmacs ); } next; } elsif ($cline =~ /$AC_CONF_SUBDIRS/) { # [01] 39: [AC_CONFIG_SUBDIRS(autoconf-lib-link gettext-runtime gettext-tools)], # and these SUBDIRS can contain Makefile.am files, so... $nval = trim_all($1); prt( "[07] $lnn: Got AC_CONFIG_SUBDIRS = [$nval]\n" ) if ($dbg_lac07); @varr = split(/\s+/, $nval); $vlen = scalar @varr; foreach $ky (@varr) { $ky .= "\\" if ( !($ky =~ /(\\|\/)$/) ); $ky .= "Makefile"; $ff = $root_dir; $ff .= "\\" if ( !($ff =~ /(\\|\/)$/) && !($ky =~ /^(\\|\/)/) ); $ff .= $ky; $ff .= ".am"; if (-f $ff) { prt( "[01|09] Adding $ky [$ff] to mk_inp_list ...\n" ) if ($dbg_lac01 || $dbg_lac09); push(@{$ramil}, $ky); } else { prtw("WARNING: Makefile.am NOT found in [$ff]!\n"); } # Should MAYBE search this SUBDIR/Makefile.am for sub-directories # =============================================================== } } # Follow includes. This is a weirdness commonly in use at # Cygnus and hopefully nowhere else. if (($cline =~ /sinclude\((.*)\)/)||($cline =~ /\s*include\((.*)\)/)) { $ff = $root_dir.$1; if ( -f $ff ) { ${$rparams}{'CURR_FILE'} = $ff; ${$rh}{'H_CONF_AC_MACS'} = $racmacs; ${$rh}{'A_MAKE_INPUT_LIST'} = $ramil; ${$rh}{'R_SUBS_NOT_FOUND'} = $rsnf; ${$rh}{'A_OTHER_INPUT_LIST'} = $roif; scan_configure_ac_file($rparams,($lev + 1)); ${$rparams}{'CURR_FILE'} = $filename; } else { prtw("WARNING:$lnn: Unable to find INCLUDE [$ff], line [$_], in [$filename]\n"); } } if (! $in_ac_output && ($cline =~ s/AC_OUTPUT\s*\(\[?// || $cline =~ s/AC_CONFIG_FILES\s*\(\[?// ) ) { $in_ac_output = 1; $ac_output_line = $lnn; # get LINE number prt( "[08] Got ac_output_line = line $ac_output_line ... [$tline]\n" ) if ($dbg_lac08); } if ($in_ac_output) { my $closing = 0; if ($cline =~ s/[\]\),].*$//) { $in_ac_output = 0; $closing = 1; prt( "[08] ac_out: [$tline] CLOSING\n" ) if ($dbg_lac08); } else { prt( "[08] ac_out: [$tline]\n" ) if ($dbg_lac08); } # Look at potential Makefile.am's @varr = split(/\s+/,$cline); # FIX20110306 - split on multiple spaces \s+ foreach $nline (@varr) { # Must skip empty string for Perl 4. next if (($nline eq "\\") || ($nline eq '')); $nline = path_u2d($nline); # FIX20110306 - ensure DOS path only my ($local,$input,@rest) = split(/:/,$nline); my ($inp2); if (! $input) { $input = $local; $inp2 = $local; } else { $inp2 = $input; $input =~ s/\.in$//; } if ($input =~ /Makefile/) { $ff = $root_dir . $input . '.am'; if ($supp_in && ( ! -f $ff ) && ( -f $root_dir.$input.'.in') ) { $ff = $root_dir.$input.'.in'; } if (-f $ff) { prt( "[01|09] Adding $input [$ff] to mk_inp_list ...\n" ) if ($dbg_lac01 || $dbg_lac09); push(@{$ramil}, $input); $make_list{$input} = join(':', ($local,@rest)); } else { prt( "[01|10] M NOT LOCATED [$ff] [$input] to other_input_files ...\n" ) if ($dbg_lac01 || $dbg_lac10); # We have a file that automake should cause to be # rebuilt, but shouldn't generate itself. push (@{$roif}, $nline); } } else { # NOT a Makefile # We have a file that automake should cause to be # rebuilt, but shouldn't generate itself. $ff = $root_dir . $inp2; if (-f $ff) { prt( "[01|10] O found [$ff] [$inp2] to other_input_files ...\n" ) if ($dbg_lac01 || $dbg_lac10); push (@{$roif}, $inp2); } else { prt( "[01|10] O NOT LOCATED [$ff] [$inp2] to other_input_files ...\n" ) if ($dbg_lac01 || $dbg_lac10); push (@{$roif}, $nline); } } } } # Handle configuration headers. A config header of `[$1]' # means we are actually scanning AM_CONFIG_HEADER from # aclocal.m4. if (($cline =~ /A([CM])_CONFIG_HEADER\s*\((.*)\)/) && ($2 ne '[$1]')) { if ($abort_on_ac_config) { ac_am_conf_line_error($filename, $lnn, "automake requires 'AM_CONFIG_HEADER', not 'AC_CONFIG_HEADER'") if $1 eq 'C'; } else { # 23/09/2010 - downgrade to a NOTE prt("[11] NOTE: $lnn: automake requires 'AM_CONFIG_HEADER', not 'AC_CONFIG_HEADER'!\n file [$filename]\n") if ($dbg_lac11); } $config_header_line = $lnn; my ($one_hdr); foreach $one_hdr (split (' ', $2)) { push (@config_fullnames, $one_hdr); if ($one_hdr =~ /^([^:]+):(.+)$/) { push (@config_names, $1); push (@config_headers, $2); } else { push (@config_names, $one_hdr); push (@config_headers, $one_hdr . '.in'); } } } if ($cline =~ /$AM_CONDITIONAL_PATTERN/o) { $nval = $1; if ( defined ${$racdefs}{$nval} ) { # has been DEFINED in am2dsp?.cfg file, that is by the USER $tmp = 2; $msg = ${$racdefs}{$nval}; } else { $tmp = 1; $msg = 'NOT USER DEFINED'; } $configure_cond{$nval} = $tmp; prt( "[11] Storing configure_cond key [$nval]... value=[$msg] ($tmp)\n" ) if ($dbg_lac11); } if ($cline =~ /$AM_INIT_AUTOMAKE/o) { $ac_prog = $1; $ac_vers = $2; prt( "[07] $lnn: Got AM_INIT_AUTOMAKE = [$ac_prog] [$ac_vers] [$tline]\n" ) if ($dbg_lac07); $scan_flag |= 2; #$ac_prog = ac_do_macro_subs($ac_prog,0,$rparams); #${$rparams}{'CURR_KEY'} = $ac_prog; #$ac_prog = ac_do_macro_subs($ac_vers,0,$rparams); if (defined ${$rh}{'-NEW_PROJECT_NAME-'}) { if (${$rh}{'-NEW_PROJECT_NAME-'} ne $ac_prog) { prtw("WARNING: CHANGED DSP package from ".${$rh}{'-NEW_PROJECT_NAME-'}." to $ac_prog, DSP version = $ac_vers ...\n" ); } } ac_add_2_ac_macros('PACKAGE_NAME', $ac_prog, $racmacs); prt("[07] $lnn:AM_INIT_AUTOMAKE: Setting PACKAGE_NAME = [$ac_prog]\n") if ($dbg_lac07); } } if ($lev == 0) { if (( !($scan_flag & 1) && !($scan_flag & 2)) || (length($ac_prog)==0) || ($ac_prog =~ /^\s+$/)) { $msg = "\nBIG BIG WARNING: Parsing [$filename]\n"; $msg .= " You supplied an INVALID input. It has bad (or missing) AC_INIT or AM_INIT_AUTOMAKE macros!\n"; $msg .= " Check that you supplied a valid input file, such as 'configure.ac' or 'configure.in'!\n"; if (($filename =~ /\.(ac)$/)||($filename =~ /\.(in)$/)) { $msg .= " Although it has an '$1' extension, it does NOT look like a configure[.ac|.in] file!\n"; } else { $msg .= " What you supplied does NOT have a '.ac', nor '.in' extension!\n"; } if ($sfilnm =~ /^configure/) { $msg .= " And although it starts with 'configure', it does NOT feel like a configure[.ac|.in] file!\n"; } else { $msg .= " And also note it does NOT start with 'configure'!\n"; } $msg .= " Simply, [$sfilnm] is not a valid file for input. Try another...\n"; $msg .= " NOTE: You may see many other warnings, and perhaps errors after here,\n since this is a VERY BAD START ;=()\n"; prtw("$msg\n"); } $nval = ((defined ${$rparams}{'PROJECT_NAME_MASTER'}) ? ${$rparams}{'PROJECT_NAME_MASTER'} : ''); if (length($nval) && ($nval ne $ac_prog)) { prt("Over-ridding current [$ac_prog], with user [$nval], as master project name\n"); $ac_prog = $nval; } else { if (($scan_flag & 1) && !($scan_flag & 2)) { prtw("WARNING: Project NAME [$ac_prog] only set from AC_INIT, no AM_INIT_ATUOMAKE found!\n"); } } if ((length($ac_prog) == 0)||($ac_prog =~ /^\s+$/)) { prtw("WARNING: Blank (or spacey) program name [$ac_prog]!\n". " Setting it to be 'temp_no_name' for now,\n". " but you can use '-n ' to set your OWN project name.\n"); $ac_prog = 'temp_no_name'; } if ( !($ac_prog =~ /^[\+\-\w]+$/) ) { $nval = $ac_prog; # keep original for comparison $ac_prog = trim_all(strip_square_braces(trim_all($ac_prog))); $ac_prog =~ s/\./_/g; $ac_prog =~ s/(\\|\/)/_/g; $ac_prog =~ s/\$/_/g; $ac_prog =~ s/\@/_/g; if ($ac_prog =~ /^[\+\-\w]+$/) { prtw("WARNING: Project name CHANGED from [$nval] TO [$ac_prog]\n"); } else { $lnn = __LINE__; $msg = "\nBIG WARNING: Project name "; if ($nval eq $ac_prog) { $msg .= "MASSAGED but remains unchanged as [$ac_prog]\n"; } else { $msg .= "CHANGED from [$nval] TO [$ac_prog]\n"; } $msg .= "BUT IS STILL NOT ALL alphanumeric chars!!!\n". "NEED 'FIX' in lib_acscan.pl about line $lnn\n"; prtw("$msg\n"); } } ${$rparams}{'PROJECT_NAME'} = $ac_prog; # overall PROJECT NAME ${$rh}{'-NEW_PROJECT_NAME-'} = $ac_prog; ${$rh}{'H_CONF_AC_MACS'} = $racmacs; ${$rh}{'A_MAKE_INPUT_LIST'} = $ramil; ${$rh}{'R_SUBS_NOT_FOUND'} = $rsnf; ${$rh}{'A_OTHER_INPUT_LIST'} = $roif; } prt("[01] END SCAN CONFIGURE AC FILE: [$filename] $lncnt lines... level=$lev\n" ) if ($dbg_lac01); } 1; # eof - lib_acscan.pl