The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

C::Utility - utilities for generating C programs

VERSION

This documents C::Utility version 0.009 corresponding to git commit 3ddad303724b7d7b1e8a30afe53edd09bed484f7 released on Tue Mar 27 15:32:59 2018 +0900.

DESCRIPTION

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.

FUNCTIONS

convert_to_c_string

   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 @.

convert_to_c_string_pc

    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);

produces output

    "The quick \"brown\" fox\@farm\n"
    "jumped %%over the lazy dog.\n"

(This example is included as fox-pc.pl in the distribution.)

c_string

Alias for "convert_to_c_string".

ch_files

    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".

escape_string

   my $escaped_string = escape_string ($normal_string);

Escape double quotes (") in a string with a backslash.

c_to_h_name

    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

    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".

wrapper_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.

    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,

    #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"

hash_to_c_file

    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 $!;

produces output

    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:

    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

     line_directive ($fh, 42, "file.x")

prints

     #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.

    use C::Utility 'line_directive';
    my $out = '';
    line_directive (\$out, 99, "balloons.c");
    print $out;

produces output

    #line 99 "balloons.c"

(This example is included as line-directive.pl in the distribution.)

brute_force_line

    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.

add_lines

    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.

remove_quotes

    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.

linein

    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.

lineout

    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.

    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 $!;

produces output

    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

    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;

produces output

    /*
    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.

read_includes

    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.

DEPENDENCIES

Carp

Carp is used to report errors.

File::Spec

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

File::Versions is used to back up files

C::Tokenize

C::Tokenize is used by "read_includes".

File::Slurper

File::Slurper is used by "read_includes".

HISTORY

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.

AUTHOR

Ben Bullock, <bkb@cpan.org>

COPYRIGHT & LICENCE

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.