#!/usr/bin/perl # # jcpp Copyright (C) 1999 Jochen Hoenicke. # # 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, 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; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # # $Id$ # This is a program to allow conditional compiled code in java files. # The key idea is, not to run the file always through the # preprocessor, but to modify the java files directly and make use of # comments. # # The comments all have the form /// to distinguish them from normal # comments. You should not use such comments yourself. # # Usage is simple: jcpp -Ddefine1 -Ddefine2 first.java second.java # The files should contain comments of the form # # ///#ifdef JDK12 # jdk1.2 code # ///#else # jdk1.1 code # ///#endif # # After running jcpp the false branch is commented out. If the true # branch was commented out it will get commented in. my @files; my %defs; for (@ARGV) { if ($_ =~ /^-D([^=]*)$/) { $defs{$1} = 1; } elsif ($_ =~ /^-D([^=]*)=([^=]*)$/) { $defs{$1} = $2; } else { push @files, $_; } } for (@files) { # Number of nested #if directives. Initially 0, will be increased # on every #if directive and decreased on every #endif directive. my $level = 0; # The number of the outermost level, whose #if directive was # false. This is 0, if there wasn't an false #if directive, yet. # As long as it is != 0, we comment every line, and ignore # directives except for increasing/decreasing $level. my $falselevel = 0; # Tells if an error occured and the transformation shouldn't # be done. my $error = 0; my $changes = 0; my $file = $_; open OLD, "<$file" or do { print STDERR "Can't open file $file\n"; next; }; open NEW, ">$file.tmp" or do { print STDERR "Can't open tmp file $file.tmp\n"; next; }; my $linenr = 0; LINE: while () { $linenr++; if (m'^///#') { # This is a directive. First we print it out. print NEW $_; if (m'^///# *if') { $level++; if (m'^///# *ifdef (\S*)$') { # If there was an outer false #if directive, we ignore the # condition. next LINE if ($falselevel); my $label=$1; # An ifdef directive, look if -D is defined. $falselevel = $level unless (defined $defs{$label}); } elsif (m'^///# *ifndef (\S*)$') { # If there was an outer false #if directive, we ignore the # condition. next LINE if ($falselevel); my $label=$1; # An ifndef directive, look if -D is defined $falselevel = $level if (defined $defs{$label}); } } elsif (m'^///# *else') { # An else directive. We switch from true to false and # if level is falselevel we switch from false to true if ($level == 0) { # An else outside of any directives; warn. print STDERR "$file: $linenr: unmatched $_"; $error = 1; } elsif ($falselevel == $level) { $falselevel = 0; } elsif ($falselevel == 0) { $falselevel = $level; } } elsif (m'^///# *endif') { # set $falselevel to 0, if the false branch is over now. $falselevel = 0 if ($falselevel == $level); # decrease level. if ($level == 0) { print STDERR "$file: $linenr: unmatched $_"; $error = 1; } else { $level--; } } else { print STDERR "$file: $linenr: ignoring unknown directive $_"; $error = 1; } } elsif (m'^///(.*)') { $line = $1; if ($falselevel == 0 && $level > 0) { # remove comments in true branch, but not in outermost level. print NEW "$line\n"; $changes = 1; } else { # print out the full line with comments: print NEW $_; } } else { if ($falselevel != 0) { # add comments in false branch print NEW "///$_"; $changes = 1; } else { print NEW $_; } } } if ($level != 0 || $falselevel != 0) { # something got wrong print STDERR "$file: unmatched directives: level $level, ". "falselevel $falselevel\n"; $error = 1; } if ($error == 0) { if ($changes == 0) { unlink "$file.tmp"; } else { (rename "$file", "$file.orig" and rename "$file.tmp", "$file") or print STDERR "$file: Couldn't rename files.\n"; } } else { print STDERR "$file: errors occured, file not transformed.\n"; } }