October 19, 2015

Streamlining huge sets of documentation

Documentation, everybody wants to read it, nobody likes to write it. When you have it there never is any order to it. This post is all about streamlining documents so everything looks like you had a plan to begin with.

Usually, documentation are created using several sources, html, pdf, doc etc. There are always many requirements for the actual documents, but ever requirements for the actual file naming conventions, and how do you treat multiple formats?

I suggest pdf as the single publishing source you should aim for. Pdf because it is readable basically anywhere, and because if your document is in some obscure format, you can usually find a printer driver at any system and print your obscure document as pdf.

But before we start changing to the output format let's have a look at the actual fie naming conventions. These are very important as they serve as the for searching through the documentation once it is located on a disk.

For starters I'd like the file names to look similar even though they are utterly obscure. I'm choosing the encoding:

authorname authorsurname - document title.extension

Once the formatting is the same we can always have a look at changing the order of the author,name etc. The important thing is that all documents follow the same conventions because this makes it possible to work on a huge set of data.

#/bin/bash
files=("*")

for f in $files; do 
    test ! -f "$f" && echo "$f is not a file - skipping" && continue

    lc=`echo "$f" | tr '[A-Z]' '[a-z]'`

    bad=`echo "$lc" | grep -v " - "`
    if [ -n "$bad" ]; then 
echo "yikes -> $bad";
    else
author=`echo $lc | sed 's/\(.*\) - \(.*\)/\1/'`
title=`echo $lc | sed 's/\(.*\) - \(.*\)/\2/'`
dyt=`echo $author | sed 's/\(.*\), \(.*\)/\2 \1/'`
n=`echo $dyt - $title`
if [ "$f" != "$n" ]; then
   mv -i "$f" "$dyt - $title"
fi
    fi
done

The above snipplet changes the names of the files in your folder to lower case and swaps some of the document formatting to format above. All files that are not touched are echoed with Yikes to your terminal and multiple filenames are queried for action. This handles "with some luck" most of your files. Once your directory is edited for the final changes you'll need to convert your stuff.

Depending on your document source formats, you'll need to install the appropriate converter tools. The following snipplet is for djvu to pdf conversion. You can add more converters:

#/bin/bash
files=("*")

for f in $files; do
    extension=`echo "$f" | cut -d '.' -f2`
    n=`echo "$f" | cut -d '.' -f1`
    if [ "$extension" = "djvu" ]; then
ddjvu -format=pdf "$f" "$n.pdf"
    fi
done

That's all for the conversion process, feel free to edit and change the snipplets to suit your needs.

July 04, 2015

Yosemite Eclipsed?!

♬ Total Eclipse of Yosemite  . To quote an old Pink Floyd song. Or was that total eclipse of the moon? Anyway, now that we have PHP, Apache, and SVN installed, it's time we setup a programming IDE that can utilise these tools.

Download Eclipse PHP Edition, more specifically the Mac tarball. Extract it to your applications folder:

# tar -xzvf ~/Downloads/eclipse-php-mars-R-macosx-cocoa-x86_64.tar.gz -C /applications/

This will install the Eclipse IDE in your Application folder, making it clickable using F4 to select the applications. To get xdebug rolling follow this guide.

July 02, 2015

SVN in Yosemite

If you intend to code in Yosemite, you're bound to need a source control system. I'm using svn, its old and i know it, but I'm quite fond of the old chap. The easiest way to get it there is by using MacPorts.

# sudo port selfupdate
# sudo port install sqlite3 apr-util neon subversion

It's verified by issuing:

# svn 

in you terminal. You're now ready to use the source control system for your own programming projects.

MySQL in Yosemite



This is the second article on marvellous Yosemite. This time we're installing and configuring MySQL.

Download MySQL and run the pkg installer, there's an issue the MySQL LaunchDeamon script, so if the installation fails it's ok the files are there, but the MySQL deamon could not be added. To add the MySQL deamon to launchctl the LaunceDeamon file needs to be created.

# echo "<!--?xml version="1.0" encoding="UTF-8"?-->
<plist version="1.0">
  <dict>
    <key>KeepAlive</key>
    <true />
    <key>Label</key>
    <string>com.mysql.mysqld</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/mysql/bin/mysqld_safe</string>
      <string>--user=mysql</string>
    </array>        
  </dict>
</plist>" | sudo tee /Library/LaunchDaemons/com.mysql.mysql.plist 

Once you have your file created, you'll need to set the file premissions, like we did for apache, and add the file to the launch deamon.

# sudo chown root:wheel /Library/LaunchDaemons/com.mysql.mysql.plist 
# sudo chmod 644 /Library/LaunchDaemons/com.mysql.mysql.plist 
# sudo launchctl -w /Library/LaunchDaemons/com.mysql.mysql.plist 

There are some socket logging issues that needs to be fixed, apparently a file is missing the /var folder. 

# sudo mkdir /var/mysql
# sudo ln -s /tmp/mysql.sock /var/mysql/mysql.sock

Next, you'll need to add the MySQL to your bash environment

# echo 'export PATH="/usr/local/mysql/bin:$PATH"' > ~/.bash_profile

Or you could add it to your bashrc file using >> ~/.bashrc its up to you. Then source the MySQL environment into your environment. This environment should be set at every log on via your .bash_profile file. To verify the environment type:

# mysql -v

You quit the MySQL shell using \q (escaped q). To setup the MTSQL root users password type:

# mysqladmin -u root password 'thepasswordyoulike'

You should now be able to run MySQL from your command line.

Apache in Yosemite?

Sounds like a cool trip to those ginormous trees dosen't it? And you may even see a native american while you're there. Well it is some kinda field trip, except you dont get to go to Yosemite. But you get to update your Mac to Yosemite.

So, if you haven't already updated your MacBook Pro to the latest OSX, get on with it lad. The following describes how to setup apache in a freshly baked OS-X 10.10.xx setup.

The apache webserver and php is already installed in Yosemite, it's just not setup to support 'users' sites. The webserver root directory of apache is present at:

# ls /Library/WebServer/Documents/

If you want to know your apache version type: 

# apachectl -v

To start, restart or stop, apache you use the apachectl command, i.e. 

# apachectl start
# apachectl restart
# apachectl stop

But prior to starting the web server you should configure the server for user Sites. We'd like to setup the 'old' Sites folder support, which now no longer can be done from the GUI, unless you view the shell as a GUI (I know I do).

You'll need to create a folder called 'Sites' in your home directory. This folder will serve as the web root for your source code, and allow you to access your files in a browser or eclipse, using the http://localhost/~username/ URL.

# mkdir ~/Sites
# echo "<Directory \"/Users/$USER/Sites\">
AllowOverride All
Options Indexes MultiViews FollowSymLinks
Require all granted
</Directory>" | tee sudo /etc/apache2/users/`whoami`.conf
# sudo chown root:wheel /etc/apache2/users/`whoami`.conf
# sudo chmod 644 /etc/apache2/users/`whoami`.conf

The above commands gives you a folder named 'Sites' in our user accounts home directory, and adds the 'users' configuration to the apache server. Next, we'll configure the apache to use the 'users' folder when it runs.

Open the apache configuration file in an editor as superuser (root) and uncomment the following configuration lines. I use emacs, but pico, nano or any other editor is just as good.

# sudo emacs /etc/apache/httpd.conf  

LoadModule authz_user_module libexec/apache2/mod_authz_user.so
LoadModule authz_host_module libexec/apache2/mod_authz_host.so
LoadModule userdir_module libexec/apache2/mod_userdir.so
LoadModule php5_module libexec/apache2/libphp5.so
Include /private/etc/apache2/extra/httpd-userdir.conf

Save the file and exit the editor. Then, open the apaches 'users' configuration file and uncomment the line 

Include /private/etc/apache2/users/*.conf

Save and exit, and your apache server will be ready to rock, with user dir and php support. To verify that the changes work you'll need to restart the apache http deamon.

# sudo apachectl restart
# curl http://localhost

the curl command should echo the contents of the apache servers index.html file, so after the command has run you should see:

<html><body><h1>It works!</h1></body></html>

To verify the userdir configuration you'll need the curl redirect option and an index.html file to check against.

# echo "<html><body><h1>$USER</h1></body></html>" > ~/Sites/index.html
# curl -L http://localhost/~`whoami`

The curl command should dump the file you created above, where $USER has been replaced with your user account name. 

To verify that PHP runs, you can create a simple php file in your ~/Sites folder:

# echo "<?php echo phpversion(); ?>" > ~/Sites/index.php
curl -L http://localhost/~`whoami`/index.php

The output should be the version number, if you prefer you can use the phpinfo() function instead but it will flood your terminal with info.

Finally, you'll need to add appache to the launch deamon to get it started every time you reboot.

# sudo launchctl load -w /System/Library/LaunchDeamons/org.apache.httpd.plist

May 28, 2015

WAR ENSEMBLE ring tone?

I did, I just needed to her Tom start the Slayer song with a scream at every incoming SMS. So I decided to rip him off youtube and also to try audacity.

# sudo aptitude install audacity

Then, goto to youtube.com and find Tom Screaming WAR ENSAMBLE. Fire up audacity and click record, flip to youtube, press play when done stop the recording, and play a bit with the filters.

Here is a noise reduction and amplify sound introduction

\m/ (o_O) \m/

Find and copy

One of the best articles on this subject. And a final single line for quick reference

# find /path/to/search/ -type f -name "regular-expression-to-find-files" | xargs cp -t /target/path


April 20, 2015

Parallel make & optimizations

Here's a bunch of makefile notes for creating valid parallel makefiles. The problem with writing makefiles and having then executed in parallel is that you'll have to know your source dependencies and resolve them so make does not attempt to build your in the wrong order.

I have header a lot about how bad make is at solving dependencies, and hvor other tool like the latest build in Visual Studio build is much better etc. I strongly disagree. VC hides the dependencies behind a "pointy clicky" scheme. Make dosent assume anything it leaves the dependency problem up to the developers, meanins that the people working on the source should know how to solve their sources dependencies!

As an example, the common idiom for writing recursive makefiles is that directory traversing, or any traversion for that matter, is implemented as a shell loop, or by using the make function "foreach". As both of these methods solve the traversion, they also both have their drawbacks.

The drawback with the shell method is that firstly you'll invoke a separate shell for each directory in the make process, and make cannot know whats going on in these sub shells and therefore make cannot solve any dependencies in them, which in the end usually causes the build to break. The "foreach" method forces you to create a function based makefile, which again makes writing dependencies hard(er).

Makes primary way to handle dependencies is using targets. The usual way is to say i.e.

all: prepare: depend

The above says that to build the all target, you'll have to build first prepare, which in turn depends on depend, meaning that make will have to build depend before prepare. Simple, and as i may add easy to read. For make this means that to start any processes it'll first build depend, and any parts of depend that can be executed in parallel will be so, again this goes for prepare and all. But how do you then traverse a set of subdirectories? Simple, you'll just make your dub directories a target i.e.

SUBDIRS:= src lib interface doc

.PHONY: $(SUBDIRS)
$(SUBDIRS):
            $(MAKE) $(MAKEFLAGS) --directory=$@ $(MAKECMDGOALS)

.PHONY: all
all: $(SUBDIRS)

The snipplet above executes make in the SUBDIRS list, using a make target instead of the common "for" approach. Not each of these SUBDIRS may have a set of dependencies that needs to be resolved, these dependencies are solved in the respective SUBDIRS directory, where they belong.

Lets say, that for the sake of illustration that lib depends on src and interface. Meaning that you cannot build the lib part of the project before both src and interface are finished. All you'd have to do to tell make these dependencies is to add a new target line stating these dependencies i.e

lib: src interface

There, the lib target is now depended on the src and interface targets meaning that make cannot execute the lib target in parallel with either src and interface. So, because the dependencies must be resolved, make will execute src, interface and doc in parallel and once it's done build the lib target. Just as you specified.

Let's say that the src directory is a huge directory, containing roughly 100 different software components for the build. Some set of these components are interdependend. Then, again you'll have to create a makefile containing a SUBDIRS target to traverse the various src components. Now, even though there are 100 components you still have to know which ones are depending on each other, and which can be build in parallel.

Usually, solving your source dependencies are pretty easy, but it could be a major writing task. Because it may only be 4 of the 100 components that must be build first. You can solve this in various ways, by creating 2 targets like SUBDIRS making the higher level components dependend on the lower levels i.e.

LOWLEVEL:=hw io drv os

These are the components lowest level, they must be build prior to other components in the src directory. For the sake of argument, hw contain the memory map, a interrupt layout etc. io contain hardware io, you know hardware ;), drv contain drivers needed by the os to communicate with the hw etc.

Next, the src directory contain a core components part, usually some components that are part of a framework and running on top of the lower levels, this could again be a subset of the 100 directories.
 

CORE:=menu network error

And finally, the rest of the 100 components are applications that all must be build after LOWLEVEL and CORE

APPLICATIONS:=$(filter-out $(LOWLEVEL) $(CORE), $(shell ls -d ./*/))

The applications are found using a shell command, this is because listing everyfile in this directory would be a pain. But you should remember that automatically finding things like this can have its drawbacks.Once you have all the targets in your makefile, you'll have to resolve the dependencies i.e.

$(APPLICATIONS):$(CORE):$(LOWLEVEL)

Should do the trick. Here's a listing of the short make file I used to explore these issues independently with.

SHELL:=/bin/sh
ALL_DIRS:=$(shell ls -d ./*/)
ENV:=${ENV}
LOWLEVEL:=src elektra
STUFF:=Documents Music
CORE:=$(filter-out $(LOWLEVEL) $(STUFF),$(ALL_DIRS))
SUBDIRS:=$(STUFF) $(CORE) $(LOWLEVEL)

.PHONY:
all: $(SUBDIRS)
    @echo $(ENV)

.PHONY: $(SUBDIRS)
$(SUBDIRS):

.PHONY: $(LOWLEVEL)
$(LOWLEVEL):
    @echo "lowlevel-> $@"

.PHONY: $(STUFF)
$(STUFF):
    @echo "stuff-> $@"   

.PHONY: $(CORE)
$(CORE):
    @echo "core-> $@"

$(CORE):$(LOWLEVEL) $(STUFF)

.PHONY: lowlevel
lowlevel: $(LOWLEVEL)

.PHONY: core
core: $(CORE)

.PHONY: stuff
stuff: $(STUFF)


References: makefile_tricks, Recursive make considered harmful

January 07, 2015

Flexin' your Bison

Code that writes code that writes code

The problem I'd like to solve in this post is a simple network structure generation scheme. Say we have a number of messages that we'd like to send from one machine to another. Being programmers we'd also like to have a visual indication of our network transactions, for this I'd use "Wireshark". And we'd like to have valid documentation representation, say, in html or generated by doxygen for that matter.

To keep this example as simple as possible, I'll address only the C structure generation and the wireshark "Lua" extention generation. This pair should be enough to display the general idea behind code generation. What I'd like to achieve is to produce a set of outputs based on a single input, helping me maintain the code base. This approach is similar to the "Strategy" pattern, if you're into patterns.

The tool we're writing is a command line tool for linux. I'd like the following options:
-l creates lua output, -c creates c output and -a creates all targets. The tool should take a single file in as argument with -f and produce a single file with -o output i.e

# ./yantlg -c -f telegram.ntl -o telegram.h
# ./yantlg -l -f telegram.ntl -o telegram.lua
# ./yantlg -a -f telegram.ntl

The above examples are what I'd like the final program to use, in this simple version the focus will be on the Lex and Yacc parts of the project. As using gnu opts for passing and error reporting program options in a program is worthy of a separate blog post.

The Lex and Yacc tools are explained in detail in may places here is, IMHO, a good introduction.

Network telegram language

Lex needs a file it can use to tokensize the language. But first we must define a simple network telegram structure language or "NTL" for short. I'm sure I'm not the first implementer of something like this, there's most likely a bunch of tools out there, but here's what I consider rational for solving the problem at hand.

The first  and simple version of NTL will be supporting the data types listed below, and of these data types, except the end of message marker, need a name to identify the variable of that type, which gives us:

M <name> - message
B <name> - byte (8 bits)
W <name> - word (16 bits)
D <name> - double word (32 bits)
Q <name> - quart word (64 bits)
E - end of message

An example of a test NTL telegram could, therefore, be:

M telegram
B version
B size
W word
D dword
Q qword
E

This will be stored in a file called "telegram.ntl" and this file will serve as the input for our NTL generator (compiler/encode/writer/whatever) .

Flex'ing tokens with lex - "or lexing tokens with Flex"

Lex needs a token it shares these tokens with the parser, translate file. Lex input files are usually identified by the extention "l" (that's lower case L), at least that's the extension recognized by make, so we'll use this.

%{
#include <stdio.h>
#include <stddef.h>
#include "yyltype.h"
#include "parser.h"

/* definitions for reporting errors, see a lex and yacc doc/book for details */
int yycolumn = 1;
#define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; \
    yylloc.first_column = yycolumn; yylloc.last_column = yycolumn + yyleng - 1;\
    yycolumn += yyleng;

%}
%option yylineno

%%
m                     { yylval.type = MESSAGE; return MESSAGE;}
e                     { return END; }
b                     { yylval.type = BYTE; return BYTE; }
w                     { yylval.type = WORD; return WORD; }
d                     { yylval.type = DWORD; return DWORD; }
q                     { yylval.type = QWORD; return QWORD; }
[a-zA-Z][a-zA-Z0-9_]+ { yylval.name = strdup(yytext); return NAME; }
\n                    { yycolumn = 1; } /* ignore end of line */;
[ \t]+                /* ignore whitespace */;
[^mebwdq]             { yyerror("'%s' unknown symbol",yytext); yyerror;}  /* Error on unknown tokens */
%%


The above is a *simple* lexer for our NTL generator, the only file that seem a bit strange is in the header section where #include "parser.h" is added. This file is generated by Yacc, and it must be included for the token names to be defined in the final compilation.

Notice every data type is assigned to a token. A token is identified by a token type and a name (except from the end token).  Tokens are composed by the [a-zA-Z][a-zA-Z0-9_]+ regular expression.

This expression states that a name must begin with a character either upper or lower case, this is defined by the first []: [a-zA-Z] part. Followed by either upper or lower characters a numeric value or the underscore character, defined by the second []: [a-zA-Z0-9_]+ part.

The final tree expressions are to ignore white spaces and newlines, and forces error reporting for unknown token characters.

Tokenized code generation

The code generation part is handled with Yacc (Bison). This tool needs a file with the extension "y", again an extension recognized by make. This file must contain the various specific C code parts for our NTL generator program.

Like the Lex file for tokenization this file is divided into a number of sections. Where the percentage curly braces contains the C code part, "%{ C code %}", including header file definitions etc. The %tokens contain the token definitions, and, finally, the percentage percentage section, "%% bnf %%", contain the BNF notated language syntax.

%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include "token.h"
#include "yyltype.h"

extern int yyleng;           /* Defined by the lexer used to output the length of the column */
extern int yylineno;         /* Defined by the lexer to get the current line number */
extern char *yytext;         /* Defined by the lexer to get the current token stream */
struct YYLTYPE yylloc;       /* This is the lexer location structure, it is used to produce the parser error messages */
struct Token *root,*current; /* This is the parsed token tree, it is collected by the parser and used later to produce the output code */

void yyerror(char *s, ...)
{
  va_list ap;
  va_start(ap, s);

  fprintf(stderr,"error: line: ");

  if(yylloc.first_line) {
      fprintf(stderr, "%d.%d-%d.%d ", yylloc.first_line, yylloc.first_column,yylloc.last_line, yylloc.last_column);
  }
  vfprintf(stderr, s, ap);
  fprintf(stderr, "\n");
}

void lyyerror(YYLTYPE t, char *s, ...)
{
  va_list ap;
  va_start(ap, s);

  fprintf(stderr,"error: line: ");

  if(yylloc.first_line) {
      fprintf(stderr, "%d.%d - %d.%d ", yylloc.first_line, yylloc.first_column,yylloc.last_line, yylloc.last_column);
  }
  vfprintf(stderr, s, ap);
  fprintf(stderr, "\n");
  va_end(ap);
}

int yywrap()
{
  return 1;
}

%}

%locations


The above C code section contain error parts, see the yacc/bison documentation or check a book on the subject for details. We will focus on the next part, where the actual parsing definitions are placed.

%union {
    int type;
    char *name;
}

%token <type> MESSAGE
%token <type> BYTE
%token <type> WORD
%token <type> DWORD
%token <type> QWORD
%token <name> NAME
%token END

%%
message: /* empty */
   |
   message data;

data:  byte | word | dword | qword | end;

message: MESSAGE NAME { root = current = create($1,$2); };
 | NAME { lyyerror(@1,"'%s' undeclared identifier",$1); /*YYABORT*/;};
 | error '\n'

byte: BYTE NAME { current = current->next = create($1,$2); };
 | NAME { lyyerror(@1,"'%s' undeclared identifier",$1); /*YYABORT*/;};
 | error '\n'

word: WORD NAME { current = current->next = create($1,$2);};
 | NAME {lyyerror(@1,"'%s' undeclared identifier",$1); /*YYABORT*/;};
 | error '\n'

dword: DWORD NAME { current = current->next = create($1,$2);};
 | NAME {lyyerror(@1,"'%s' found where d was exspected",$1); /*YYABORT*/;};
 | error '\n'

qword: QWORD NAME { current = current->next = create($1,$2);};
 | NAME {lyyerror(@1,"'%s' undeclared identifier",$1); /*YYABORT*/;};
 | error '\n'

end: END { current = NULL;};
%%


The above yacc code defines the token type, the input as it is read fom yyin to be either a int, in the case of token type or a char* in the case of token names.  These are used to create a token table (a simple linked list) from the files token.h and token.c

The next part, all the %token <foo> bar, definitions defines the tokens. Finally, the %% message: section defines the NTL language BNF.

Basically, what the BNF does it defines that a message must contain a set of data, taht can be of the types byte, word, dword, qword or end.

Then, each of the token types are assigned some code, which in a correctly formatted scenario feeds a token generator, a simple c linked list, with the token type and name. If there is an error in the syntax this will be issued to the user and the parser will read to the next newline.

The token linked list

Heres a listing of the token linked list structure for creating the simple linked list. First the header then the implementation file

#ifndef token_h_
#define token_h_

struct Token {

    int type;
    char *name;
    struct Token *next;
} *root,*current;

struct Token *create(int type, char *name);


#endif // token_h


The above defines a token structure, used to generate code from.

#include <stdlib.h>
#include <string.h>
#include "token.h"

struct Token *create(int type, char *name)

{
    struct Token *t = malloc(sizeof(struct Token));
    memset(t,0x00,sizeof(struct Token));
    t->type = type;
    t->name = name;
    return t;
}

The above defines a function that creates and assigns the token type and name to a simple linked list. This list is used to generate the code from.

The code generation for this project is also fairly simple. The principle is that a single function generates the code for each section. This function is then used from the main program as a function pointer, providing the polymorphic ability for generating code.

The benefit of using function pointers is that to generate a new output all you have to do is write a function for the generation, and register this function. The other parts of the program stays the same.

#ifndef C_GENERATOR_H
#define C_GENERATOR_H

enum OUTPUT_TYPE {
    GENERATE_NONE = 0x00,
    GENERATE_TREE,
    GENERATE_C,
    GENERATE_LUA,
    GENERATE_MAX = GENERATE_LUA,
};

void c_generator(char *filename);
void tree_generator(char *filename);
void lua_generator(char *filename);
typedef void (*generator)(char *);

#endif /* C_GENERATOR_H */


The above defines a set of functions, one for each output type, and a set of constants for the corresponding function.

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include "token.h"
#include "file.h"

void tree_generator(char *outfile) {

    outfile = strcat(outfile,".tree");
    fprintf(stdout,"Generating: %s\n",outfile);

    struct Token *next;
    fprintf(stdout,"Generating: %s\n",outfile);
    fprintf(stdout,"Token: %s Type: %d\n",root->name,root->type);
    for(next = root->next; next!=NULL; next = next->next) {
    fprintf(stdout,"\t |-- Type: %d - Token: %s\n",next->type,next->name);
    }
}

void c_generator(char *outfile)
{
    struct Token *next;

    outfile = strcat(outfile,".h");
    fprintf(stdout,"Generating: %s\n",outfile);

    char *type_words[] =  {"","struct","uint8_t","uint16_t","uint32_t","uint64_t"};
    char *hton_functions[] = {"","","","htons","htonl","undefined_htoll"};
    char *ntoh_functions[] = {"","","","ntohs","ntohl","undefined_ntohll"};
    FILE *ntlout = file_open(outfile,"w","couldn't open temp for writting\n");

    fprintf(ntlout,"#ifndef %s_h\n",root->name);
    fprintf(ntlout,"#define %s_h\n\n",root->name);

    fprintf(ntlout,"struct %s {\n",root->name);
    for(next = root->next;next!=NULL;next = next->next) {
    fprintf(ntlout,"\t%s %s\n",type_words[next->type],next->name);
    }
    fprintf(ntlout,"\n");
    fprintf(ntlout,"\tvoid hton();\n");
    fprintf(ntlout,"\tvoid ntoh();\n");
    fprintf(ntlout,"};\n\n");

    fprintf(ntlout,"void %s::hton()\n{\n",root->name);
    for(next = root->next;next!=NULL;next = next->next) {
    fprintf(ntlout,"\t%s = %s(%s)\n",next->name,hton_functions[next->type],next->name);
    }
    fprintf(ntlout,"}\n\n");
   
    fprintf(ntlout,"void %s::ntoh()\n{\n",root->name);
    for(next = root->next;next!=NULL;next = next->next) {
    fprintf(ntlout,"\t%s = %s(%s)\n",next->name,ntoh_functions[next->type],next->name);
    }
    fprintf(ntlout,"}\n\n");

    fprintf(ntlout,"#endif // %s_h\n",root->name);

    fclose(ntlout);
}

void lua_generator(char *outfile) {
    outfile = strcat(outfile,".lua");
    fprintf(stdout,"Generating: %s\n",outfile);
}


Disadvantages

Lets face it, writing code that writes code has both its advantages and disadvantages.
The advantages are many, and discussed deeply at various resources like: "The Pragmatic Programmer" or "The Art Of Unix Programming". The Disadvantages are usually not addressed as they're not the key selling point, and their consequences are usually ignored. Remember:

"If you write code that writes bad code, there's no end to what you can't generate!"

If you just want to know how jump to the code section. If you want to know why, the following section lists some of the pitfalls I've met during my travels in professional programmer land.

The disadvantages I personally have experienced with code generation, have all been in the same area.
  1. The outputted code was impossible to debug and use due to bad code design.
  2. The input was so advanced that it was a programming language on it's own.
  3. Lack of tokenization after the lexical analysis.
  4. Choosing the wrong tool for the job.
Well, the first item leads to the kind of code you just want to, for the lack of a better word, refactor. Bad code should be removed immediately as it's consequences is your projects greatest risk. The first item is also related heavily to the second item.

The second leads to your project having to educate its programmers to the specific code generation language. This is expensive as you cannot hire an expert. You'll have to, as a project or company, educate your own experts.

That will be hard as the experts your project educate cannot use the expertise elsewhere, and this might cause a motivational issue in your project. Plus, your project will have to maintain the full infrastructure related to a programming language like: usage examples, and documentation. Expensive.

Item three is a common mistake, a code generation step that is often overlooked in the process of producing the code generator output. This may be due to lack of experience, or, even worse, due to a poor programming work environment. The latter of these is the worst as the environment enforces a fast process with out any consideration for the side effects. A side effect could be porting of the generated code to a new platform, or documentation generation in a different format.

The fourth item is a common mistake in many technical matters. Choosing a tool to preform a specific task is often not trivial. But in many cases some of the new parsers etc. are often misused due to lack of understanding in the problem domain. One of the things I have seen is the usage of Apache ant and not make.

This is not a criticism of either Apache ant or make. I'm certain that they both have their specific problem to solve. Nevertheless, I believe that the purpose of Apache ant can be solved by make, but that is just my personal opinion, I honestly believe in the approach taken in the "The Art Of Unix Programming" book. Where the suggested solution is to make use of the tools available to you already, and creating only the smallest possible solution to perform the task needed.

Re-sizing the C drive of your vmware installation.

1 Re-sizing the VM disk
1.1 Power oww your virtual XP installation
1.2 Select VM menu item, and press settings in the drop down list
1.3 Select the Hard Disk entry, and press the utilities button in the lower right corner of the dialog
1.4 Select Expand from the utility list, set the desired size in the dialog (I went for 100 GB)
1.5 Wait until the virtual machine has expanded the drive size, then click save

2 Re-sizing the virtual XP disk
2.1 install a partition tool on your machine, I'm using EASEUS partition magic professional
2.2 Follow your tool's re-size procedure (Mine is listed below)
2.2.1 Select the C drive and click the re-size button.
2.2.2 Drag the allocated space pointer to the desired size (100GB)
2.2.3 Press apply and close the partition tool
2.2 Reboot your virtual XP image

3 Check new partition size
3.1 After rebooting your virtual XP image, press "windows key" + e
3.2 Right click the Local Disk(C:), and select properties