Sometimes you don’t have access to vim’s wonderful xxd
tool, and you need to use it to generate some .c code based on
a binary file.
This happened to me recently when packaging up the EFI signing tools for Gentoo.
Adding a build requirement of vim for a single autogenerated file was
not an option for some users, so I created a perl version of the
xxd -i command line tool.
This works because everyone has perl in their build systems, whether
they like it or not. Instead of burying it in the efitools
package, here’s a copy of it for others to use if they want/need it.
#!/usr/bin/env perl## xxdi.pl - perl implementation of 'xxd -i' mode## Copyright 2013 Greg Kroah-Hartman <gregkh@linuxfoundation.org># Copyright 2013 Linux Foundation## Released under the GPLv2.## Implements the "basic" functionality of 'xxd -i' in perl to keep build# systems from having to build/install/rely on vim-core, which not all# distros want to do. But everyone has perl, so use it instead.usestrict;usewarnings;useFile::Slurpqw(slurp);my$indata=slurp(@ARGV?$ARGV[0]:\*STDIN);my$len_data=length($indata);my$num_digits_per_line=12;my$var_name;my$outdata;# Use the variable name of the file we read from, converting '/' and '.# to '_', or, if this is stdin, just use "stdin" as the name.if(@ARGV){$var_name=$ARGV[0];$var_name=~s/\//_/g;$var_name=~s/\./_/g;}else{$var_name="stdin";}$outdata.="unsigned char $var_name\[] = {";# trailing ',' is acceptable, so instead of duplicating the logic for# just the last character, live with the extra ','.for(my$key=0;$key<$len_data;$key++){if($key%$num_digits_per_line==0){$outdata.="\n\t";}$outdata.=sprintf("0x%.2x, ",ord(substr($indata,$key,1)));}$outdata.="\n};\nunsigned int $var_name\_len = $len_data;\n";binmodeSTDOUT;print{*STDOUT}$outdata;
Yes, I know I write perl code like a C programmer, that’s not an insult
to me.