#!/usr/bin/env python

"""Regenerate C++ mapping classes"""

#---------------------------------------------------------------------------#
#                                                                           #
#---------------------------------------------------------------------------#

def regenDebugMapper( basename ):
    """
    Debug Mapper - maps ioctl numbers to names, e.g. 0x4x5a -> SIOCGIWNAME
    """

    result = os.popen( 'find /usr/include -name "*.h" |xargs -- grep -h SIOC|grep 0x' ).readlines()

    try:
        tablehfile = file( basename+".h", "w" )
    except:
        tablehfile = sys.stdout

    try:
        tablecfile = file( basename+".cpp", "w" )
    except:
        tablecfile = sys.stdout

    print >>tablehfile,"""
/*
 * debug value mapper - generated by %s - (C) Michael 'Mickey' Lauer <mickey@vanille.de>
 */

#ifndef DEBUGMAPPER_H
#define DEBUGMAPPER_H

#include <qstring.h>
#include <qintdict.h>

typedef QIntDict<QString> IntStringMap;

class DebugMapper
{
  public:
    DebugMapper();
    ~DebugMapper();

    const QString& map( int value ) const;
  private:
    IntStringMap _map;
};

#endif
""" % sys.argv[0]

    print >>tablecfile,"""
/*
 * debug value mapper - generated by %s - (C) Michael 'Mickey' Lauer <mickey@vanille.de>
 */

#include <opie2/odebug.h>

#include "%s"

DebugMapper::DebugMapper()
{
    odebug << "DebugMapper::DebugMapper()" << oendl;

""" % ( sys.argv[0], tablehfile.name )

    for line in result:
        l = line.split()
        if not l[0].startswith( "#define" ) or not l[2].startswith( "0x" ):
            print >>sys.stderr, "can't parse line: %s" % l
            continue
        print >>tablecfile, "    _map.insert( %s, new QString(\"%s\") );" % ( l[2], l[1] )


    print >>tablecfile,"""
};


DebugMapper::~DebugMapper()
{
    odebug << "DebugMapper::~DebugMapper()" << oendl;
}


const QString& DebugMapper::map( int value ) const
{
    QString* result = _map[ value ];

    if ( !result )
    {
        owarn << "DebugMapper::map() - value " << value << " is not found." << oendl;
        return QString::null;
    }
    else
    {
        return *result;
    }
}

"""

#---------------------------------------------------------------------------#
#                                                                           #
#---------------------------------------------------------------------------#

def regenManufacturerDB( basename ):

    try:
        h = file( basename+".h", "w" )
    except:
        h = sys.stdout

    try:
        cpp = file( basename+".cpp", "w" )
    except:
        cpp = sys.stdout

    print >>h,"""
#ifndef OMANUFACTURERDB_H
#define OMANUFACTURERDB_H

#include <qmap.h>

/**
 * @brief A Ethernet card vendor database.
 *
 * This class encapsulates the lookup of Ethernet vendor given a
 * certain Mac Address. Only the first three bytes define the vendor.
 */
class OManufacturerDB
{
  public:
    /**
     * @returns the one-and-only @ref OManufacturerDB instance.
     */
    static OManufacturerDB* instance();
    /**
     * @returns the short manufacturer string given a @a macaddr.
     */
    const QString& lookup( const QString& macaddr ) const;
    /**
     * @returns the enhanced manufacturer string given a @a macaddr.
     */
    const QString& lookupExt( const QString& macaddr ) const;

  protected:
    OManufacturerDB();
    virtual ~OManufacturerDB();

  private:
    QMap<QString, QString> manufacturers;
    QMap<QString, QString> manufacturersExt;
    static OManufacturerDB* _instance;
};

#endif
"""

    print >>cpp,"""
#include "%s.h"

/* OPIE CORE */
#include <opie2/odebug.h>

/* QT */
#include <qapplication.h>
#include <qstring.h>

#define OPIE_IMPROVE_GUI_LATENCY 1

OManufacturerDB* OManufacturerDB::_instance = 0;

OManufacturerDB* OManufacturerDB::instance()
{
    if ( !OManufacturerDB::_instance )
    {
        odebug << "OManufacturerDB::instance(): creating OManufacturerDB..." << oendl;
       _instance = new OManufacturerDB();
    }
    return _instance;
}


OManufacturerDB::OManufacturerDB()
{
""" % basename

    count = 0
    for line in sys.stdin:
        if line[0] == "#":  # skip comments
            continue
        #print line.strip()
        entries = line.strip().split()
        #print "number of entries =", len( entries )
        #print entries
        if len( entries ) < 2:
            continue
        elif len( entries ) == 2:
            count += 1
            print "2-line detected."
            print >>cpp, '    manufacturers.insert( "%s", "%s" );' % ( entries[0], entries[1] )
            print >>cpp, '    manufacturersExt.insert( "%s", "%s" );' % ( entries[0], entries[1] )
        elif len( entries ) > 2:
            count += 1
            print "3-line detected."
            print >>cpp, '    manufacturers.insert( "%s", "%s" );' % ( entries[0], entries[1] )
            print >>cpp, '    manufacturersExt.insert( "%s", "%s" );' % ( entries[0], "_".join( entries[3:] ) )
        else:
            assert( false )
        if not (count % 1000):
            print >>cpp,"""
#ifdef OPIE_IMPROVE_GUI_LATENCY
    if (qApp) qApp->processEvents();
#endif
"""
    print "successfully parsed", count, "manufacturer lines"
    print >>cpp,"""
}


OManufacturerDB::~OManufacturerDB()
{
}


const QString& OManufacturerDB::lookup( const QString& macaddr ) const
{
    return manufacturers[macaddr.upper().left(8)];
}


const QString& OManufacturerDB::lookupExt( const QString& macaddr ) const
{
    QMap<QString,QString>::ConstIterator it = manufacturersExt.find( macaddr.upper().left(8) );
    return it == manufacturersExt.end() ? lookup( macaddr ) : *it;
}
"""

#---------------------------------------------------------------------------#
#                                                                           #
#---------------------------------------------------------------------------#

#---------------------------------------------------------------------------#
#                                                                           #
#---------------------------------------------------------------------------#

#---------------------------------------------------------------------------#
#                                                                           #
#---------------------------------------------------------------------------#

import sys
import os
import copy

if __name__ == "__main__":
    if len( sys.argv ) != 3:
        print """
Usage: %s <table> <basename>

Available tables: %s
""" % ( sys.argv[0], [ str(k)[5:] for k in copy.copy( locals() ) if k.startswith( "regen" ) ] )
        sys.exit( -1 )

    try:
        func = locals()["regen%s" % sys.argv[1]]
    except KeyError:
        print "Table '%s' unknown." % sys.argv[1]
        sys.exit( -1 )
    else:
        func( sys.argv[2] )
        sys.exit( 0 )