#! /usr/bin/env python
'''
Author: Lu Xu
Generate the header files including all the declarations of test functions,
a array of functions, a array of function names and the number of functions.
'''
import os

def readfuncs(filename):
    '''
    read files and find test function declarations or definitions.
    return a list of sorted function names.
    FIXME: invoke linux command here, so it is not going to work under Windows.
    '''
    # TODO: change to platform-independent
    regex = 'int +test[1-9|a-z|A-Z|_]* *\( *\)*'
    command = "awk '/%s/{print$2}' %s|sort|awk -F'(' '{print $1}'"  % (regex, filename)
    return os.popen(command).read().split()

def gentest(funcs):
    '''
    generate test header file
    '''
    with open(testh, 'w') as header:
        header.write(
'''/**
 * This file is automatically generated by GenerateTest.py, collecting function
 * information from source files.
 *
 * If you want to change the content of this file, go to GenerateTest.py and
 * modify the script. Or you can maintain this file by yourself after you delete
 * the related lines in the makefile.
 */

#ifndef _TESTDECLARATION_H_
#define _TESTDECLARATION_H_

#define PASSED 0
#define FAILED 1

/* declarations of testfunctions */
%s \nvoid testall();

/* define the array of all test functions */
#define FUNC_ARRAY { %s \\\n}

/* define the array of function names */
#define NAME_ARRAY { %s \\\n}

/* define the number of functions */
#define FUNC_COUNT %d

#endif
''' %  (''.join(['int %s();\n' % func for func in funcs]),
        ''.join(['\\\n\t%s,' % func for func in funcs])[:-1],
        ''.join(['\\\n\t\"%s\",' % func for func in funcs])[:-1],
        len(funcs)))

def main():
    '''
    If the header file exists and the functions in it are the same as those in
    source files, then it is up to date. Otherwise update the header file
    '''
    funclist = readfuncs('`ls test*`')
    if os.path.exists('Test.h') and funclist == readfuncs('Test.h'):
        print 'Test header file is up to date.'
    else:
        gentest(funclist)
        print 'Test header file is (re)generated.'

if __name__ == '__main__':
    main()
