/*
Copyright (C) 2006 Evan Teran
                   eteran@alum.rit.edu

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "FunctionDBPlugin.h"
#include "FunctionDB.h"
#include "Debugger.h"

static const Function funcs[] = {

	// ctype functions
	{ "isalnum", FunctionInfo('c') },
	{ "isalpha", FunctionInfo('c') },
	{ "iscntrl", FunctionInfo('c') },
	{ "isdigit", FunctionInfo('c') },
	{ "isgraph", FunctionInfo('c') },
	{ "islower", FunctionInfo('c') },
	{ "isprint", FunctionInfo('c') },
	{ "ispunct", FunctionInfo('c') },
	{ "isspace", FunctionInfo('c') },
	{ "isupper", FunctionInfo('c') },
	{ "isxdigit", FunctionInfo('c') },
	{ "tolower", FunctionInfo('c') },
	{ "toupper", FunctionInfo('c') },
	
	// errno functions
	{ "__errno_location", FunctionInfo() },
	
	// setjmp functions
	{ "setjmp", FunctionInfo('p') },
	{ "longjmp", FunctionInfo('p', 'i') },
	
	// signal functions
	{ "signal", FunctionInfo('i', 'p') },
	{ "raise", FunctionInfo('i') },
	
	// stdio functions
	{ "fputc", FunctionInfo('c', 'p') },
	{ "putchar", FunctionInfo('c') },
	{ "printf", FunctionInfo('f') },
	{ "fputs", FunctionInfo('s', 'p') },
	{ "puts", FunctionInfo('s') },
	{ "fopen", FunctionInfo('s', 'p') },
	{ "fclose", FunctionInfo('p') },
	{ "fwrite", FunctionInfo('p', 'u', 'u', 'p') },
	{ "fread", FunctionInfo('p', 'u', 'u', 'p') },
	{ "remove", FunctionInfo('s') },
	{ "sprintf", FunctionInfo('p', 's') },
	// putc
	// vsprintf
	// vfprintf
	// fprintf
	// clearerr
	// getchar
	// gets
	// feof
	// ferror
	// setbuf
	// setvbuf
	// setlinebuf
	// setbuffer
	// perror
	// fflush
	// fseek
	// rewind
	// fgets
	// ftell
	// tmpnam
	// tmpfile
	// snprintf
	// scanf
	// fscanf
	// sscanf
	// vscanf
	// vfscanf
	// vsscanf
	// fsetpos
	// fgetpos
	// fileno
	// freopen
	// ungetc
	// rename

	// stdlib functions
	{ "malloc", FunctionInfo('u') },
	{ "free", FunctionInfo('p') },
	{ "realloc", FunctionInfo('p', 'u') },
	{ "calloc", FunctionInfo('u', 'u') },
	{ "getenv", FunctionInfo('s') },
	{ "exit", FunctionInfo('i') },
	{ "system", FunctionInfo('s') },
	// abort
	// abs
	// div
	// ldiv
	// mbtowc
	// mblen
	// qsort
	// labs
	// strtoul
	// strtol
	// atoi
	// atol
	// atof
	// strtod
	// rand
	// srand
	// atexit
	// bsearch
	// strtof
	// mbstowcs
	// wcstombs
	// wctomb

	// string functions
	{ "memchr", FunctionInfo('p', 'c', 'u') },
	{ "memcmp", FunctionInfo('p', 'p', 'u') },
	{ "memcpy", FunctionInfo('p', 'p', 'u') },
	{ "memmove", FunctionInfo('p', 'p', 'u') },
	{ "memset", FunctionInfo('p', 'c', 'u') },
	{ "strcat", FunctionInfo('s', 's') },
	{ "strchr", FunctionInfo('s', 'c') },
	{ "strcmp", FunctionInfo('s', 's') },
	{ "strcoll", FunctionInfo('s', 's') },
	{ "strcpy", FunctionInfo('p', 's') },
	{ "strcspn", FunctionInfo('s', 's') },
	{ "strerror", FunctionInfo('i') },
	{ "strlen", FunctionInfo('s') },
	{ "strncat", FunctionInfo('s', 's', 'u') },
	{ "strncmp", FunctionInfo('s', 's', 'u') },
	{ "strncpy", FunctionInfo('p', 's', 'u') },
	{ "strpbrk", FunctionInfo('s', 's') },
	{ "strrchr", FunctionInfo('s', 'c') },
	{ "strspn", FunctionInfo('s', 's') },
	{ "strstr", FunctionInfo('s', 's') },
	{ "strtok", FunctionInfo('s', 's') },
	{ "strxfrm", FunctionInfo('p', 's', 'u') },
	{ "strdup", FunctionInfo('s') },
	{ "strndup", FunctionInfo('s', 'u') },

	// locale functions
	{ "setlocale", FunctionInfo('i', 's') },

	// misc other functions
	{ "__cxa_atexit", FunctionInfo('p', 'p', 'p') },	
	{ "opendir", FunctionInfo('s') },
	{ "sbrk", FunctionInfo('p') },	
	{ "__libc_start_main", FunctionInfo('p', 'i', 'p', 'p', 'p', 'p', 'p') },
	{ "getpagesize", FunctionInfo() },
	{ "ioctl", FunctionInfo('i', 'i', 'p') },
	{ "isatty", FunctionInfo('i') },
	{ "poll", FunctionInfo('p', 'u', 'i') },
	{ "setenv", FunctionInfo('s', 's', 'i') },
	{ "bindtextdomain", FunctionInfo('s', 's') },
	{ "textdomain", FunctionInfo('s') },
	{ "getopt", FunctionInfo('i', 'p', 's') },
	{ "getopt_long", FunctionInfo('i', 'p', 's', 'p', 'p') },
};

static const Function *funcs_begin	= funcs;
static const Function *funcs_end	= funcs + (sizeof(funcs) / sizeof(funcs[0]));

//------------------------------------------------------------------------------
// Name: FunctionDBPLugin()
// Desc: 
//------------------------------------------------------------------------------
const FunctionInfo *FunctionDBPLugin::find(const QString &name) const {
	const FunctionInfo *ret = 0;
	const Function *const it = qFind(funcs_begin, funcs_end, name);
	if(it != funcs_end) {
		const FunctionInfo *const info = &it->f;
		if(info != 0) {
			ret = info;
		}
	}
	return ret;
}

//------------------------------------------------------------------------------
// Name: FunctionDBPLugin()
// Desc: 
//------------------------------------------------------------------------------
FunctionDBPLugin::FunctionDBPLugin() {
	FunctionDB::RegisterFunctionDBInstance(this);
	edb::v1::log("[Function Database] loaded with %d function definitions.", sizeof(funcs) / sizeof(funcs[0]));
}

//------------------------------------------------------------------------------
// Name: menu(QWidget *parent)
// Desc: 
//------------------------------------------------------------------------------
QMenu *FunctionDBPLugin::menu(QWidget *parent) {
	Q_UNUSED(parent);
	return 0;
}

Q_EXPORT_PLUGIN2(FunctionDBPLugin, FunctionDBPLugin)
