#!/usr/bin/env perl # C Macro expander # Vincent Pit - http://www.profvince.com use strict; use warnings; use File::Temp; use Getopt::Std; our $VERSION = '0.03'; my %opts; getopts('ino:', \%opts); my $cc = $ENV{CC} || 'gcc'; my $key = 'HLAGH'; for my $infile (@ARGV) { open my $in, '<', $infile or die "open($infile): $!"; my $tmp = new File::Temp UNLINK => 0, SUFFIX => '.h'; my ($m, @macros, $cont); while (<$in>) { if (/^#\s*(include|define|undef)/ || $cont) { $m .= $_; $cont = /\\$/; } print $tmp $_ if not $1 or $1 ne 'include'; if (!$cont && $m) { push @macros, $m; print $tmp "$key($#macros)\n"; undef $m; } } close $in; close $tmp; pipe my $rdr, my $wtr or die "pipe(rdr, wtr): $!"; my $pid = fork; if (!defined $pid) { die "fork(): $!"; } elsif ($pid == 0) { close $rdr or die "close(rdr): $!"; open \*STDOUT, '>&', $wtr or die "open(STDOUT>&wtr): $!"; exec "$cc -E $tmp"; } close $wtr or die "close(wtr): $!"; my ($out, $outfile); if ($opts{i}) { $outfile = $infile; open $out, '>', $infile or die "open($infile): $!"; } elsif ($opts{o}) { $outfile = $opts{o}; open $out, '>', $opts{o} or die "open($opts{o}): $!"; } else { $out = \*STDOUT; } while (<$rdr>) { next if /^#/; s/([;{}])(?!\n)/$1\n/g; s!^$key\((\d+)\)$!$macros[$1]!; print $out $_; } waitpid $pid, 0; 1 while unlink $tmp->filename; close $out; if ($opts{n} && $outfile) { system "indent -nut $outfile"; } }