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:
new XXX
are replaced by:
new XXX(({struct XXX t = {proto: &ProtoTypes_$1}; t;}))
Occurrences of:
new XXX(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 20200901.
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.
mapCode($file)
Find the structures and methods defined in a file
Parameter Description
1 $file Input file
printData($lineNumber, $line)
Print statement
Parameter Description
1 $lineNumber Code line number
2 $line Code line
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'); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
exports aaa new$Node key_$Node
typedef struct $Node // Node definition
{char * key; // Key for the node
} $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 :aaa 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;
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;
ok index(scalar(readFile($bh)), <<END) > -1; # Generated base.h
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};
BaseNode newBaseNode(BaseNode allocator) {return allocator;}
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;
ok index(scalar(readFile $dh), <<'END') > -1;
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};
DerivedNode newDerivedNode(DerivedNode allocator) {return allocator;}
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",
},
},
structureParameters => { BaseNode => { dump_BaseNode => 1, key_BaseNode => 1 } },
structures => {
BaseNode => { comment => "Node definition", flags => "", name => "BaseNode" },
},
testsFound => { dump => 1, newNode => 1 },
testsNeeded => { key => 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",
},
},
structureParameters => { DerivedNode => { dump_DerivedNode => 1, key_DerivedNode => 1 } },
structures => {
DerivedNode => { comment => "Node definition", flags => "", name => "DerivedNode" },
},
testsFound => {},
testsNeeded => { dump => 1, key => 1 },
};
}
clearFolder($d, 10);
done_testing;
if ($localTest)
{say "TO finished in ", (time() - $startTime), " seconds";
}
PreprocessOpsMap Definition
Methods and structures in the C file being preprocessed
Output fields
methods
Methods.
structures
Structure definitions.
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 mapCode - Find the structures and methods defined in a file
4 method - Check whether a line of C code defines a method, returning (return, name, flags, comment) if it is, else ()
5 printData - Print statement
6 structure - Check whether a line of C code defines a structure, returning (name, flags, comment) if it is, else ()
7 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
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.