#!/usr/bin/perl # Kconfig.pl # # Copyright (C) 2006 Struan Bartlett # This software is licensed under the GPL v2 as described below. # # Also note that the GPL below is copyrighted by the Free Software # Foundation, but the instance of code that it refers to (Kconfig.pl) # is copyrighted by me, Struan Bartlett, who actually wrote it. # # Also note that the only valid version of the GPL as far as Kconfig.pl # is concerned is _this_ particular version of the license (ie v2, not # v2.2 or v3.x or whatever), unless explicitly otherwise stated. # # Struan Bartlett # ------------------------------------------------------------------------------- # # GNU GENERAL PUBLIC LICENSE # Version 2, June 1991 # # Copyright (C) 1989, 1991 Free Software Foundation, Inc. # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Everyone is permitted to copy and distribute verbatim copies # of this license document, but changing it is not allowed. # # Preamble # # The licenses for most software are designed to take away your # freedom to share and change it. By contrast, the GNU General Public # License is intended to guarantee your freedom to share and change free # software--to make sure the software is free for all its users. This # General Public License applies to most of the Free Software # Foundation's software and to any other program whose authors commit to # using it. (Some other Free Software Foundation software is covered by # the GNU Library General Public License instead.) You can apply it to # your programs, too. # # When we speak of free software, we are referring to freedom, not # price. Our General Public Licenses are designed to make sure that you # have the freedom to distribute copies of free software (and charge for # this service if you wish), that you receive source code or can get it # if you want it, that you can change the software or use pieces of it # in new free programs; and that you know you can do these things. # # To protect your rights, we need to make restrictions that forbid # anyone to deny you these rights or to ask you to surrender the rights. # These restrictions translate to certain responsibilities for you if you # distribute copies of the software, or if you modify it. # # For example, if you distribute copies of such a program, whether # gratis or for a fee, you must give the recipients all the rights that # you have. You must make sure that they, too, receive or can get the # source code. And you must show them these terms so they know their # rights. # # We protect your rights with two steps: (1) copyright the software, and # (2) offer you this license which gives you legal permission to copy, # distribute and/or modify the software. # # Also, for each author's protection and ours, we want to make certain # that everyone understands that there is no warranty for this free # software. If the software is modified by someone else and passed on, we # want its recipients to know that what they have is not the original, so # that any problems introduced by others will not reflect on the original # authors' reputations. # # Finally, any free program is threatened constantly by software # patents. We wish to avoid the danger that redistributors of a free # program will individually obtain patent licenses, in effect making the # program proprietary. To prevent this, we have made it clear that any # patent must be licensed for everyone's free use or not licensed at all. # # The precise terms and conditions for copying, distribution and # modification follow. # # GNU GENERAL PUBLIC LICENSE # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION # # 0. This License applies to any program or other work which contains # a notice placed by the copyright holder saying it may be distributed # under the terms of this General Public License. The "Program", below, # refers to any such program or work, and a "work based on the Program" # means either the Program or any derivative work under copyright law: # that is to say, a work containing the Program or a portion of it, # either verbatim or with modifications and/or translated into another # language. (Hereinafter, translation is included without limitation in # the term "modification".) Each licensee is addressed as "you". # # Activities other than copying, distribution and modification are not # covered by this License; they are outside its scope. The act of # running the Program is not restricted, and the output from the Program # is covered only if its contents constitute a work based on the # Program (independent of having been made by running the Program). # Whether that is true depends on what the Program does. # # 1. You may copy and distribute verbatim copies of the Program's # source code as you receive it, in any medium, provided that you # conspicuously and appropriately publish on each copy an appropriate # copyright notice and disclaimer of warranty; keep intact all the # notices that refer to this License and to the absence of any warranty; # and give any other recipients of the Program a copy of this License # along with the Program. # # You may charge a fee for the physical act of transferring a copy, and # you may at your option offer warranty protection in exchange for a fee. # # 2. You may modify your copy or copies of the Program or any portion # of it, thus forming a work based on the Program, and copy and # distribute such modifications or work under the terms of Section 1 # above, provided that you also meet all of these conditions: # # a) You must cause the modified files to carry prominent notices # stating that you changed the files and the date of any change. # # b) You must cause any work that you distribute or publish, that in # whole or in part contains or is derived from the Program or any # part thereof, to be licensed as a whole at no charge to all third # parties under the terms of this License. # # c) If the modified program normally reads commands interactively # when run, you must cause it, when started running for such # interactive use in the most ordinary way, to print or display an # announcement including an appropriate copyright notice and a # notice that there is no warranty (or else, saying that you provide # a warranty) and that users may redistribute the program under # these conditions, and telling the user how to view a copy of this # License. (Exception: if the Program itself is interactive but # does not normally print such an announcement, your work based on # the Program is not required to print an announcement.) # # These requirements apply to the modified work as a whole. If # identifiable sections of that work are not derived from the Program, # and can be reasonably considered independent and separate works in # themselves, then this License, and its terms, do not apply to those # sections when you distribute them as separate works. But when you # distribute the same sections as part of a whole which is a work based # on the Program, the distribution of the whole must be on the terms of # this License, whose permissions for other licensees extend to the # entire whole, and thus to each and every part regardless of who wrote it. # # Thus, it is not the intent of this section to claim rights or contest # your rights to work written entirely by you; rather, the intent is to # exercise the right to control the distribution of derivative or # collective works based on the Program. # # In addition, mere aggregation of another work not based on the Program # with the Program (or with a work based on the Program) on a volume of # a storage or distribution medium does not bring the other work under # the scope of this License. # # 3. You may copy and distribute the Program (or a work based on it, # under Section 2) in object code or executable form under the terms of # Sections 1 and 2 above provided that you also do one of the following: # # a) Accompany it with the complete corresponding machine-readable # source code, which must be distributed under the terms of Sections # 1 and 2 above on a medium customarily used for software interchange; or, # # b) Accompany it with a written offer, valid for at least three # years, to give any third party, for a charge no more than your # cost of physically performing source distribution, a complete # machine-readable copy of the corresponding source code, to be # distributed under the terms of Sections 1 and 2 above on a medium # customarily used for software interchange; or, # # c) Accompany it with the information you received as to the offer # to distribute corresponding source code. (This alternative is # allowed only for noncommercial distribution and only if you # received the program in object code or executable form with such # an offer, in accord with Subsection b above.) # # The source code for a work means the preferred form of the work for # making modifications to it. For an executable work, complete source # code means all the source code for all modules it contains, plus any # associated interface definition files, plus the scripts used to # control compilation and installation of the executable. However, as a # special exception, the source code distributed need not include # anything that is normally distributed (in either source or binary # form) with the major components (compiler, kernel, and so on) of the # operating system on which the executable runs, unless that component # itself accompanies the executable. # # If distribution of executable or object code is made by offering # access to copy from a designated place, then offering equivalent # access to copy the source code from the same place counts as # distribution of the source code, even though third parties are not # compelled to copy the source along with the object code. # # 4. You may not copy, modify, sublicense, or distribute the Program # except as expressly provided under this License. Any attempt # otherwise to copy, modify, sublicense or distribute the Program is # void, and will automatically terminate your rights under this License. # However, parties who have received copies, or rights, from you under # this License will not have their licenses terminated so long as such # parties remain in full compliance. # # 5. You are not required to accept this License, since you have not # signed it. However, nothing else grants you permission to modify or # distribute the Program or its derivative works. These actions are # prohibited by law if you do not accept this License. Therefore, by # modifying or distributing the Program (or any work based on the # Program), you indicate your acceptance of this License to do so, and # all its terms and conditions for copying, distributing or modifying # the Program or works based on it. # # 6. Each time you redistribute the Program (or any work based on the # Program), the recipient automatically receives a license from the # original licensor to copy, distribute or modify the Program subject to # these terms and conditions. You may not impose any further # restrictions on the recipients' exercise of the rights granted herein. # You are not responsible for enforcing compliance by third parties to # this License. # # 7. If, as a consequence of a court judgment or allegation of patent # infringement or for any other reason (not limited to patent issues), # conditions are imposed on you (whether by court order, agreement or # otherwise) that contradict the conditions of this License, they do not # excuse you from the conditions of this License. If you cannot # distribute so as to satisfy simultaneously your obligations under this # License and any other pertinent obligations, then as a consequence you # may not distribute the Program at all. For example, if a patent # license would not permit royalty-free redistribution of the Program by # all those who receive copies directly or indirectly through you, then # the only way you could satisfy both it and this License would be to # refrain entirely from distribution of the Program. # # If any portion of this section is held invalid or unenforceable under # any particular circumstance, the balance of the section is intended to # apply and the section as a whole is intended to apply in other # circumstances. # # It is not the purpose of this section to induce you to infringe any # patents or other property right claims or to contest validity of any # such claims; this section has the sole purpose of protecting the # integrity of the free software distribution system, which is # implemented by public license practices. Many people have made # generous contributions to the wide range of software distributed # through that system in reliance on consistent application of that # system; it is up to the author/donor to decide if he or she is willing # to distribute software through any other system and a licensee cannot # impose that choice. # # This section is intended to make thoroughly clear what is believed to # be a consequence of the rest of this License. # # 8. If the distribution and/or use of the Program is restricted in # certain countries either by patents or by copyrighted interfaces, the # original copyright holder who places the Program under this License # may add an explicit geographical distribution limitation excluding # those countries, so that distribution is permitted only in or among # countries not thus excluded. In such case, this License incorporates # the limitation as if written in the body of this License. # # 9. The Free Software Foundation may publish revised and/or new versions # of the General Public License from time to time. Such new versions will # be similar in spirit to the present version, but may differ in detail to # address new problems or concerns. # # Each version is given a distinguishing version number. If the Program # specifies a version number of this License which applies to it and "any # later version", you have the option of following the terms and conditions # either of that version or of any later version published by the Free # Software Foundation. If the Program does not specify a version number of # this License, you may choose any version ever published by the Free Software # Foundation. # # 10. If you wish to incorporate parts of the Program into other free # programs whose distribution conditions are different, write to the author # to ask for permission. For software which is copyrighted by the Free # Software Foundation, write to the Free Software Foundation; we sometimes # make exceptions for this. Our decision will be guided by the two goals # of preserving the free status of all derivatives of our free software and # of promoting the sharing and reuse of software generally. # # NO WARRANTY # # 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY # FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN # OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES # PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED # OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS # TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE # PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, # REPAIR OR CORRECTION. # # 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING # WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR # REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, # INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING # OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED # TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY # YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER # PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGES. # # END OF TERMS AND CONDITIONS # # How to Apply These Terms to Your New Programs # # If you develop a new program, and you want it to be of the greatest # possible use to the public, the best way to achieve this is to make it # free software which everyone can redistribute and change under these terms. # # To do so, attach the following notices to the program. It is safest # to attach them to the start of each source file to most effectively # convey the exclusion of warranty; and each file should have at least # the "copyright" line and a pointer to where the full notice is found. # # # Copyright (C) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # # Also add information on how to contact you by electronic and paper mail. # # If the program is interactive, make it output a short notice like this # when it starts in an interactive mode: # # Gnomovision version 69, Copyright (C) year name of author # Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. # This is free software, and you are welcome to redistribute it # under certain conditions; type `show c' for details. # # The hypothetical commands `show w' and `show c' should show the appropriate # parts of the General Public License. Of course, the commands you use may # be called something other than `show w' and `show c'; they could even be # mouse-clicks or menu items--whatever suits your program. # # You should also get your employer (if you work as a programmer) or your # school, if any, to sign a "copyright disclaimer" for the program, if # necessary. Here is a sample; alter the names: # # Yoyodyne, Inc., hereby disclaims all copyright interest in the program # `Gnomovision' (which makes passes at compilers) written by James Hacker. # # , 1 April 1989 # Ty Coon, President of Vice # # This General Public License does not permit incorporating your program into # proprietary programs. If your program is a subroutine library, you may # consider it more useful to permit linking proprietary applications with the # library. If this is what you want to do, use the GNU Library General # Public License instead of this License. # ----------------------------------------------------------------------------- # Kconfig.pl # ----------------------------------------------------------------------------- # DOCUMENTATION # see linux/Documentation/kbuild/kconfig-language.txt package Linux::Kconfig; my $EOT = '(\s+|$)'; my $EOS = '(\s*|$)'; sub new { my $Class = ref($_[0]) || $_[0]; return bless {}, $Class; } sub String { my $tok = shift; my $one; do { $one = $1; return $one . &String($tok); } if s/^(.*?\\$tok)//s; do { $one = $1; return $one; } if s/^(.*?)$tok$EOS//s; return '' if s/^$tok$EOS//s; die; } sub Symbol { my $y; return bless [ &String($1) ], 'Linux::Kconfig::String' if s/^([\"\'])//s; do { my $one = $1; return bless [ $one ], 'Linux::Kconfig::Symbol'; } if s/^([A-Za-z0-9_]+)\s*//s; do { my $x = &Expr; s/^\)\s*//s; return $x; } if s/^\(\s*//s; die "Symbol: $_"; } sub Expr { my $y; while($_) { s/^\#.*$//s; return $y if s/^\)\s*//s; return $y if /^if\s+/s; do { $y = bless [ &String($1) ], 'Linux::Kconfig::String'; next; } if s/^([\"\'])//s; do { my $one = $1; $y = bless [ $one ], 'Linux::Kconfig::Symbol'; next; } if s/^([A-Za-z0-9_]+)\s*//s; do { $y = bless [ &Symbol ], 'Linux::Kconfig::Not'; next; } if s/^\!([^=])\s*/$1/s; # want this to match single symbol or () in preference do { my $one = $1; my $op = $2; $y = bless [ $one, &Symbol ], 'Linux::Kconfig::' . (($op eq '=') ? 'EqualTo' : 'NotEqualTo'); next; } if s/^([A-Za-z0-9_]+)\s*(=|!=)\s*//s; do { my $op = $1; $y = bless [ $y, &Symbol ], 'Linux::Kconfig::' . (($op eq '=') ? 'EqualTo' : 'NotEqualTo'); next; } if s/^(=|!=)\s*//s; do { my $one = $1; my $op = $2; $y = bless [ $one, &Expr ], 'Linux::Kconfig::' . (($op eq '&&') ? 'And' : 'Or'); next; } if s/^([A-Za-z0-9_]+)\s*(\|\||\&\&)\s*//s; do { my $op = $1; $y = bless [ $y, &Expr ], 'Linux::Kconfig::' . (($op eq '&&') ? 'And' : 'Or'); next; } if s/^(\|\||\&\&)\s*//s; # A || B && C => [ '||', A, [ '&&', B, C ] ] # (A || B) && C => [ '&&', [ '||', A, B ], C ] do { my $x = &Expr; s/^\)\s*//s; return $x; } if s/^\(\s*//s; } return $y; die "'$_'"; } sub Optimise { local $_ = shift; for(my $i = 0; $i < @{$_}; $i++) { &Optimise( $_->[$i] ) if ref($_->[$i]) =~ /::(And|Or)$/s; if( ref($_) eq ref($_->[$i]) ) { my @Before = @{$_}[0...($i-1)] if $i > 0; my @After = @{$_}[($i+1)...(@$_-1)] if $i < @$_; @$_ = (@Before, @{$_->[$i]}, @After); } } if(ref($_) =~ /::(And|Or)$/s && (@$_ == 1) && (ref($_->[0]) !~ /::(Symbol|String)$/)) { bless $_, ref $_->[0]; @$_ = @{$_->[0]}; } return $_; } sub OptExpr { local $_ = &Expr; return $_; # return &Optimise($_); } # $_ = '(X86_NUMAQ || X86_SUMMIT) && ABC'; # $_ = 'X86_NUMAQ || (!X86_SUMMIT && ABC)'; # $_ = '(SGI_IP22 || SGI_IP27 || ((MACH_JAZZ || SNI_RM200_PCI) && !CPU_LITTLE_ENDIAN))'; # $_ = "(QETH = IPV6) || (QETH && IPV6 = 'ABC')"; # $_ = "IDE = 'y' && !BLK_DEV_IDE_SATA && (SCSI_SATA_AHCI || SCSI_ATA_PIIX)"; # $_ = '(X86 || IA64)'; # use Data::Dumper; print "$_\n"; $z = &OptExpr; print &Dumper($z); exit; sub read { my $self = shift; my $file = shift; my $fh; open($fh,"<$file") || die "Cannot open '$file' (error '$!')\n - are you sure you are running this from your Linux source directory?\n"; my $config; my $choice; my $help; my $comment; my $if_deps; while(<$fh>) { chomp; do { undef $help; next; } if /^\#/s; do { undef $help; undef $comment; my $e = $_; my $E = &OptExpr; push(@$if_deps, [$e, $E]); next; } if s/^if\s+//s; do { undef $help; undef $comment; pop(@$if_deps); next; } if /^endif/s; do { undef $help; undef $comment; $self->read( $1 ); next; } if /^source\s+\"([^\"]+)\"$/s; do { undef $help; undef $comment; $config = $1; $self->{$config}->{'.file'} = $file; do { %{$self->{$config}} = %{$self->{$choice}}; $self->{$config}->{'.choice'} = $choice; } if $choice; next; } if /^(?:menu)?config\s+([^\s]+)/s; do { undef $help; undef $comment; $choice = $config = ".$config.choice"; $self->{$config}->{'.file'} = $file; next; } if /^choice$/s; do { undef $help; undef $comment; undef $choice; next; } if /^endchoice$/s; do { undef $help; $comment = 1; next; } if /^comment$EOT/s; next if $comment; do { $self->{$config}->{'help'} .= "\n" if $self->{$config}->{'help'}; $self->{$config}->{'help'} .= "$1"; next; } if $help && (/^\s{$help,}(.*)$/s || /^$/s); undef $help; print STDERR "\n$file - $config: [$_]" if $DEBUG > 9; if( s/^(\s+)(---)?help(---)?$EOT//s ) { $help = 1; # length($1); next; } next unless s/^\s+//sg; # Other keywords are ignored # if($config eq 'PCI') { # print "OK\n"; # } if( s/^(bool(?:ean)?|tristate|string|hex|int)$EOT//s ) { $self->{$config}->{ $1 }++; $self->{$config}->{'.type'} = $1; while($_) { $self->{$config}->{'prompt'} = &String($1) if s/^([\"\'])//s; do { push( @{ $self->{$config}->{'depends on'} }, map { $_->[0] } @$if_deps ); push( @{ $self->{$config}->{'.depends on'} }, map { $_->[1] } @$if_deps ); bless $self->{$config}->{'.depends on'}, 'Linux::Kconfig::And'; } if @$if_deps; do { push( @{ $self->{$config}->{'depends on'} }, $_ ); push( @{ $self->{$config}->{'.depends on'} }, &OptExpr ); bless $self->{$config}->{'.depends on'}, 'Linux::Kconfig::And'; } if s/^if\s+(.*)$/$1/s; next if s/^\#.*$//s; } next; } if( s/^default\s+//s ) { $self->{$config}->{'default'} = &OptExpr; while($_) { do { push( @{ $self->{$config}->{'default depends on'} }, $_ ); push( @{ $self->{$config}->{'.default depends on'} }, &OptExpr ); bless $self->{$config}->{'.default depends on'}, 'Linux::Kconfig::And'; } if s/^if\s+(.*)$/$1/s; next if s/^\#.*$//s; } next; } if( s/^(depends\s+on|requires)\s+//s ) { push( @{ $self->{$config}->{'depends on'} }, $_ ); push( @{ $self->{$config}->{'.depends on'} }, &OptExpr ); bless $self->{$config}->{'.depends on'}, 'Linux::Kconfig::And'; next if s/^\#.*$//s; next; } if( s/^select\s+//s ) { push( @{ $self->{$config}->{'select'} }, $_ ); push( @{ $self->{$config}->{'.select'} }, &OptExpr ); bless $self->{$config}->{'.select'}, 'Linux::Kconfig::And'; next if s/^\#.*$//s; next; } print STDERR " - Unknown attribute" if $DEBUG > 9; } print STDERR "\n\n" if $DEBUG > 9; } sub SetDeps { my $self = shift; my $m = shift; my $val = shift; my $l = shift; die if $l == 10; # if($m eq 'SPARC32') { # print "OK\n"; # } do { printf STDERR ("%s%s='%s': doesn't exist so nothing to set\n\n", (' ' x ($l*3)), $m, $val) if $DEBUG > 9; return; } if (!$val) && (!exists($self->{$m})); do { printf STDERR ("%s='%s': Don't know how to handle '%s'\n\n", $m, $val, defined $self->{$m}) if $DEBUG > 9; return; } if $self->{$m}->{'.type'} !~ /^(bool(ean)?|tristate)$/s; $val = 'y' if ($val eq 'm') && ($self->{$m}->{'.type'} =~ /^bool(ean)?$/s); printf STDERR ("%s%s='%s'", (' ' x ($l*3)), $m, $val) if $DEBUG > 9; do { printf STDERR (" - already set to '%s'\n\n", $val); return; } if defined $self->{$m}->{'.status'} && ($self->{$m}->{'.status'} eq $val) if $DEBUG > 9; do { printf STDERR (" - conflict! - can't set to '%s' because previously set to '%s'\n\n", $val, $self->{$m}->{'.status'}); return; } if defined $self->{$m}->{'.status'} && ($self->{$m}->{'.status'} ne $val) if $DEBUG > 9; # if($m eq 'FS_MBCACHE') { # print STDERR "OK\n" if $DEBUG > 9; # } $self->{$m}->{'.status'} = $val; my $deps = $self->{$m}->{'.depends on'}; if(!$deps) { print STDERR " - no deps\n\n" if $DEBUG > 9; } else { printf STDERR (" - depends on %s\n\n", $deps->asString) if $DEBUG > 9; $deps->SetDeps( $self, $val ); } printf STDERR ("%s%s='%s'", (' ' x ($l*3)), $m, $val) if $DEBUG > 9; my $select = $self->{$m}->{'.selects'}; if(!$select) { print STDERR " - no selects\n\n" if $DEBUG > 9; } else { printf STDERR (" - selects %s\n\n", $select->asString) if $DEBUG > 9; $select->SetDeps( $self, $val ); } } sub GetDeps { my $self = shift; my $m = shift; my $mode = shift; my $lookup = { '' => 0, 'n' => 0, 'm' => 1, 'y' => 2 }; return $lookup->{ $self->{$m}->{'.status'} } if (exists $self->{$m}) && ($self->{$m}->{'.status'} || ($mode == 0)); return $lookup->{ $self->{$m}->{'.config.status'} }; } sub asString { my $self = shift; } package Linux::Kconfig::Op; sub asString { my $self = shift; return $self->[0]; } sub SetDeps { my $self = shift; my $SELF = shift; my $val = shift; printf STDERR ("%s: don't know how to handle %s\n\n", $self, $self->asString); } package Linux::Kconfig::Symbol; use base 'Linux::Kconfig::Op'; sub SetDeps { my $self = shift; my $SELF = shift; my $val = shift; $SELF->SetDeps( $self->[0], $val ); } sub GetDeps { my $self = shift; my $SELF = shift; my $mode = shift; return $SELF->GetDeps( $self->[0], $mode ); } package Linux::Kconfig::String; use base 'Linux::Kconfig::Op'; sub Value { my $self = shift; return $self->[0]; } package Linux::Kconfig::And; use base 'Linux::Kconfig::Op'; sub asString { my $self = shift; return sprintf("AND( %s )", join(', ', map { $_->asString } @$self)); } sub GetDeps { my $self = shift; my $SELF = shift; my $mode = shift; my $V; foreach my $d (@$self) { my $v = $d->GetDeps( $SELF, $mode ); $V = $v if (defined $v) && ($v < $V); } return $V; } sub SetDeps { my $deps = shift; my $SELF = shift; my $val = shift; foreach my $d (@$deps) { $d->SetDeps( $SELF, $val ); } } package Linux::Kconfig::Or; use base 'Linux::Kconfig::Op'; sub asString { my $self = shift; return sprintf("OR( %s )", join(', ', map { $_->asString } @$self)); } sub GetDeps { my $self = shift; my $SELF = shift; my $mode = shift; my $V; foreach my $d (@$self) { my $v = $d->GetDeps( $SELF, $mode ); printf STDERR ("Testing %s: v=%s\n", $d->asString, $v) if $DEBUG > 9; $V = $v if (defined $v) && ($v > $V); } return $V; } sub SetDeps { my $self = shift; my $SELF = shift; my $val = shift; my $V = $self->GetDeps( $SELF ); printf STDERR ("%s == '%s'", $self->asString, $V) if $DEBUG > 9; do { print STDERR " - nothing to do\n\n"; return; } if defined $V if $DEBUG > 9; print STDERR "\n\n" if $DEBUG > 9; foreach (@$self) { my $v = $_->GetDeps( $SELF, 1); do { $_->SetDeps( $SELF, 'y' ); return; } if ($v == 2); do { $_->SetDeps( $SELF, $val ); return; } if ($val eq 'm') && ($v == 1); } } package Linux::Kconfig::Not; use base 'Linux::Kconfig::Op'; sub asString { my $self = shift; return sprintf("NOT( %s )", join(', ', map { $_->asString } @$self)); } sub SetDeps { my $self = shift; my $SELF = shift; my $val = shift; $self->[0]->SetDeps( $SELF, !$val ); } sub GetDeps { my $self = shift; my $SELF = shift; my $mode = shift; return 2 - $self->[0]->GetDeps( $SELF, $mode ); } package Linux::Kconfig::EqualTo; use base 'Linux::Kconfig::Op'; sub asString { my $self = shift; return sprintf("EQUAL-TO( %s, %s )", $self->[0]->asString, $self->[1]->asString); }; sub SetDeps { my $self = shift; my $SELF = shift; my $val = shift; $self->[0]->SetDeps( $SELF, $self->[1]->asString ); } sub GetDeps { my $self = shift; my $SELF = shift; my $mode = shift; return $self->[0]->GetDeps( $SELF, $mode ) == $self->[1]->GetDeps( $SELF, $mode ); } package Linux::Kconfig::NotEqualTo; use base 'Linux::Kconfig::Op'; sub asString { my $self = shift; return sprintf("NOT-EQUAL-TO( %s, %s )", $self->[0]->asString, $self->[1]->asString); }; sub SetDeps { my $self = shift; my $SELF = shift; my $val = shift; do { print STDERR " - nothing to do\n\n"; return; } if $self->[0]->GetDeps( $SELF ) ne $self->[1]->asString if $DEBUG > 9; $self->[0]->SetDeps( $SELF, ($self->[1]->asString eq 'n') ? 'm' : 'n'); } sub GetDeps { my $self = shift; my $SELF = shift; my $mode = shift; return $self->[0]->GetDeps( $SELF, $mode ) != $self->[1]->GetDeps( $SELF, $mode ); } package main; use Getopt::Std; my %opts; sub HELP_MESSAGE { print STDERR "Usage: $0 > \n" if $DEBUG > 9; exit; } sub VERSION_MESSAGE { print STDERR "$0: version " . &VERSION() . "\n" if $DEBUG > 9; } sub VERSION { return '0.4'; } $Getopt::Std::STANDARD_HELP_VERSION = 1; # -M MODULE1,MODULE2,MODULE3 # -M mod1,mod2,mod3 # -a # -v # -d - dumper getopts( 'M:m:a:v:d', \%opts); $DEBUG->{'ModuleFileKeyLookup'} = 1 if $opts->{'v'} == 1; $DEBUG->{'ModuleKeyFileLookup'} = 1 if $opts->{'v'} == 2; $DEBUG->{'SetModuleDependencies'} = 1 if $opts->{'v'} == 3; $DEBUG->{'OutputConfig'} = 1 if $opts->{'v'} == 4; $|=1; # Initialise Kconfig object, read in and parse Kconfig files my $Kconfig = Linux::Kconfig->new(); $Kconfig->read( $opts->{'a'} ? "arch/$$opts{'a'}/Kconfig" : 'arch/i386/Kconfig' ); if( $opts->{'d'} ) { use Data::Dumper; print STDERR &Dumper($Kconfig),"\n" if $DEBUG > 9; } # Attempt to parse module filenames from Kconfig help my $MOD_NAME_LOOKUP; foreach my $key (keys %$Kconfig) { # 'SCSI_SATA_INTEL_COMBINED', 'FB_ARMCLCD') { Linux::Kconfig::Optimise( $Kconfig->{$key}->{'.depends on'} ); print STDERR "{$key} " if $DEBUG->{'ModuleKeyFileLookup'} if $DEBUG > 9; if( $Kconfig->{$key}->{'help'} =~ /module\s+.*?called\s+([^\s\.]+)/s ) { $MOD_NAME_LOOKUP->{$1} = $key; print STDERR "{$1}" if $DEBUG->{'ModuleKeyFileLookup'} if $DEBUG > 9; } print STDERR "\n" if $DEBUG->{'ModuleKeyFileLookup'} if $DEBUG > 9; } # Read in .config file and set status of each key in the Kconfig object my $Config; open(CONFIG,"<$ARGV[0]") || die "Cannot open file '$ARGV[0]: $!"; while() { chomp; push( @$Config, $_ ); if( /^CONFIG_([^=]+)=(.*)\s*$/ ) { $Kconfig->{$1}->{'.config.status'} = $2; } } close CONFIG; my $MODPATH = '/lib/modules/' . `uname -r`; chomp $MODPATH; my @MY_MODULES_CONFIG; my @MODULES; if( $opts->{'m'} ) { @MODULES = split(/[\s\,]+/, $opts->{'m'}); } else { @MODULES = split(/\n+/, `cat /proc/modules`); } foreach my $m (sort @MODULES) { $m =~ s/\s+.*$//s; print STDERR "$m => " if $DEBUG->{'ModuleFileKeyLookup'} if $DEBUG > 9; print STDERR "[$MOD_NAME_LOOKUP->{$m}] " if $DEBUG->{'ModuleFileKeyLookup'} if $DEBUG > 9; # Allow any character in place of an underscore in the module name my $fn = $m; $fn =~ s/_/\?/sg; print STDERR "$fn => " if $DEBUG->{'ModuleFileKeyLookup'} if $DEBUG > 9; # Search for .ko module files with that filename my $fnp = `find $MODPATH -type f -name "$fn.ko"`; chomp $fnp; do { print STDERR "[module object file path not found]\n" if $DEBUG->{'ModuleFileKeyLookup'}; next; } unless $fnp if $DEBUG > 9; $fnp =~ s/^\Q$MODPATH\/kernel\/\E//s; print STDERR "$fnp => " if $DEBUG->{'ModuleFileKeyLookup'} if $DEBUG > 9; my $mp = $fnp; $mp =~ s/\/[^\/]+$/\//s; print STDERR "$mp => " if $DEBUG->{'ModuleFileKeyLookup'} if $DEBUG > 9; my $mfn = $fnp; $mfn =~ s/^.*\/([^\/]+)\..*$/$1/; print STDERR "$mfn => " if $DEBUG->{'ModuleFileKeyLookup'} if $DEBUG > 9; my $cfg = `grep "CONFIG.*+=.* $mfn\\.o" $mp/Makefile`; chomp $cfg; do { print STDERR "[no single option found]\n" if $DEBUG->{'ModuleFileKeyLookup'}; next;} if (!$cfg) || ($cfg =~ /\n/s); $cfg =~ s/^.*(CONFIG[^\W]+).*$/$1/ if $DEBUG > 9; print STDERR "$cfg\n" if $DEBUG->{'ModuleFileKeyLookup'} if $DEBUG > 9; $cfg =~ s/^CONFIG_//s; push(@MY_MODULES_CONFIG, $cfg); } # Set status of dependencies in the Kconfig object for given modules foreach my $m (@MY_MODULES_CONFIG) { print STDERR "[$m]\n" if $DEBUG->{'SetModuleDependencies'} if $DEBUG > 9; $Kconfig->SetDeps( $m, 'm' ); } foreach (@$Config) { if( /^(?:#\s*)?CONFIG_([^=\s]+)/ ) { my $m = $1; # if($m eq 'MODULES') { # print STDERR "OK\n" if $DEBUG > 9; # } my $deps = $Kconfig->{$m}->{'.depends on'}; if( ($Kconfig->{$m}->{'.status'} =~ /^[ym]$/s) || ($Kconfig->{$m}->{'.config.status'} !~ /^m?$/s) ) { printf( "CONFIG_%s=%s", $m, $Kconfig->{$m}->{'.status'} || $Kconfig->{$m}->{'.config.status'} ); } else { printf( "# CONFIG_%s is not set", $m ); } printf( " # ='%s'; type '%s'; depends on '%s'", $Kconfig->{$m}->{'.type'}, $deps ? $deps->asString : 'none' ) if $DEBUG{'OutputConfig'}; print "\n"; } else { print "$_\n"; } }