C::Utility - utilities for generating C programs
This documents C::Utility version 0.009 corresponding to git commit 3ddad303724b7d7b1e8a30afe53edd09bed484f7 released on Tue Mar 27 15:32:59 2018 +0900.
This module contains functions which assist in automatic generation of C programs. "convert_to_c_string" converts a string into a string with characters correctly escaped for use in a C program. "convert_to_c_string_pc" does the same thing plus escaping percent signs so that they may be used as format strings for printf. "ch_files" makes a header file name from a C file name. "escape_string" escapes double quotes. "valid_c_variable" checks whether a string is valid as a C variable. "wrapper_name" returns a C preprocessor wrapper name. "print_top_h_wrapper" prints the top wrapper for a header file, and "print_bottom_h_wrapper" prints the bottom part. "print_include" prints #include statements. "hash_to_c_file" converts a Perl hash into a compilable C file with the keys as C strings. "line_directive" prints a C line directive. "brute_force_line" puts line directives on every line. "add_lines" converts the string #line to line directives as do "linein" and "lineout". "remove_quotes" removes leading and trailing quotes. "stamp_file" adds a printed stamp to a file handle.
#include
my $c_string = convert_to_c_string ($perl_string);
This converts a Perl string into a C string. For example,
use C::Utility 'convert_to_c_string'; my $string =<<'EOF'; The quick "brown" fox\@farm jumped %over the lazy dog. EOF print convert_to_c_string ($string);
produces output
"The quick \"brown\" fox\@farm\n" "jumped %over the lazy dog.\n"
(This example is included as fox.pl in the distribution.)
It also removes backslashes from before the @ symbol, so \@ is transformed to @.
my $c_string = convert_to_c_string_pc ($string);
As "convert_to_c_string", but also with % (the percent character) converted to a double percent, %%. This is for generating strings which may be used as C format strings without generating an error because of embedded percent characters.
use C::Utility 'convert_to_c_string_pc'; my $string =<<'EOF'; The quick "brown" fox\@farm jumped %over the lazy dog. EOF print convert_to_c_string_pc ($string);
"The quick \"brown\" fox\@farm\n" "jumped %%over the lazy dog.\n"
(This example is included as fox-pc.pl in the distribution.)
Alias for "convert_to_c_string".
my $hfile = ch_files ($c_file_name);
This makes a .h filename from a .c filename, and backs up both C and .h files using File::Versions. See also "c_to_h_name".
my $escaped_string = escape_string ($normal_string);
Escape double quotes (") in a string with a backslash.
my $h_file = c_to_h_name ("frog.c"); # $h_file = "frog.h".
Make a .h file name from a .c file name.
valid_c_variable ($variable_name);
This returns 1 if $variable_name is a valid C variable, the undefined value otherwise. It tests for two things, first that the argument only contains the allowed characters for a C variable, and second that the argument is not a C keyword like "goto" or "volatile".
$variable_name
my $wrapper = wrapper_name ($file_name);
Given a file name, this returns a suitable C preprocessor wrapper name based on the file name. The preprocessor wrapper name is just the uppercase version of the file name with hyphens and dots replaced with underscores. This does not strip out directory paths from $file_name, since it would usually be an error to include a particular directory path in a header file's wrapper.
$file_name
print_top_h_wrapper ($file_handle, $file_name); # Prints #ifndef wrapper at top of file.
Print an "include wrapper" for a .h file to $file_handle. For example,
$file_handle
#ifndef MY_FILE #define MY_FILE
The name of the wrapper comes from "wrapper_name" applied to $file_name. If $file_handle is a scalar reference, this concatenates the wrapper to the scalar.
See also "print_bottom_h_wrapper".
print_bottom_h_wrapper ($file_handle, $file_name);
Print the bottom part of an include wrapper for a .h file to $file_handle.
The name of the wrapper comes from "wrapper_name" applied to $file_name.
If $file_handle is a scalar reference, this concatenates the wrapper to the scalar.
See also "print_top_h_wrapper".
print_include ($file_handle, $file_name);
Print an #include statement for a .h file named $file_name to $file_handle:
#include "file.h"
my $h_file = hash_to_c_file ($c_file_name, \%hash);
Output a Perl hash as a set of const char * strings. For example,
use FindBin '$Bin'; use C::Utility 'hash_to_c_file'; use File::Slurper 'read_text'; my $file = "$Bin/my.c"; my $hfile = hash_to_c_file ($file, { version => '0.01', author => 'Michael Caine' }); print "C file:\n\n"; print read_text ($file); print "\nHeader file:\n\n"; print read_text ($hfile); unlink $file, $hfile or die $!;
C file: #include "my.h" const char * author = "Michael Caine"; const char * version = "0.01"; Header file: #ifndef MY_H #define MY_H extern const char * author; /* "Michael Caine" */ extern const char * version; /* "0.01" */ #endif /* MY_H */
(This example is included as michael-caine.pl in the distribution.)
The keys of the hash are checked with "valid_c_variable", and the routine dies if they are not valid C variable names.
A third argument, $prefix, contains an optional prefix to add to all the variable names:
$prefix
hash_to_c_file ('that.c', {ok => 'yes'}, 'super_');
prints
const char * super_ok = "yes";
The behaviour of returning the name of the header file was added in version 0.006.
line_directive ($fh, 42, "file.x")
#line 42 "file.x"
to $fh. This prints a C preprocessor line directive to the file specified by $fh. If $fh is a scalar reference, it concatenates the line directive to the end of it.
$fh
use C::Utility 'line_directive'; my $out = ''; line_directive (\$out, 99, "balloons.c"); print $out;
#line 99 "balloons.c"
(This example is included as line-directive.pl in the distribution.)
brute_force_line ($input_file, $output_file);
Read $input_file, put #line directives on every single line, and write that to $output_file. This is a fix used to force line numbers into a file before it is processed by Template.
$input_file
$output_file
my $text = add_lines ($file);
Read $file, and replace strings of the form #line in the file with a C-style line directive using $file before it is processed by Template. Also add a line directive to the first line of the file. $file must be in the UTF-8 encoding. The line directives are given the full path name of the file using "rel2abs" in File::Spec.
$file
my $unquoted_string = remove_quotes ($string);
This removes the leading and trailing quotes from $string. It also removes the "joining quotes" in composite C strings. Thus input of the form "composite " "C" " string" is converted into composite C string without the quotes.
$string
my $intext = linein ($infile);
Given a file $infile, this opens the file, reads it in, replaces the text #linein in the file with a C line directive referring to the original file, then returns the complete text as its return value.
#linein
lineout ($outtext, $outfile);
Given a C output text $outtext and a file name $outfile, this writes out the text to $outfile, replacing the text #lineout with an appropriate line directive using $outfile as the file name and the lines of the file as the line numbers.
$outtext
#lineout
$outfile
use FindBin '$Bin'; use C::Utility 'lineout'; use File::Slurper 'read_text'; my $file = "$Bin/some.c"; my $c = <<EOF; static void unknown (int x) { return x; } #lineout int main () { return 0; } EOF lineout ($c, $file); print read_text ($file); unlink $file or die $!;
static void unknown (int x) { return x; } #line 2 "/usr/home/ben/projects/c-utility/examples/some.c" int main () { return 0; }
(This example is included as lineout.pl in the distribution.)
stamp_file ($fh);
Add a stamp to file handle $fh containing the name of the program which created it, and the time of generation.
The name of the C file output can be added as a second argument:
stamp_file ($fh, $name);
If $fh is a scalar reference, the stamp is concatenated to it.
use C::Utility 'stamp_file'; my $out = ''; stamp_file (\$out); print $out;
/* This C file was generated by /usr/home/ben/projects/c-utility/examples/stamp-file.pl at Fri Oct 13 18:20:44 2017. */
(This example is included as stamp-file.pl in the distribution.)
This function was added in version 0.006.
my $includes = read_includes ($file);
Read lines of the form
#include "some.h"
from $file and return the list of included files as an array reference.
This function was added in version 0.008.
Carp is used to report errors.
File::Spec is used to get the base name of the file from the argument to "hash_to_c_file", and to get the absolute name of the file in "add_lines".
File::Versions is used to back up files
C::Tokenize is used by "read_includes".
File::Slurper is used by "read_includes".
Most of the functions in this module are for supporting automated C code generators.
C::Utility was on CPAN, but then deleted between version 0.005 and version 0.006. I don't know of anyone who was using the module, but I decided to restore it to CPAN anyway, since I'm still using and maintaining it, and it might be useful to somebody.
Ben Bullock, <bkb@cpan.org>
This package and associated files are copyright (C) 2012-2018 Ben Bullock.
You can use, copy, modify and redistribute this package and associated files under the Perl Artistic Licence or the GNU General Public Licence.
To install C::Utility, copy and paste the appropriate command in to your terminal.
cpanm
cpanm C::Utility
CPAN shell
perl -MCPAN -e shell install C::Utility
For more information on module installation, please visit the detailed CPAN module installation guide.