mirror of
https://github.com/freedoom/freedoom.git
synced 2025-09-01 22:25:46 -04:00
Convert simplecpp script to Python.
This commit is contained in:
parent
0b332510ac
commit
ece77ca176
1 changed files with 138 additions and 96 deletions
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env perl
|
#!/usr/bin/env python
|
||||||
#
|
#
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||||
# Contributors to the Freedoom project. All rights reserved.
|
# Contributors to the Freedoom project. All rights reserved.
|
||||||
|
@ -56,119 +56,161 @@
|
||||||
#
|
#
|
||||||
# include the contents of a file
|
# include the contents of a file
|
||||||
|
|
||||||
use strict;
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
my @readstack;
|
debug = False
|
||||||
my %defines;
|
defines = {}
|
||||||
|
|
||||||
sub parse_cmdline {
|
command_re = re.compile("\#(\w+)(\s+(.*))?")
|
||||||
foreach (@ARGV) {
|
include_re = re.compile("\s*\"(.*)\"\s*")
|
||||||
if (/^-D/) {
|
|
||||||
my ($define) = /^-D(.*)$/;
|
def debug_msg(message):
|
||||||
$defines{$define} = 1;
|
if debug:
|
||||||
}
|
sys.stderr.write(message)
|
||||||
}
|
|
||||||
|
# Parse command line options
|
||||||
|
|
||||||
|
def parse_cmdline():
|
||||||
|
for arg in sys.argv[1:]:
|
||||||
|
if arg.startswith("-D"):
|
||||||
|
name = arg[2:]
|
||||||
|
defines[name] = True
|
||||||
|
|
||||||
|
def parse_stream(stream):
|
||||||
|
result = read_block(stream, False)
|
||||||
|
|
||||||
|
if result is not None:
|
||||||
|
raise Exception("Mismatched #if in '%s'" % stream.name)
|
||||||
|
|
||||||
|
def parse_file(filename):
|
||||||
|
f = file(filename)
|
||||||
|
|
||||||
|
try:
|
||||||
|
parse_stream(f)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# #include
|
||||||
|
|
||||||
|
def cmd_include(arg):
|
||||||
|
# Extract the filename
|
||||||
|
|
||||||
|
match = include_re.match(arg)
|
||||||
|
|
||||||
|
if not match:
|
||||||
|
raise Exception("Invalid 'include' command")
|
||||||
|
|
||||||
|
filename = match.group(1)
|
||||||
|
|
||||||
|
# Open the file and process it
|
||||||
|
|
||||||
|
parse_file(filename)
|
||||||
|
|
||||||
|
# #define
|
||||||
|
|
||||||
|
def cmd_define(arg):
|
||||||
|
defines[arg] = True
|
||||||
|
|
||||||
|
# #undef
|
||||||
|
|
||||||
|
def cmd_undef(arg):
|
||||||
|
if arg in defines:
|
||||||
|
del defines[arg]
|
||||||
|
|
||||||
|
# #ifdef/#ifndef
|
||||||
|
|
||||||
|
def cmd_ifdef(arg, command, stream, ignore):
|
||||||
|
|
||||||
|
# Get the define name
|
||||||
|
name = arg.strip()
|
||||||
|
|
||||||
|
debug_msg("%s %s >\n" % (command, arg))
|
||||||
|
|
||||||
|
# Should we ignore the contents of this block?
|
||||||
|
|
||||||
|
sub_ignore = (name not in defines)
|
||||||
|
|
||||||
|
if "n" in command:
|
||||||
|
sub_ignore = not sub_ignore
|
||||||
|
|
||||||
|
# Parse the block
|
||||||
|
|
||||||
|
result = read_block(stream, ignore or sub_ignore)
|
||||||
|
|
||||||
|
debug_msg("%s %s < (%s)\n" % (command, arg, result))
|
||||||
|
|
||||||
|
# There may be a second "else" block to parse:
|
||||||
|
|
||||||
|
if result == "else":
|
||||||
|
debug_msg("%s %s else >\n" % (command, arg))
|
||||||
|
result = read_block(stream, ignore or (not sub_ignore))
|
||||||
|
debug_msg("%s %s else < (%s)\n" % (command, arg, result))
|
||||||
|
|
||||||
|
# Should end in an endif:
|
||||||
|
|
||||||
|
if result != "endif":
|
||||||
|
raise Exception("'if' block did not end in an 'endif'")
|
||||||
|
|
||||||
|
commands = {
|
||||||
|
"include" : cmd_include,
|
||||||
|
"define" : cmd_define,
|
||||||
|
"undef" : cmd_undef,
|
||||||
|
"if" : cmd_ifdef,
|
||||||
|
"ifdef" : cmd_ifdef,
|
||||||
|
"ifn" : cmd_ifdef,
|
||||||
|
"ifndef" : cmd_ifdef,
|
||||||
}
|
}
|
||||||
|
|
||||||
# add contents of stdin to read stack
|
# Recursive block reading function
|
||||||
|
|
||||||
sub read_stdin {
|
|
||||||
my @lines = <STDIN>;
|
|
||||||
chomp @lines;
|
|
||||||
|
|
||||||
@readstack = (@readstack, reverse(@lines));
|
|
||||||
}
|
|
||||||
|
|
||||||
# add contents of a file to stack
|
|
||||||
|
|
||||||
sub read_file {
|
|
||||||
my ($filename) = @_;
|
|
||||||
|
|
||||||
open(FILE, $filename) or die "cant open $filename: $!";
|
|
||||||
my @lines = <FILE>;
|
|
||||||
close(FILE);
|
|
||||||
|
|
||||||
chomp @lines;
|
|
||||||
@readstack = (@readstack, reverse(@lines));
|
|
||||||
}
|
|
||||||
|
|
||||||
# recursive block reading function
|
|
||||||
# if 'ignore' argument is 1, contents are ignored
|
# if 'ignore' argument is 1, contents are ignored
|
||||||
|
|
||||||
sub readblock {
|
def read_block(stream, ignore):
|
||||||
my ($ignore) = @_;
|
|
||||||
|
|
||||||
while (scalar @readstack > 0) {
|
for line in stream:
|
||||||
$_ = pop @readstack;
|
|
||||||
|
|
||||||
next if (/^\s*$/);
|
# Remove newline
|
||||||
|
|
||||||
if (/^\#include\s+\".*\"\s*$/ ) {
|
line = line[0:-1]
|
||||||
if (!$ignore) {
|
|
||||||
my ($filename) = /^\#include\s+\"(.*)\"\s*/;
|
|
||||||
read_file $filename;
|
|
||||||
}
|
|
||||||
} elsif (/^\#define\s/ ) {
|
|
||||||
if (!$ignore) {
|
|
||||||
my ($name) = /^\#define\s*(\w+)/;
|
|
||||||
$defines{$name} = 1;
|
|
||||||
}
|
|
||||||
} elsif (/^\#undef\s/ ) {
|
|
||||||
if (!$ignore) {
|
|
||||||
my ($name) = /^\#undef\s*(\w+)/;
|
|
||||||
$defines{$name} = undef;
|
|
||||||
}
|
|
||||||
} elsif (/^\#(if|ifdef|ifn|ifndef)\s/) {
|
|
||||||
my ($type, $defines) = /^\#(\w+)\s+(.*)/;
|
|
||||||
$defines =~ s/\s*$//;
|
|
||||||
|
|
||||||
my @definelist = split(/\s*\|\|\s*/, $defines);
|
# Ignore empty lines
|
||||||
|
|
||||||
my $ev;
|
if line == " " * len(line):
|
||||||
|
continue
|
||||||
|
|
||||||
if ($type =~ /^(if|ifdef)$/) {
|
# Check if this line has a command
|
||||||
$ev = 0;
|
|
||||||
|
|
||||||
foreach (@definelist) {
|
match = command_re.match(line)
|
||||||
$ev = 1 if $defines{$_};
|
|
||||||
}
|
|
||||||
} elsif ($type =~ /^(ifn|ifndef)$/) {
|
|
||||||
$ev = 1;
|
|
||||||
|
|
||||||
foreach (@definelist) {
|
if match:
|
||||||
$ev = 0 if $defines{$_};
|
command = match.group(1)
|
||||||
}
|
arg = match.group(3)
|
||||||
} else { die "what type?"; }
|
|
||||||
|
|
||||||
my $result = readblock($ignore || !$ev);
|
if command == "else" or command == "endif":
|
||||||
|
return command
|
||||||
|
elif command not in commands:
|
||||||
|
raise Exception("Unknown command: '%s'" % \
|
||||||
|
command)
|
||||||
|
|
||||||
die if $result == -1;
|
# Get the callback function.
|
||||||
|
|
||||||
if ($result == 1) {
|
func = commands[command]
|
||||||
# block ended on an else
|
|
||||||
# call again for the second block
|
|
||||||
|
|
||||||
my $result = readblock($ignore || $ev);
|
# Invoke the callback function. #ifdef commands
|
||||||
|
# are a special case and need extra arguments.
|
||||||
|
# Other commands are only executed if we are not
|
||||||
|
# ignoring this block.
|
||||||
|
|
||||||
die if $result != 0;
|
if func == cmd_ifdef:
|
||||||
}
|
cmd_ifdef(arg, command=command,
|
||||||
|
stream=stream,
|
||||||
|
ignore=ignore)
|
||||||
|
elif not ignore:
|
||||||
|
func(arg)
|
||||||
|
else:
|
||||||
|
if not ignore:
|
||||||
|
print line
|
||||||
|
|
||||||
} elsif (/^\#endif/) {
|
parse_cmdline()
|
||||||
return 0;
|
parse_stream(sys.stdin)
|
||||||
} elsif (/^\#else/) {
|
|
||||||
return 1;
|
|
||||||
} elsif (/^\#(.*)/) {
|
|
||||||
die "invalid # command: '$1'";
|
|
||||||
} else {
|
|
||||||
print "$_\n" if !$ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_cmdline;
|
|
||||||
read_stdin;
|
|
||||||
die if (readblock(0) != -1);
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue