Preprocess::Ops - Preprocess ◁, ◀, ▷ and ▶ as operators in ANSI-C.
See the final lines of: https://github.com/philiprbrenan/C/blob/master/c/z/arenaTree/arenaTree.c for working examples of the following operators.
Preprocess ▷ and ▶ as method dispatch by translating:
p = node ▷ key("a");
to:
p = node . proto->key(&node, "a");
and:
p = node ▶ key("a");
p = node -> proto->key(node, "a");
Preprocess instances of ◁ as a constant creation operator:
c ◁ sfc("cba");
to get:
const typeof(sfc("cba")) c = sfc("cba");
Preprocess instances of ◀ as a variable creation operator:
d ◀ sfc("cba");
typeof(sfc("cba")) c = sfc("cba");
which, in effect, produces:
const char c = sfc("cba"); char d = sfc("cba");
in the context of:
char sfc(char *s) {return *s;} int main(void) { c ◁ sfc("cba"); d ◀ sfc("cba"); assert(c == 'c'); }
Preprocess instances of ◉ as starting a here document:
char *c = ◉; a b ◉
char *a = "a\n" " b\n" ;
Convert instances of ✓ as in:
✓ a == 1;
assert(a == 1);
to make assert function calls more prominent in tests.
Convert instances of ≞ as in:
Colour c; c ≞ makeColour(0,1,0,1);
Colour c; memcpy( ((void *)&c, ({typeof(c) s = makeColour(0,1,0,1); (void *)&s;}), sizeof(c));
to allow piece-wise initialization of structures with constant elements.
Occurrences of the $ character are replaced by the base name of the file containing the source 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:
newXXX(({struct XXX t = {proto: &ProtoTypes_$1}; t;}))
new XXX(a:1)
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 which should be included in the c file for use via the ▷ and ▶ operators.
//T immediately followed by the name of a method up to its first _ (if any or the end of the name otherwise) marks a function as testing all the methods that start with that name:
void test10() //Tsystem //TprintsAs { a ◁ make$FromString("uname"); a ▷ system; ✓ a ▷ containsString("Linux"); ✓ a ▷ printsAs(◉); Linux ◉ a ▷ free; }
Function test10 is marked as testing both system_string and printsAs_stringBuffer_string. Functions that are declared static but have no associated tests are listed in the preprocessor output as in:
The following methods need tests: parseXmlFromString
after preprocessing a file called xml.c containing:
static $Parse parse$FromString_$Parse_StringBuffer (StringBuffer string) {return make$ParseFromString(0, string, strlen(string)); }
with no test function marked with //TparseXmlFromString.
The duplicate command generates the previous function with the changes indicated in the words following the command as in:
static char * key_$Node // Get the key for a node (const $Node n) // Node {return n.key; } duplicate s/key/data/g
which adds the following code to the current output file:
static char * data_$Node // Get the data for a node (const $Node n) // Node {return n.data; }
The exports command provides a name for or a collection of functions that can be included in generated output files, for instance:
exports aaa new$Node key_$Node
creates a new set of exports called aaa which contains the two functions mentioned. As these names have $ in them they will be expanded with the base name of the file into which they are being copied.
The include command copies the named function, structures, and exported collections from the specified file into the current output file. For instance:
include ../arenaTree.c :arena !key_$Node data_$Node
reads the relative file ../arenaTree.c and copies in all the structures mentioned in collection arena except for key_$node as well as copying the explicitly mentioned function data_$Node.
Preprocess ◁, ◀, ▷ and ▶ as operators in ANSI-C.
Version 20201024.
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 ▷ 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:
if (88) { my $d = q(zzz); my $ds = fpd($d, qw(source)); my $dd = fpd($d, qw(derived)); my $sc = fpe($ds, qw(node c)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $dc = fpe($dd, qw(node c)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $dh = fpe($dd, qw(node h)); owf($sc, <<END); #include <stdio.h> typedef struct Node // Node {const struct ProtoTypes_Node *proto; int data; } Node; #include "node.h" static Node by // New from node * number (const Node * n, // Node const int i) // Multiplier {return new Node(data: i * n->data); } static void dump // Dump a node to stdout (const Node * n) // Node to dump {printf("data=%d\ ", n->data); } int main(void) //TnewNode //Tdump //Tby {a ◁ new Node(data: 6); b ◁ a ▷ by(7); b ▷ dump; return 0; } END my $r = c($sc, $dc, $dh); # Preprocess source c to get derived c # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $c = qq((cd $dd; gcc node.c -o a; ./a)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 is_deeply scalar(qx($c)), "data=42 "; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 is_deeply readCFile($dc), <<'END'; # Generated base.c # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 #line 1 "node.c" # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 #include <stdio.h> typedef struct Node // Node {const struct ProtoTypes_Node *proto; int data; } Node; #include "node.h" static Node by // New from node * number (const Node * n, // Node const int i) // Multiplier {return newNode(({struct Node t = {data: i * n->data, proto: &ProtoTypes_Node}; t;})); } static void dump // Dump a node to stdout (const Node * n) // Node to dump {printf("data=%d ", n->data); } int main(void) //TnewNode //Tdump //Tby {const typeof(newNode(({struct Node t = {data: 6, proto: &ProtoTypes_Node}; t;}))) a = newNode(({struct Node t = {data: 6, proto: &ProtoTypes_Node}; t;})); const typeof(a.proto->by(&a, 7)) b = a.proto->by(&a, 7); b.proto->dump(&b); return 0; } END is_deeply readCFile($dh), <<END; # Generated include file static Node by (const Node * n, const int i); static void dump (const Node * n); int main(void); struct ProtoTypes_Node { Node (*by)( // New from node * number const Node * n, // Node const int i); // Multiplier void (*dump)( // Dump a node to stdout const Node * n); // Node to dump } const ProtoTypes_Node = {by, dump}; Node newNode(Node allocator) {return allocator;} END clearFolder($d, 10); } if (36) { my $d = q(zzz); my $c = owf(fpe($d, qw(source c)), <<'END'); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 #include <assert.h> #include <stdio.h> int main(void) {char *a = ◉; a b ◉ ✓ a[0] == 'a'; printf("%s", a); } END my $h = fpe($d, qw(source h)); my $g = fpe($d, qw(derived c)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $r = c($c, $g, $h); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 is_deeply scalar(qx(cd $d; gcc derived.c -o a; ./a)), <<END; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 a b END is_deeply readCFile($g), <<'END'; #line 1 "source.c" # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 #include <assert.h> #include <stdio.h> int main(void) {char *a = "a " " b " ; assert( a[0] == 'a'); printf("%s", a); } END clearFolder($d, 10); }
Methods and structures in the C file being preprocessed
Methods.
Structure definitions.
Structure of the C program being preprocessed
Structures used as parameters
Tests found
Tests still needed
Structure declaration
Comment for structure
Flags for structure
Name of structure
Remove trailing white space and comment
Parameter Description 1 $s String
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
Check whether a line of C code defines a structure, returning (name, flags, comment) if it is, else ()
Find the structures and methods defined in a file
Parameter Description 1 $file Input file
Print statement
Parameter Description 1 $lineNumber Code line number 2 $line Code line
Duplicate the previous function with the specified changes applied
Parameter Description 1 $lineNumber Line number of line being expanded 2 $inputFile File containing line being expanded 3 $code Lines of 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
1 c - Preprocess ▷ and ▶ as method dispatch operators in ANSI-C.
2 duplicateFunction - Duplicate the previous function with the specified changes applied
3 includeFile - Expand include files so that we can pull in code and structures from other files in the includes folder.
4 mapCode - Find the structures and methods defined in a file
5 method - Check whether a line of C code defines a method, returning (return, name, flags, comment) if it is, else ()
6 printData - Print statement
7 structure - Check whether a line of C code defines a structure, returning (name, flags, comment) if it is, else ()
8 trimComment - Remove trailing white space and comment
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
philiprbrenan@gmail.com
http://www.appaapps.com
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.
To install Preprocess::Ops, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Preprocess::Ops
CPAN shell
perl -MCPAN -e shell install Preprocess::Ops
For more information on module installation, please visit the detailed CPAN module installation guide.