Hello there,

Great forum, I don't know how I didn't find it before.
So my problem is, I'm trying to write a C version of perl's pack function.

It's not a homework or something, I was trying to create an ICQ client, and found myself over and over again manually creating the packets.
So I thought in creating a pack function, which would make my life easier.

Anyway, I wrote one, but I feel it can be really improved.
And here's where I need some help - improving this code.
Any advice will really help.
So I wont post all the code, because it's pretty useless to do so.
I removed similar cases and some error handling, to make the code easier to be read.

Code:

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

char *pack( char *format, ... )
{
   va_list parameters;
   char *buffer = NULL;
   char *pBuffer = buffer;
   char *pFormat = format;
   long lSize = 0;
   char *tmp;
   
   va_start( parameters, format );
   while( *pFormat != '\0' )
     {
        if( *pFormat == 'C' )
          {
             /*
              * signed char
              */
             signed char c;
             c = va_arg( parameters, int );
             
             ++lSize;
             if( ( tmp = realloc( buffer, lSize ) ) == NULL )
               {
                  perror( "realloc: " );
                  free( buffer );
                  return NULL;
               }
             else
               {
                  buffer = tmp;
                  pBuffer = buffer+lSize-1;
                  *pBuffer = c;
               }
          }
        else if( *pFormat == 'c' )
          {
             /*
              * unsigned char
              */
             unsigned char c;
             c = va_arg( parameters, int );
             
             ++lSize;
             if( ( tmp = realloc( buffer, lSize ) ) == NULL )
               {
                  perror( "realloc: " );
                  free( buffer );
                  return NULL;
               }
             else
               {
                  buffer = tmp;
                  pBuffer = buffer+lSize-1;
                  *pBuffer = c;
               }
             
          }
        else if( *pFormat == 'n' )
          {
             /*
              * unsigned short, 16bits, big endian
              */
             unsigned short n = va_arg( parameters, int );
             long lComplement = 2;
             
             lSize += lComplement;
             if( ( tmp = realloc( buffer, lSize ) ) == NULL )
               {
                  perror( "realloc: " );
                  free( buffer );
                  return NULL;
               }
             else
               {
                  buffer = tmp;
                  pBuffer = buffer+lSize-lComplement;
                  *pBuffer = n >> 8;
                  ++pBuffer;
                  *pBuffer = n & 0x00ff;
               }
          }
        else if( *pFormat == 'v' )
          {
             /*
              * unsigned short, 16 bits, little endian
              */
             unsigned short n = va_arg( parameters, int );
             long lComplement = 2;
             
             lSize += lComplement;
             if( ( tmp = realloc( buffer, lSize ) ) == NULL )
               {
                  perror( "realloc: " );
                  free( buffer );
                  return NULL;
               }
             else
               {
                  buffer = tmp;
                  pBuffer = buffer+lSize-lComplement;
                  *pBuffer = n & 0x00ff;
                  ++pBuffer;
                  *pBuffer = n >> 8;
               }
             
          }
        else if( *pFormat == 'a' )
          {
             /*
              * NUL padded string
              */
             char *s = va_arg( parameters, char* );
             long lComplement = strlen( s );
             
             lSize += lComplement;
             if( ( tmp = realloc( buffer, lSize ) ) == NULL )
               {
                  perror( "realloc: " );
                  free( buffer );
                  return NULL;
               }
             else
               {
                  buffer = tmp;
                  pBuffer = buffer+lSize-lComplement;
                  memcpy( pBuffer, s, lComplement );
               }
          }
        else if( *pFormat == 'A' )
          {
             /*
              * Space padded string
              */
             char *s = va_arg( parameters, char* );
             char *pString = s;
             long lComplement = 0;
             
             while( *pString != ' ' )
               {
                  ++lComplement;
                  ++pString;
               }
             lSize += lComplement;
             if( ( tmp = realloc( buffer, lSize ) ) == NULL )
               {
                  perror( "realloc: " );
                  free( buffer );
                  return NULL;
               }
             else
               {
                  buffer = tmp;
                  pBuffer = buffer+lSize-lComplement;
                  memcpy( pBuffer, s, lComplement );
               }
          }
        else if( *pFormat == 'N' )
          {
             /*
              * unsigned long, 32bits, big endian
              */
             //0x12345678
             unsigned long n = va_arg( parameters, unsigned long );
             long lComplement = 4;
             
             lSize += lComplement;
             if( ( tmp = realloc( buffer, lSize ) ) == NULL )
               {
                  perror( "realloc: " );
                  free( buffer );
                  return NULL;
               }
             else
               {
                  buffer = tmp;
                  pBuffer = buffer+lSize-lComplement;
                  *pBuffer = n >> 24;
                  ++pBuffer;
                  *pBuffer = ( ( n & 0xff0000) >> 16 );
                  ++pBuffer;
                  *pBuffer = ( ( n & 0xff00 ) >> 8 );
                  ++pBuffer;
                  *pBuffer = n & 0xff;
               }
          }
        
        ++pFormat;
     }
   
   /*
    * before returning, add a NUL char at the end
    */
   ++lSize;
   tmp = realloc( buffer, lSize );
   if( tmp == NULL )
     {
        perror( "realloc: " );
        return NULL;
     }
   else
     {
        buffer = tmp;
        pBuffer = buffer+lSize-1;
        *pBuffer = '\0';
     }
   va_end( parameters );
   return buffer;
}
Any advice will be appreciated.
Thanks in advance, and have a nice day.

PS: I'm sorry the code alignment isn't that good, I'll try to do better next time.