#!/usr/bin/perl use strict; use warnings; use IPC::Open2; use IPC::Cmd qw[can_run]; can_run('gperf') or die 'No gperf binary found, make sure to have gperf installed!'; print("/******** GENERATED FILE ********/\n"); my $rewritten_input = ''; my $iter = 0; my $keys = ''; my %key_vals; # collect keywords and rewrite input file with in lookup keys while (my $line = ) { if (!($line =~ s/CSH_LOOKUP\("(.*?)"\)/{}/)) { $rewritten_input .= $line; next; } my $key = $1; if (exists($key_vals{$key})) { $line =~ s/{}/$key_vals{$key}/; } else { $line =~ s/{}/$iter/; $keys .= "$key,$iter\n"; $key_vals{$key} = $iter; $iter++; } $rewritten_input .= $line; } # pass collected output to gperf my ($rd, $wr); my $pid = open2($rd, $wr, qw(gperf -t -E -l -c -t -I -H __csh_hash -N __csh_lookup_raw)); # gperf header and keys print { $wr } "struct __csh_hash_lookup { char *name; int num; };\n%%\n"; print { $wr } $keys; # read gperf output close($wr); my $hash_func_code; { local $/ = undef; $hash_func_code = <$rd>; } close($rd); waitpid($pid, 0); exit(1) if $?; # convert lookup function to static $hash_func_code =~ s/(^|\s)struct\s+__csh_hash_lookup\s*\*/\nstatic$&/s; # print combined output print "#pragma GCC diagnostic push\n"; print "#pragma GCC diagnostic ignored \"-Wmissing-field-initializers\"\n"; print $hash_func_code; print "#pragma GCC diagnostic pop\n"; # add convenience function print <s) return -1; struct __csh_hash_lookup *h = __csh_lookup_raw(s->s, s->len); if (!h) return -1; return h->num; } END # adjust diagnostic line numbers and originating file print $ARGV[0] ? "#line 1 \"$ARGV[0]\"\n" : "#line 1\n"; print $rewritten_input;