Name

Preprocess::Ops - Preprocess ▷ and ▶ as method dispatch operators in ANSI-C.

Synopsis

Preprocess ▷ and ▶ as method dispatch operators in ANSI-C by translating:

p = node ▶ key("a");

to:

p = node->proto->key(node, "a");

and:

p = tree ▷ root;

to:

p = tree.proto->root(tree);

Occurrences of the $ character are replaced by the base name of the containing file with the first letter capitalized, so that

typedef struct $Node $Node;

in a file called tree.c becomes:

typedef struct TreeNode TreeNode;

Occurrences of:

newXXX

are replaced by:

newXXX(({struct XXX t = {proto: &ProtoTypes_$1}; t;}))

Occurrences of:

newXXX(a:1)

are replaced by:

newXXX(({struct XXX t = {a:1, proto: &ProtoTypes_$1}; t;}))

The prototype vectors are generated by examining all the methods defined in the c file. The prototype vectors are written to the specified h file so that they can be included in the c file for use via the ▷ and ▶ operators.

See: https://github.com/philiprbrenan/C/blob/master/c/z/xml/xml.c for a working example.

Description

Preprocess ▷ and ▶ as method dispatch operators in ANSI-C.

Version 20200826.

The following sections describe the methods in each functional area of this module. For an alphabetic listing of all methods by name see Index.

Preprocess

Preprocess ▷ and ▶ as method dispatch operators.

c($inputFile, $cFile, $hFile, $column)

Preprocess ▷ and ▶ as method dispatch operators in ANSI-C.

   Parameter   Description
1  $inputFile  Input file
2  $cFile      C output file
3  $hFile      H output file
4  $column     Optional start column for comments (80)

Example:

  my $I   =     fpd($d, qw(includes));

  my $sbc = owf(fpe($d, qw(source base c)), <<'END');  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

typedef struct $Node                                                            // Node definition
 {char * key;                                                                   // Key for the node
 } $Node;

$Node new$Node                                                                  //C Create a new node
 (const struct $Node node)                                                      // Input key
 {return node;
 }

static char * key_$Node                                                         // Get the key for a node
 (const $Node n)                                                                // Node to dump
 {return n.key;
 }

static void dump_$Node                                                          // Dump a node
 (const $Node n)                                                                // Node to dump
 {printf("%s
", n ▷ key);
 }

$Node n = new$Node(key: "a");                                                   //TnewNode
assert(!strcmp(n ▷ key, "a"));
      n ▷ dump;                                                                 //Tdump
END


  my $sdc = owf(fpe($d, qw(source derived c)), <<'END');  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

typedef struct $Node                                                            // Node definition
 {wchar * key;
 } $Node;


include base.c new$Node  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


include base.c key_$Node  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


include base.c dump_$Node  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

END


  my $bc = fpe($I, qw(base c));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  my $bh = fpe($I, qw(base h));

  my $dc = fpe($I, qw(derived c));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  my $dh = fpe($I, qw(derived h));


  my $r = c($sbc, $bc, $bh);                                                    # Preprocess base.c  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


# owf($logFile, readFile($bc)); exit;

  ok index(scalar(readFile($bc)), <<'END') > -1;                                # Generated base.c  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

typedef struct BaseNode                                                            // Node definition
 {char * key;                                                                   // Key for the node
 } BaseNode;

BaseNode newBaseNode                                                                  //C Create a new node
 (const struct BaseNode node)                                                      // Input key
 {return node;
 }

static char * key_BaseNode                                                         // Get the key for a node
 (const BaseNode n)                                                                // Node to dump
 {return n.key;
 }

static void dump_BaseNode                                                          // Dump a node
 (const BaseNode n)                                                                // Node to dump
 {printf("%s
", n.proto->key(n));
 }

BaseNode n = newBaseNode(({struct BaseNode t = {key: "a", proto: &ProtoTypes_BaseNode}; t;}));                                                   //TnewNode
assert(!strcmp(n.proto->key(n), "a"));
      n.proto->dump(n);                                                                 //Tdump
END

# owf($logFile, readFile($bh)); exit;
  is_deeply scalar(readFile($bh)), <<END;                                       # Generated base.h
BaseNode newBaseNode
 (const struct BaseNode node);
static char * key_BaseNode
 (const BaseNode n);
static void dump_BaseNode
 (const BaseNode n);
struct ProtoTypes_BaseNode {
  void  (*dump)(                                                                // Dump a node
    const BaseNode n);                                                          // Node to dump
  char *  (*key)(                                                               // Get the key for a node
    const BaseNode n);                                                          // Node to dump
 } const ProtoTypes_BaseNode =
{dump_BaseNode, key_BaseNode};
END



  my $R = c($sdc, $dc, $dh);                                                    # Preprocess derived.c  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

# owf($logFile, readFile($dc)); exit;
  ok index(scalar(readFile $dc), <<'END') > -1;
static void dump_DerivedNode                                                          // Dump a node
 (const DerivedNode n)                                                                // Node to dump
 {printf("%s
", n.proto->key(n));
 }
END
# owf($logFile, readFile($dh)); exit;
  is_deeply scalar(readFile $dh), <<'END';
DerivedNode newDerivedNode
 (const struct DerivedNode node);
static char * key_DerivedNode
 (const DerivedNode n);
static void dump_DerivedNode
 (const DerivedNode n);
struct ProtoTypes_DerivedNode {
  void  (*dump)(                                                                // Dump a node
    const DerivedNode n);                                                       // Node to dump
  char *  (*key)(                                                               // Get the key for a node
    const DerivedNode n);                                                       // Node to dump
 } const ProtoTypes_DerivedNode =
{dump_DerivedNode, key_DerivedNode};
END

# owf($logFile, dump(unbless $r)); exit;

  is_deeply $r,
{
  methods             => {
                           dump_BaseNode => {
                                              comment    => "Dump a node",
                                              flags      => {},
                                              name       => "dump",
                                              parameters => [["const BaseNode", "n", "Node to dump"]],
                                              return     => "void ",
                                              structure  => "const BaseNode",
                                            },
                           key_BaseNode  => {
                                              comment    => "Get the key for a node",
                                              flags      => {},
                                              name       => "key",
                                              parameters => [["const BaseNode", "n", "Node to dump"]],
                                              return     => "char * ",
                                              structure  => "const BaseNode",
                                            },
                           newBaseNode   => {
                                              comment    => "Create a new node",
                                              flags      => { C => 1 },
                                              name       => "newBaseNode",
                                              parameters => [["const struct BaseNode", "node", "Input key"]],
                                              return     => "BaseNode ",
                                              structure  => "const struct BaseNode",
                                            },
                         },
  structureParameters => {
                           "BaseNode" => { dump_BaseNode => 1, key_BaseNode => 1 },
                           "struct BaseNode" => { newBaseNode => 1 },
                         },
  structures          => {
                           BaseNode => { comment => "Node definition", flags => "", name => "BaseNode" },
                         },
  testsFound          => { dump => 1, newNode => 1 },
  testsNeeded         => { key => 1, newBaseNode => 1 },
};

# owf($logFile, dump(unbless $R)); exit;

  is_deeply $R,
{
  methods             => {
                           dump_DerivedNode => {
                                                 comment    => "Dump a node",
                                                 flags      => {},
                                                 name       => "dump",
                                                 parameters => [["const DerivedNode", "n", "Node to dump"]],
                                                 return     => "void ",
                                                 structure  => "const DerivedNode",
                                               },
                           key_DerivedNode  => {
                                                 comment    => "Get the key for a node",
                                                 flags      => {},
                                                 name       => "key",
                                                 parameters => [["const DerivedNode", "n", "Node to dump"]],
                                                 return     => "char * ",
                                                 structure  => "const DerivedNode",
                                               },
                           newDerivedNode   => {
                                                 comment    => "Create a new node",
                                                 flags      => { C => 1 },
                                                 name       => "newDerivedNode",
                                                 parameters => [["const struct DerivedNode", "node", "Input key"]],
                                                 return     => "DerivedNode ",
                                                 structure  => "const struct DerivedNode",
                                               },
                         },
  structureParameters => {
                           "DerivedNode"        => { dump_DerivedNode => 1, key_DerivedNode => 1 },
                           "struct DerivedNode" => { newDerivedNode => 1 },
                         },
  structures          => {
                           DerivedNode => { comment => "Node definition", flags => "", name => "DerivedNode" },
                         },
  testsFound          => {},
  testsNeeded         => { dump => 1, key => 1, newDerivedNode => 1 },
};

PreprocessOpsParse Definition

Structure of the C program being preprocessed

Output fields

methods

Methods.

structureParameters

Structures used as parameters

structures

Structure definitions.

testsFound

Tests found

testsNeeded

Tests still needed

PreprocessOpsStruct Definition

Structure declaration

Output fields

comment

Comment for structure

flags

Flags for structure

methods

Methods.

name

Name of structure

structureParameters

Structures used as parameters

structures

Structure definitions.

testsFound

Tests found

testsNeeded

Tests still needed

Private Methods

trim($s)

Remove trailing white space and comment

   Parameter  Description
1  $s         String

method($line)

Check whether a line of C code defines a method, returning (return, name, flags, comment) if it is, else ()

   Parameter  Description
1  $line      Line of C code

structure($line)

Check whether a line of C code defines a structure, returning (name, flags, comment) if it is, else ()

   Parameter  Description
1  $line      Line of C code

includeFile($lineNumber, $inputFile, $cFile, $hFile, $code)

Expand include files so that we can pull in code and structures from other files in the includes folder.

   Parameter    Description
1  $lineNumber  Line number of line being expanded
2  $inputFile   File containing line being expanded
3  $cFile       Output C file
4  $hFile       Output H file
5  $code        Line of code

Index

1 c - Preprocess ▷ and ▶ as method dispatch operators in ANSI-C.

2 includeFile - Expand include files so that we can pull in code and structures from other files in the includes folder.

3 method - Check whether a line of C code defines a method, returning (return, name, flags, comment) if it is, else ()

4 structure - Check whether a line of C code defines a structure, returning (name, flags, comment) if it is, else ()

5 trim - Remove trailing white space and comment

Installation

This module is written in 100% Pure Perl and, thus, it is easy to read, comprehend, use, modify and install via cpan:

sudo cpan install Preprocess::Ops

Author

philiprbrenan@gmail.com

http://www.appaapps.com

Copyright

Copyright (c) 2016-2019 Philip R Brenan.

This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.