Autogen

AutoGen is an interesting code generation tool that I just stumbled upon.

What can you do with it? Well, let’s say that we have a simple specification for what an Employee class might look like:

autogen definitions employee;

class_name = Employee;
field = {
    field_type = long;
    field_name = id; 
    field_example_value = 1001;
};
field = {
    field_type = string;
    field_name = first_name;
    field_example_value = "\"Marc\"";
};
field = {
    field_type = string;
    field_name = last_name;
    field_example_value = "\"Abramowitz\"";
};
field = { 
    field_type = long;
    field_name = department_id;
    field_example_value = 500;
};

We can take this and then process it with a template to generate code automatically.

Here’s an example of such a template:

[+ AutoGen5 template h cpp +]
[+
(define (type-name underscored_name) (string-substitute (string-capitalize underscored_name) "_" ""))
+]
[+ CASE (suffix) +][+
   ==  h  +]
#include <string>
   
class [+ (get "class_name") +] {
public:
  [+ (type-name (get "class_name")) +]([+ FOR field "," +]
    [+ (get "field_type") +] [+ (get "field_name") +][+ ENDFOR list +]
  );
  // virtual ~[+ (type-name (get "class_name")) +]();
  
[+ FOR field "" +] [+ (get "field_type") +] get_[+ (get "field_name") +]() const;
[+ ENDFOR list +]
private:
  [+ (get "class_name") +](const [+ (get "class_name") +]&); // prevent compiler-generated copy constructor
[+ FOR field "" +]
  [+ (get "field_type") +] [+ (get "field_name") +];[+ ENDFOR list +]
  
};
[+ ==  cpp  +]
#include <iostream>
#include "[+ (string-downcase (get "class_name")) +].h"

[+ (get "class_name") +]::[+ (get "class_name") +]([+ FOR field "," +]
    [+ (get "field_type") +] [+ (get "field_name") +][+ ENDFOR list +]
)
{[+ FOR field "" +]
  this->[+ (get "field_name") +] = [+ (get "field_name") +];[+ ENDFOR list +]
} 
  
[+ FOR field "" +][+ (get "field_type") +] [+ (get "class_name") +]::get_[+ (get "field_name") +]() const
{
  return this->[+ (get "field_name") +];
} 
  
[+ ENDFOR list +]

int main(int argc, char* argv[])
{
  [+ (get "class_name") +] [+ (string-downcase (get "class_name")) +]([+ FOR field ", " +][+ (get "field_example_value") +][+ ENDFOR list +]);
  [+ FOR field "" +]
  cout << "[+ (get "field_name") +] = " << [+ (string-downcase (get "class_name")) +].get_[+ (get "field_name") +]() << endl;[+ ENDFOR list +]
  
  return 0;
}

[+ ESAC +]

You can generate code from this definition and template by doing:

$ autogen employee.def

This spits out a .h and a .cpp file which are ready to be used:

$ g++ -o employee employee.cpp && ./employee 
id = 1001
first_name = Marc
last_name = Abramowitz
department_id = 500

The template syntax is a little bit odd. Autogen is based on Guile, which is similar to Scheme, which is derived from Lisp (:-)). But as you can see even from this very simple example, there’s a lot of expressiveness here, allowing you to probably do some fairly sophisticated things.

Downloads

Updates

  • Update 2006-03-17: I updated the files a bit so that more of the code is actually generated, including the example data in the main function.
  • Update 2006-03-20: I fixed the capitalization of AutoGen. Also, if you are interested in code generation tools in general, you may want to check out my post on CodeWorker.

Design Patterns: Elements of Reusable Object-Oriented Software (Addison-Wesley Professional Computing Series)

Leave a Reply

Your email address will not be published. Required fields are marked *