A simple script to serialize files

Config file format - general info

Jun 15, 2010 by cesla

Each CodeIgor project needs a config file, where you define

  • solutions, i.e. subdirectiories for processed files
  • files and directories to process for each solution
  • params: patterns with values

Config file is in a simple XML format and looks e.g. like this:

<config version="1.0"> <preproc> <parse> <dir>input/files</dir> <file>input/</file> </parse> </preproc> <solution name="some_name"> <parse> <file>input/main.cpp</file> <param pattern="{xxx}">12345</param> </parse> <parse> <file output="main2.cpp">input/main.cpp</file> <param pattern="{xxx}">9999</param> </parse> </solution> <solution name="some_other_name"> <parse> <file>input/main.cpp</file> <param pattern="{xxx}">321049</param> </parse> </solution> </config>

Minimal config file looks like this

<config> <solution name="some_name"> <parse> <file>input/main.cpp</file> <param pattern="{xxx}">12345</param> </parse> </solution> </config>

This means that in solution 'some_name' file 'input/main.cpp' will be processed in such a way, that every occurence of '{xxx}' in the file will be changed to '12345'. So the end result, will be generating such directory structure:

./cc_out/ some_name/ main.cpp - all {xxx} changed to 12345

XML structure

Jun 17, 2010 by cesla

As stated before, CodeIgor config files are of XML format. XML entities inside can be rewritten in a form of tree structure:

config fileset file dir preproc parse file dir fileset param (...) postproc parse file dir fileset param (...) solution parse file dir fileset param (...) (...) summary parse file param

This means that each 'config' block may contain a 'preproc' block, 'postproc' block and any number of 'solution' blocks. These block contain 'parse' blocks (or 'parse sets') - and each one of these defines input files and directories, and how does CodeIgor have to process them.

The 'config' block may also have one or more 'fileset' blocks, each with an 'id' attribute, defining input files and directories (just like in 'parse' blocks). Such file sets can then be used in 'parse' blocks by adding empty 'fileset' block to them. Therefore

<config> <fileset id="someid"> <file output="xx/">input/</file> <file>input/main.cpp</file> </fileset> <solution> <parse> <fileset id="someid" /> <param pattern="{someparam}">1</param> </parse> </solution> </config>

is exactly te same as

<config> <solution> <parse> <file output="xx/">input/</file> <file>input/main.cpp</file> <param pattern="{someparam}">1</param> </parse> </solution> </config>

This may not seem useful at first, but if you need to specify 5 or more files for more than one parse set, it becomes very helpful.

For every solution, CodeIgor creates a subdirectory (name corresponds to the solution name or - if that's not defined - solution number) in which every parse set output is saved.

Global & solution blocks

Jun 15, 2010 by cesla

Every 'solution' or 'preproc'/'postproc' block consists of one or more 'parse' blocks. The only difference between 'solution' and 'preproc'/'postproc' is that all parse sets of 'preproc' (older versions support 'global' block - since 1.03 it's proper name is 'preproc') block are processed before parse sets of each solution, and all parse sets of 'postproc' block are processed after parse sets of each solution, i.e. config

<config> <preproc> <parse> <dir>input/files</dir> </parse> </preproc> <postproc> <parse> <dir>input/other/files</dir> </parse> </postproc> <solution name="some_name"> <parse> <file>input/main.cpp</file> <param pattern="{xxx}">12345</param> </parse> </solution> <solution name="some_other_name"> <parse> <file>input/main.cpp</file> <param pattern="{xxx}">321049</param> </parse> </solution> </config>

is equal to

<config> <solution name="some_name"> <parse> <dir>input/files</dir> </parse> <parse> <file>input/main.cpp</file> <param pattern="{xxx}">12345</param> </parse> <parse> <dir>input/other/files</dir> </parse> </solution> <solution name="some_other_name"> <parse> <dir>input/files</dir> </parse> <parse> <file>input/main.cpp</file> <param pattern="{xxx}">321049</param> </parse> <parse> <dir>input/other/files</dir> </parse> </solution> </config>

Parse sets

Jun 17, 2010 by cesla

A 'parse set' is a set of 'file', 'dir', 'fileset' and 'param' blocks that needs to be treated separately within one solution. By defining a parse set you're telling CodeIgor:

Thou shall fetch me this file, and another one, and this directory, and also all files and directories defined in these filesets; next, use these patterns to change whatever thou will find inside in the manner I specify!

Of course, CodeIgor always agrees do to your bidding!

You may be wondering, why would you need more than one parse set for each solution. Consider this example:

<config> <solution name="some_name"> <parse> <dir>input</dir> <param pattern="{xxx}">12345</param> </parse> </solution> </config>

This means that for every file in './input' directory, every '{xxx}' will be changed to '12345'. Having multiple parse sets allows you to

  • save copies of files with a different value of the same parameter within the same solution: <config> <solution name="some_name"> <parse> <dir>input</dir> <param pattern="{xxx}">12345</param> </parse> <parse> <dir output="another">input</dir> <param pattern="{xxx}">90</param> </parse> </solution> </config> Now for every file in './input' directory, every '{xxx}' will be changed to '12345', but there will be also directory 'another/' within the solution, containing every file in './input' directory, but with every '{xxx}' changed to '90' instead of '12345'.
  • use the same pattern to get two or more different outputs: <config> <solution name="some_name"> <parse> <file output="file1.txt">input/file.txt</file> <param pattern="{xxx}">AAA</param> </parse> <parse> <file output="file2.txt">input/file.txt</file> <param pattern="{xxx}">BBB</param> </parse> </solution> </config> Now in file './input/file.txt' directory, every '{xxx}' will be changed to
    • 'AAA' and this will be saved to 'some_name/file1.txt'
    • 'BBB' and this will be saved to 'some_name/file2.txt'

Summary block

Jun 21, 2010 by cesla

Having generated a lot of different solutions, you usually need some way to visit each directory and do something there, e.g. compile your code, run 'make' or something similar. CodeIgor provides summary block to generate a special file in your output directory.

(...) <summary> <file></file> <param><![CDATA[#!/bin/sh {startloop} cd {codeigor:solution_names} make cd .. {stoploop} ]]></param> </summary> (...)

(Note that param block doesn't have a 'pattern' attribute and file defined here is the name of the summary file)
From the above summary block you'll get a file looking like this:

#!/bin/sh cd solution_1 make cd .. cd solution_2 make cd ..

Note that this feature is still in development. You may define many such loops (i.e. '{startloop}-{codeigor:solution_names}-{stoploop}' structures) inside your summary block - it will work properly, but I still am looking for a better solution.